summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2013-06-28 12:59:40 +0200
committerOndřej Surý <ondrej@sury.org>2013-06-28 12:59:40 +0200
commit124965832295a277b9ca6ae9fac4f45a74a36b2a (patch)
treef299e2335863f74e0be0707f84b85211baaf2d03
parent3d2d198c71a6b844b60fa9ef68801b66bba93361 (diff)
downloadknot-124965832295a277b9ca6ae9fac4f45a74a36b2a.tar.gz
New upstream version 1.3.0~rc3upstream/1.3.0_rc3
-rw-r--r--AUTHORS1
-rw-r--r--CodingStyle77
-rw-r--r--Doxy.page.h87
-rw-r--r--Doxyfile1638
-rw-r--r--Doxyfile.devel1634
-rw-r--r--INSTALL8
-rw-r--r--KNOWN_ISSUES16
-rw-r--r--Knot.config1
-rw-r--r--Knot.creator1
-rw-r--r--Knot.files282
-rw-r--r--Knot.includes13
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.in204
-rw-r--r--NEWS400
-rw-r--r--README115
-rw-r--r--RELNOTES355
-rw-r--r--THANKS37
-rw-r--r--aclocal.m4599
-rwxr-xr-xar-lib2
-rw-r--r--astylerc12
-rwxr-xr-xcompile343
-rwxr-xr-xconfig.guess1021
-rwxr-xr-xconfig.sub482
-rwxr-xr-xconfigure3279
-rw-r--r--configure.ac211
-rwxr-xr-xdepcomp89
-rw-r--r--doc/.gitignore17
-rw-r--r--doc/Makefile.am22
-rw-r--r--doc/Makefile.in63
-rw-r--r--doc/configuration.texi73
-rw-r--r--doc/installation.texi81
-rw-r--r--doc/introduction.texi21
-rw-r--r--doc/knot.info2709
-rw-r--r--doc/knot.texi144
-rwxr-xr-xdoc/mdate-sh15
-rw-r--r--doc/migration.texi8
-rw-r--r--doc/reference.texi322
-rw-r--r--doc/requirements.texi8
-rw-r--r--doc/running.texi162
-rw-r--r--doc/stamp-vti4
-rw-r--r--doc/texinfo.tex361
-rw-r--r--doc/troubleshooting.texi34
-rw-r--r--doc/version.texi4
-rwxr-xr-xinstall-sh14
-rw-r--r--knot.sample.conf.in18
-rw-r--r--ltmain.sh97
-rw-r--r--m4/ax_check_compile_flag.m472
-rw-r--r--m4/ax_check_compiler_flags.m478
-rw-r--r--m4/ax_ext.m412
-rw-r--r--m4/ax_gcc_x86_cpuid.m42
-rw-r--r--m4/ax_recvmmsg.m48
-rw-r--r--m4/libtool.m455
-rw-r--r--m4/visibility.m452
-rw-r--r--man/Makefile.am2
-rw-r--r--man/Makefile.in609
-rw-r--r--man/kdig.1195
-rw-r--r--man/kdig.1.in195
-rw-r--r--man/khost.189
-rw-r--r--man/khost.1.in89
-rw-r--r--man/knot.conf.5 (renamed from src/knot.conf.5)159
-rw-r--r--man/knot.conf.5.in383
-rw-r--r--man/knotc.8 (renamed from src/knotc.8)26
-rw-r--r--man/knotc.8.in101
-rw-r--r--man/knotd.8 (renamed from src/knotd.8)2
-rw-r--r--man/knotd.8.in35
-rw-r--r--man/knsupdate.1147
-rw-r--r--man/knsupdate.1.in147
-rwxr-xr-xmissing99
-rwxr-xr-xresource.sh8
-rw-r--r--samples/Makefile.am12
-rw-r--r--samples/Makefile.in54
-rw-r--r--samples/bogus25.com.zone16
-rw-r--r--samples/example.com.zone79
-rw-r--r--samples/example.com.zone.signed1686
-rw-r--r--samples/example.com.zone.signed.nsec3690
-rw-r--r--samples/knot.full.conf146
-rw-r--r--samples/knot.keys.conf10
-rw-r--r--samples/knot.min.conf30
-rw-r--r--samples/knot.sample.conf.in10
-rwxr-xr-xscripts/parse_dump.py145
-rwxr-xr-xscripts/pcap2dnsp.py17
-rw-r--r--scripts/urcu-tls-compat.patch1495
-rw-r--r--src/Makefile.am425
-rw-r--r--src/Makefile.in3303
-rw-r--r--src/common/LICENSE.txt29
-rw-r--r--src/common/acl.c25
-rw-r--r--src/common/atomic.h141
-rw-r--r--src/common/base32hex.c102
-rw-r--r--src/common/base32hex.h30
-rw-r--r--src/common/base64.c94
-rw-r--r--src/common/base64.h30
-rw-r--r--src/common/dSFMT-params.h4
-rw-r--r--src/common/dSFMT.c32
-rw-r--r--src/common/dSFMT.h14
-rw-r--r--src/common/descriptor.c291
-rw-r--r--src/common/descriptor.h252
-rw-r--r--src/common/errcode.c205
-rw-r--r--src/common/errcode.h187
-rw-r--r--src/common/errors.c4
-rw-r--r--src/common/evqueue.c3
-rw-r--r--src/common/evsched.c24
-rw-r--r--src/common/fdset.c27
-rw-r--r--src/common/fdset.h1
-rw-r--r--src/common/fdset_epoll.c6
-rw-r--r--src/common/fdset_kqueue.c14
-rw-r--r--src/common/fdset_poll.c2
-rw-r--r--src/common/general-tree.c216
-rw-r--r--src/common/general-tree.h73
-rw-r--r--src/common/getline.c61
-rw-r--r--src/common/getline.h51
-rw-r--r--src/common/hattrie/ahtable.c656
-rw-r--r--src/common/hattrie/ahtable.h120
-rw-r--r--src/common/hattrie/hat-trie.c1070
-rw-r--r--src/common/hattrie/hat-trie.h97
-rw-r--r--src/common/hattrie/murmurhash3.c2
-rw-r--r--src/common/hattrie/murmurhash3.h1
-rw-r--r--src/common/heap.c12
-rw-r--r--src/common/heap.h2
-rw-r--r--src/common/latency.c198
-rw-r--r--src/common/latency.h116
-rw-r--r--src/common/libtap/README231
-rw-r--r--src/common/libtap/tap.c6
-rw-r--r--src/common/libtap/tap.h1
-rw-r--r--src/common/libtap/tap_unit.h1
-rw-r--r--src/common/lists.c19
-rw-r--r--src/common/lists.h1
-rw-r--r--src/common/log.c40
-rw-r--r--src/common/mempattern.c73
-rw-r--r--src/common/mempattern.h34
-rw-r--r--src/common/mempool.c330
-rw-r--r--src/common/mempool.h345
-rw-r--r--src/common/modified_tree.h292
-rw-r--r--src/common/print.c54
-rw-r--r--src/common/print.h67
-rw-r--r--src/common/prng.c29
-rw-r--r--src/common/ref.c1
-rw-r--r--src/common/slab/slab.c30
-rw-r--r--src/common/sockaddr.c78
-rw-r--r--src/common/sockaddr.h29
-rw-r--r--src/common/tree.h268
-rw-r--r--src/config.h.in155
-rw-r--r--src/knot.service13
-rw-r--r--src/knot.spec91
-rw-r--r--src/knot.sysconfig4
-rw-r--r--src/knot/common.h137
-rw-r--r--src/knot/conf/cf-lex.l80
-rw-r--r--src/knot/conf/cf-parse.y356
-rw-r--r--src/knot/conf/conf.c287
-rw-r--r--src/knot/conf/conf.h73
-rw-r--r--src/knot/conf/extra.c63
-rw-r--r--src/knot/conf/extra.h61
-rw-r--r--src/knot/conf/includes.c151
-rw-r--r--src/knot/conf/includes.h83
-rw-r--r--src/knot/conf/libknotd_la-cf-lex.c2889
-rw-r--r--src/knot/conf/libknotd_la-cf-parse.c3420
-rw-r--r--src/knot/conf/libknotd_la-cf-parse.h187
-rw-r--r--src/knot/conf/logconf.c4
-rw-r--r--src/knot/ctl/knotc_main.c945
-rw-r--r--src/knot/ctl/process.c139
-rw-r--r--src/knot/ctl/process.h37
-rw-r--r--src/knot/ctl/remote.c408
-rw-r--r--src/knot/ctl/remote.h27
-rw-r--r--src/knot/knot.h76
-rw-r--r--src/knot/main.c195
-rw-r--r--src/knot/other/debug.h4
-rw-r--r--src/knot/server/dthreads.c241
-rw-r--r--src/knot/server/dthreads.h40
-rw-r--r--src/knot/server/journal.c171
-rw-r--r--src/knot/server/journal.h14
-rw-r--r--src/knot/server/notify.c125
-rw-r--r--src/knot/server/notify.h30
-rw-r--r--src/knot/server/rrl.c70
-rw-r--r--src/knot/server/rrl.h6
-rw-r--r--src/knot/server/server.c621
-rw-r--r--src/knot/server/server.h89
-rw-r--r--src/knot/server/socket.c90
-rw-r--r--src/knot/server/socket.h5
-rw-r--r--src/knot/server/tcp-handler.c209
-rw-r--r--src/knot/server/udp-handler.c787
-rw-r--r--src/knot/server/udp-handler.h25
-rw-r--r--src/knot/server/xfr-handler.c2331
-rw-r--r--src/knot/server/xfr-handler.h100
-rw-r--r--src/knot/server/zones.c1812
-rw-r--r--src/knot/server/zones.h54
-rw-r--r--src/knot/stat/gatherer.h4
-rw-r--r--src/knot/stat/stat.c2
-rw-r--r--src/knot/zone/estimator.c262
-rw-r--r--src/knot/zone/estimator.h89
-rw-r--r--src/knot/zone/semantic-check.c1166
-rw-r--r--src/knot/zone/semantic-check.h37
-rw-r--r--src/knot/zone/zone-dump-text.c1099
-rw-r--r--src/knot/zone/zone-dump.c1160
-rw-r--r--src/knot/zone/zone-dump.h70
-rw-r--r--src/knot/zone/zone-load.c1886
-rw-r--r--src/knot/zone/zone-load.h70
-rw-r--r--src/libknot/binary.c (renamed from src/tests/libknot/libknot/zonedb_tests.c)54
-rw-r--r--src/libknot/binary.h61
-rw-r--r--src/libknot/common.h30
-rw-r--r--src/libknot/consts.c108
-rw-r--r--src/libknot/consts.h216
-rw-r--r--src/libknot/dname.c216
-rw-r--r--src/libknot/dname.h88
-rw-r--r--src/libknot/edns.c40
-rw-r--r--src/libknot/hash/cuckoo-hash-table.c1765
-rw-r--r--src/libknot/hash/cuckoo-hash-table.h334
-rw-r--r--src/libknot/hash/hash-functions.c241
-rw-r--r--src/libknot/hash/hash-functions.h85
-rw-r--r--src/libknot/hash/universal-system.c116
-rw-r--r--src/libknot/hash/universal-system.h109
-rw-r--r--src/libknot/libknot.h13
-rw-r--r--src/libknot/nameserver/chaos.c139
-rw-r--r--src/libknot/nameserver/chaos.h50
-rw-r--r--src/libknot/nameserver/name-server.c762
-rw-r--r--src/libknot/nameserver/name-server.h94
-rw-r--r--src/libknot/nsec3.c43
-rw-r--r--src/libknot/packet/packet.c316
-rw-r--r--src/libknot/packet/packet.h96
-rw-r--r--src/libknot/packet/query.c89
-rw-r--r--src/libknot/packet/query.h3
-rw-r--r--src/libknot/packet/response.c849
-rw-r--r--src/libknot/packet/response.h76
-rw-r--r--src/libknot/rdata.c873
-rw-r--r--src/libknot/rdata.h352
-rw-r--r--src/libknot/rrset-dump.c2090
-rw-r--r--src/libknot/rrset-dump.h109
-rw-r--r--src/libknot/rrset.c2836
-rw-r--r--src/libknot/rrset.h346
-rw-r--r--src/libknot/sign/bnutils.c44
-rw-r--r--src/libknot/sign/bnutils.h42
-rw-r--r--src/libknot/sign/dnssec.c756
-rw-r--r--src/libknot/sign/dnssec.h131
-rw-r--r--src/libknot/sign/key.c561
-rw-r--r--src/libknot/sign/key.h168
-rw-r--r--src/libknot/sign/sig0.c231
-rw-r--r--src/libknot/sign/sig0.h47
-rw-r--r--src/libknot/tsig-op.c352
-rw-r--r--src/libknot/tsig-op.h11
-rw-r--r--src/libknot/tsig.c572
-rw-r--r--src/libknot/tsig.h60
-rw-r--r--src/libknot/updates/changesets.c153
-rw-r--r--src/libknot/updates/changesets.h16
-rw-r--r--src/libknot/updates/ddns.c691
-rw-r--r--src/libknot/updates/ddns.h2
-rw-r--r--src/libknot/updates/xfr-in.c1470
-rw-r--r--src/libknot/updates/xfr-in.h15
-rw-r--r--src/libknot/util/debug.c172
-rw-r--r--src/libknot/util/debug.h23
-rw-r--r--src/libknot/util/descriptor.c601
-rw-r--r--src/libknot/util/descriptor.h371
-rw-r--r--src/libknot/util/endian.h (renamed from src/tests/libknot/realdata/libknot/packet_tests_realdata.h)28
-rw-r--r--src/libknot/util/tolower.c1
-rw-r--r--src/libknot/util/tolower.h2
-rw-r--r--src/libknot/util/utils.c54
-rw-r--r--src/libknot/util/utils.h94
-rw-r--r--src/libknot/util/wire.h37
-rw-r--r--src/libknot/zone/dname-table.c324
-rw-r--r--src/libknot/zone/dname-table.h176
-rw-r--r--src/libknot/zone/node.c343
-rw-r--r--src/libknot/zone/node.h19
-rw-r--r--src/libknot/zone/zone-contents.c1976
-rw-r--r--src/libknot/zone/zone-contents.h156
-rw-r--r--src/libknot/zone/zone-diff.c373
-rw-r--r--src/libknot/zone/zone-tree.c503
-rw-r--r--src/libknot/zone/zone-tree.h99
-rw-r--r--src/libknot/zone/zone.c25
-rw-r--r--src/libknot/zone/zone.h12
-rw-r--r--src/libknot/zone/zonedb.c151
-rw-r--r--src/libknot/zone/zonedb.h6
-rw-r--r--src/tests/Makefile.am74
-rw-r--r--src/tests/Makefile.in840
-rw-r--r--src/tests/README6
-rw-r--r--src/tests/common/acl_tests.c11
-rw-r--r--src/tests/common/base32hex_tests.c58
-rw-r--r--src/tests/common/base64_tests.c46
-rw-r--r--src/tests/common/descriptor_tests.c234
-rw-r--r--src/tests/common/descriptor_tests.h (renamed from src/tests/libknot/libknot/nsec3_tests.h)8
-rw-r--r--src/tests/common/events_tests.c1
-rw-r--r--src/tests/common/fdset_tests.c5
-rw-r--r--src/tests/common/hattrie_tests.c161
-rw-r--r--src/tests/common/hattrie_tests.h (renamed from src/tests/libknot/libknot/packet_tests.h)8
-rw-r--r--src/tests/common/skiplist_tests.c1
-rw-r--r--src/tests/common/slab_tests.c2
-rw-r--r--src/tests/knot/conf_tests.c18
-rw-r--r--src/tests/knot/dthreads_tests.c118
-rw-r--r--src/tests/knot/journal_tests.c40
-rw-r--r--src/tests/knot/rrl_tests.c40
-rw-r--r--src/tests/knot/server_tests.c2
-rw-r--r--src/tests/libknot/dname_tests.c84
-rw-r--r--src/tests/libknot/dname_tests.h (renamed from src/tests/libknot/libknot/dname_tests.h)7
-rw-r--r--src/tests/libknot/files/parsed_databin71188 -> 0 bytes
-rw-r--r--src/tests/libknot/files/parsed_data_queriesbin1325 -> 0 bytes
-rw-r--r--src/tests/libknot/files/raw_databin72100 -> 0 bytes
-rw-r--r--src/tests/libknot/files/raw_data_queriesbin1387 -> 0 bytes
-rw-r--r--src/tests/libknot/libknot/cuckoo_tests.c383
-rw-r--r--src/tests/libknot/libknot/dname_table_tests.c392
-rw-r--r--src/tests/libknot/libknot/dname_tests.c936
-rw-r--r--src/tests/libknot/libknot/edns_tests.c597
-rw-r--r--src/tests/libknot/libknot/node_tests.c344
-rw-r--r--src/tests/libknot/libknot/nsec3_tests.c251
-rw-r--r--src/tests/libknot/libknot/packet_tests.c427
-rw-r--r--src/tests/libknot/libknot/query_tests.c159
-rw-r--r--src/tests/libknot/libknot/query_tests.h25
-rw-r--r--src/tests/libknot/libknot/rdata_tests.c953
-rw-r--r--src/tests/libknot/libknot/rdata_tests.h52
-rw-r--r--src/tests/libknot/libknot/response_tests.c449
-rw-r--r--src/tests/libknot/libknot/response_tests.h25
-rw-r--r--src/tests/libknot/libknot/rrset_tests.c888
-rw-r--r--src/tests/libknot/libknot/tsig_tests.c686
-rw-r--r--src/tests/libknot/libknot/tsig_tests.h9
-rw-r--r--src/tests/libknot/libknot/zone_tests.c852
-rw-r--r--src/tests/libknot/libknot/zone_tree_tests.c758
-rw-r--r--src/tests/libknot/libknot/zone_tree_tests.h25
-rw-r--r--src/tests/libknot/libknot/zonedb_tests.h25
-rw-r--r--src/tests/libknot/realdata/files/parsed_databin4851 -> 0 bytes
-rw-r--r--src/tests/libknot/realdata/files/parsed_data_queriesbin1325 -> 0 bytes
-rw-r--r--src/tests/libknot/realdata/files/raw_databin4935 -> 0 bytes
-rw-r--r--src/tests/libknot/realdata/files/raw_data_queriesbin1387 -> 0 bytes
-rw-r--r--src/tests/libknot/realdata/libknot/dname_tests_realdata.c411
-rw-r--r--src/tests/libknot/realdata/libknot/dname_tests_realdata.h25
-rw-r--r--src/tests/libknot/realdata/libknot/edns_tests_realdata.c563
-rw-r--r--src/tests/libknot/realdata/libknot/node_tests_realdata.c385
-rw-r--r--src/tests/libknot/realdata/libknot/packet_tests_realdata.c678
-rw-r--r--src/tests/libknot/realdata/libknot/rdata_tests_realdata.c328
-rw-r--r--src/tests/libknot/realdata/libknot/rdata_tests_realdata.h53
-rw-r--r--src/tests/libknot/realdata/libknot/response_tests_realdata.c172
-rw-r--r--src/tests/libknot/realdata/libknot/response_tests_realdata.h25
-rw-r--r--src/tests/libknot/realdata/libknot/rrset_tests_realdata.c289
-rw-r--r--src/tests/libknot/realdata/libknot/zone_tests_realdata.c334
-rw-r--r--src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c44
-rw-r--r--src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h25
-rw-r--r--src/tests/libknot/realdata/libknot_tests_loader_realdata.c1297
-rw-r--r--src/tests/libknot/realdata/libknot_tests_loader_realdata.h179
-rw-r--r--src/tests/libknot/realdata/unittests_libknot_realdata.c93
-rw-r--r--src/tests/libknot/rrset_tests.c1467
-rw-r--r--src/tests/libknot/rrset_tests.h (renamed from src/tests/libknot/libknot/rrset_tests.h)0
-rw-r--r--src/tests/libknot/sign_tests.c249
-rw-r--r--src/tests/libknot/sign_tests.h (renamed from src/tests/libknot/libknot/zone_tests.h)9
-rw-r--r--src/tests/libknot/unittests_libknot.c92
-rw-r--r--src/tests/libknot/wire_tests.c113
-rw-r--r--src/tests/libknot/wire_tests.h (renamed from src/tests/libknot/realdata/libknot/zone_tests_realdata.h)9
-rw-r--r--src/tests/libknot/ztree_tests.c136
-rw-r--r--src/tests/libknot/ztree_tests.h (renamed from src/tests/libknot/libknot/node_tests.h)9
-rw-r--r--src/tests/unittests_main.c56
-rw-r--r--src/tests/xfr_tests.c23
-rw-r--r--src/tests/zscanner/zscanner_tests.c44
-rw-r--r--src/tests/zscanner/zscanner_tests.h (renamed from src/tests/libknot/realdata/libknot/node_tests_realdata.h)8
-rw-r--r--src/utils/common/exec.c671
-rw-r--r--src/utils/common/exec.h142
-rw-r--r--src/utils/common/msg.c (renamed from src/tests/libknot/libknot/dname_table_tests.h)30
-rw-r--r--src/utils/common/msg.h58
-rw-r--r--src/utils/common/netio.c465
-rw-r--r--src/utils/common/netio.h198
-rw-r--r--src/utils/common/params.c376
-rw-r--r--src/utils/common/params.h119
-rw-r--r--src/utils/common/resolv.c193
-rw-r--r--src/utils/common/resolv.h (renamed from src/tests/libknot/libknot/edns_tests.h)27
-rw-r--r--src/utils/common/token.c136
-rw-r--r--src/utils/common/token.h91
-rw-r--r--src/utils/dig/dig_exec.c732
-rw-r--r--src/utils/dig/dig_exec.h (renamed from src/tests/libknot/realdata/libknot/edns_tests_realdata.h)34
-rw-r--r--src/utils/dig/dig_main.c39
-rw-r--r--src/utils/dig/dig_params.c976
-rw-r--r--src/utils/dig/dig_params.h133
-rw-r--r--src/utils/host/host_main.c39
-rw-r--r--src/utils/host/host_params.c322
-rw-r--r--src/utils/host/host_params.h39
-rw-r--r--src/utils/nsupdate/nsupdate_exec.c929
-rw-r--r--src/utils/nsupdate/nsupdate_exec.h (renamed from src/tests/libknot/realdata/libknot/rrset_tests_realdata.h)33
-rw-r--r--src/utils/nsupdate/nsupdate_main.c39
-rw-r--r--src/utils/nsupdate/nsupdate_params.c267
-rw-r--r--src/utils/nsupdate/nsupdate_params.h91
-rw-r--r--src/zcompile/LICENSE30
-rw-r--r--src/zcompile/parser-descriptor.c545
-rw-r--r--src/zcompile/parser-descriptor.h279
-rw-r--r--src/zcompile/parser-util.c2488
-rw-r--r--src/zcompile/parser-util.h357
-rw-r--r--src/zcompile/tests/unittests_zp_main.c62
-rw-r--r--src/zcompile/tests/zcompile_tests.c425
-rw-r--r--src/zcompile/zcompile-error.c52
-rw-r--r--src/zcompile/zcompile-error.h90
-rw-r--r--src/zcompile/zcompile.c694
-rw-r--r--src/zcompile/zcompile.h201
-rw-r--r--src/zcompile/zcompile_main.c119
-rw-r--r--src/zcompile/zlexer.l532
-rw-r--r--src/zcompile/zparser.y1774
-rw-r--r--src/zscanner/file_loader.c255
-rw-r--r--src/zscanner/file_loader.h105
-rw-r--r--src/zscanner/scanner.c7803
-rw-r--r--src/zscanner/scanner.h270
-rw-r--r--src/zscanner/scanner.rl186
-rw-r--r--src/zscanner/scanner_body.rl1956
-rw-r--r--src/zscanner/scanner_functions.c985
-rw-r--r--src/zscanner/scanner_functions.h127
-rw-r--r--src/zscanner/test/cases/00_general.in24
-rw-r--r--src/zscanner/test/cases/00_general.out68
-rw-r--r--src/zscanner/test/cases/01_owner.in34
-rw-r--r--src/zscanner/test/cases/01_owner.out124
-rw-r--r--src/zscanner/test/cases/02_class.in10
-rw-r--r--src/zscanner/test/cases/02_class.out16
-rw-r--r--src/zscanner/test/cases/03_rrttl.in26
-rw-r--r--src/zscanner/test/cases/03_rrttl.out100
-rw-r--r--src/zscanner/test/cases/04-0_ORIGIN.in29
-rw-r--r--src/zscanner/test/cases/04-0_ORIGIN.out86
-rw-r--r--src/zscanner/test/cases/04-1_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-1_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-2_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-2_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-3_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-3_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-4_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-4_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-5_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-5_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-6_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-6_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-7_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-7_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-8_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-8_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/04-9_ORIGIN.in4
-rw-r--r--src/zscanner/test/cases/04-9_ORIGIN.out2
-rw-r--r--src/zscanner/test/cases/05-0_TTL.in36
-rw-r--r--src/zscanner/test/cases/05-0_TTL.out92
-rw-r--r--src/zscanner/test/cases/05-1_TTL.in4
-rw-r--r--src/zscanner/test/cases/05-1_TTL.out2
-rw-r--r--src/zscanner/test/cases/05-2_TTL.in4
-rw-r--r--src/zscanner/test/cases/05-2_TTL.out2
-rw-r--r--src/zscanner/test/cases/05-3_TTL.in4
-rw-r--r--src/zscanner/test/cases/05-3_TTL.out2
-rw-r--r--src/zscanner/test/cases/05-4_TTL.in4
-rw-r--r--src/zscanner/test/cases/05-4_TTL.out2
-rw-r--r--src/zscanner/test/cases/06-0_INCLUDE.in29
-rw-r--r--src/zscanner/test/cases/06-0_INCLUDE.inin29
-rw-r--r--src/zscanner/test/cases/06-0_INCLUDE.out140
-rw-r--r--src/zscanner/test/cases/06-1_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-1_INCLUDE.out2
-rw-r--r--src/zscanner/test/cases/06-2_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-2_INCLUDE.out2
-rw-r--r--src/zscanner/test/cases/06-3_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-3_INCLUDE.inin5
-rw-r--r--src/zscanner/test/cases/06-3_INCLUDE.out2
-rw-r--r--src/zscanner/test/cases/06-4_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-4_INCLUDE.inin5
-rw-r--r--src/zscanner/test/cases/06-4_INCLUDE.out2
-rw-r--r--src/zscanner/test/cases/06-5_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-5_INCLUDE.out2
-rw-r--r--src/zscanner/test/cases/06-6_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-6_INCLUDE.out4
-rw-r--r--src/zscanner/test/cases/06-7_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-7_INCLUDE.out4
-rw-r--r--src/zscanner/test/cases/06-8_INCLUDE.in5
-rw-r--r--src/zscanner/test/cases/06-8_INCLUDE.out12
-rw-r--r--src/zscanner/test/cases/10_A.in22
-rw-r--r--src/zscanner/test/cases/10_A.out56
-rw-r--r--src/zscanner/test/cases/11_AAAA.in24
-rw-r--r--src/zscanner/test/cases/11_AAAA.out68
-rw-r--r--src/zscanner/test/cases/12_TXT.in39
-rw-r--r--src/zscanner/test/cases/12_TXT.out134
-rw-r--r--src/zscanner/test/cases/13_SPF.in14
-rw-r--r--src/zscanner/test/cases/13_SPF.out32
-rw-r--r--src/zscanner/test/cases/14_NS.in41
-rw-r--r--src/zscanner/test/cases/14_NS.out146
-rw-r--r--src/zscanner/test/cases/15_CNAME.in14
-rw-r--r--src/zscanner/test/cases/15_CNAME.out32
-rw-r--r--src/zscanner/test/cases/16_PTR.in14
-rw-r--r--src/zscanner/test/cases/16_PTR.out32
-rw-r--r--src/zscanner/test/cases/17_DNAME.in14
-rw-r--r--src/zscanner/test/cases/17_DNAME.out32
-rw-r--r--src/zscanner/test/cases/18_MX.in26
-rw-r--r--src/zscanner/test/cases/18_MX.out68
-rw-r--r--src/zscanner/test/cases/19_AFSDB.in14
-rw-r--r--src/zscanner/test/cases/19_AFSDB.out32
-rw-r--r--src/zscanner/test/cases/20_RT.in14
-rw-r--r--src/zscanner/test/cases/20_RT.out32
-rw-r--r--src/zscanner/test/cases/21_KX.in14
-rw-r--r--src/zscanner/test/cases/21_KX.out32
-rw-r--r--src/zscanner/test/cases/22_HINFO.in29
-rw-r--r--src/zscanner/test/cases/22_HINFO.out94
-rw-r--r--src/zscanner/test/cases/23_MINFO.in21
-rw-r--r--src/zscanner/test/cases/23_MINFO.out54
-rw-r--r--src/zscanner/test/cases/24_RP.in14
-rw-r--r--src/zscanner/test/cases/24_RP.out32
-rw-r--r--src/zscanner/test/cases/25_SOA.in36
-rw-r--r--src/zscanner/test/cases/25_SOA.out84
-rw-r--r--src/zscanner/test/cases/26_SRV.in28
-rw-r--r--src/zscanner/test/cases/26_SRV.out72
-rw-r--r--src/zscanner/test/cases/27_NAPTR.in23
-rw-r--r--src/zscanner/test/cases/27_NAPTR.out62
-rw-r--r--src/zscanner/test/cases/28_TYPE.in27
-rw-r--r--src/zscanner/test/cases/28_TYPE.out64
-rw-r--r--src/zscanner/test/cases/29_CERT.in59
-rw-r--r--src/zscanner/test/cases/29_CERT.out238
-rw-r--r--src/zscanner/test/cases/30_KEY.in34
-rw-r--r--src/zscanner/test/cases/30_KEY.out92
-rw-r--r--src/zscanner/test/cases/31_DNSKEY.in35
-rw-r--r--src/zscanner/test/cases/31_DNSKEY.out98
-rw-r--r--src/zscanner/test/cases/32_APL.in30
-rw-r--r--src/zscanner/test/cases/32_APL.out100
-rw-r--r--src/zscanner/test/cases/33_DS.in26
-rw-r--r--src/zscanner/test/cases/33_DS.out68
-rw-r--r--src/zscanner/test/cases/34_SSHFP.in24
-rw-r--r--src/zscanner/test/cases/34_SSHFP.out60
-rw-r--r--src/zscanner/test/cases/35_IPSECKEY.in32
-rw-r--r--src/zscanner/test/cases/35_IPSECKEY.out100
-rw-r--r--src/zscanner/test/cases/36_RRSIG.in48
-rw-r--r--src/zscanner/test/cases/36_RRSIG.out140
-rw-r--r--src/zscanner/test/cases/37_NSEC.in23
-rw-r--r--src/zscanner/test/cases/37_NSEC.out70
-rw-r--r--src/zscanner/test/cases/38_DHCID.in29
-rw-r--r--src/zscanner/test/cases/38_DHCID.out78
-rw-r--r--src/zscanner/test/cases/39_NSEC3.in49
-rw-r--r--src/zscanner/test/cases/39_NSEC3.out150
-rw-r--r--src/zscanner/test/cases/40_NSEC3PARAM.in26
-rw-r--r--src/zscanner/test/cases/40_NSEC3PARAM.out64
-rw-r--r--src/zscanner/test/cases/41_TLSA.in24
-rw-r--r--src/zscanner/test/cases/41_TLSA.out60
-rw-r--r--src/zscanner/test/cases/42_LOC.in67
-rw-r--r--src/zscanner/test/cases/42_LOC.out254
-rw-r--r--src/zscanner/test/cases/43_EUI48.in25
-rw-r--r--src/zscanner/test/cases/43_EUI48.out66
-rw-r--r--src/zscanner/test/cases/44_EUI64.in25
-rw-r--r--src/zscanner/test/cases/44_EUI64.out66
-rw-r--r--src/zscanner/test/cases/45_NID.in14
-rw-r--r--src/zscanner/test/cases/45_NID.out32
-rw-r--r--src/zscanner/test/cases/46_L32.in25
-rw-r--r--src/zscanner/test/cases/46_L32.out60
-rw-r--r--src/zscanner/test/cases/47_L64.in26
-rw-r--r--src/zscanner/test/cases/47_L64.out68
-rw-r--r--src/zscanner/test/cases/48_LP.in14
-rw-r--r--src/zscanner/test/cases/48_LP.out32
-rw-r--r--src/zscanner/test/cases/includes/include19
-rw-r--r--src/zscanner/test/cases/includes/include26
-rw-r--r--src/zscanner/test/cases/includes/include30
-rw-r--r--src/zscanner/test/cases/includes/include41
-rw-r--r--src/zscanner/test/cases/includes/include51
-rw-r--r--src/zscanner/test/cases/includes/include61
-rw-r--r--src/zscanner/test/processing.c212
-rw-r--r--src/zscanner/test/processing.h (renamed from src/knot/zone/zone-dump-text.h)38
-rw-r--r--src/zscanner/test/run_tests.sh45
-rw-r--r--src/zscanner/test/run_tests.sh.in45
-rw-r--r--src/zscanner/test/tests.c78
-rw-r--r--src/zscanner/test/tests.h (renamed from src/tests/libknot/libknot/cuckoo_tests.h)21
-rw-r--r--src/zscanner/test/zscanner-tool.c160
-rw-r--r--tests/Makefile16
-rw-r--r--tests/chkjournal.c541
-rw-r--r--tests/querytcp.c797
-rwxr-xr-xylwrap176
547 files changed, 66484 insertions, 61319 deletions
diff --git a/AUTHORS b/AUTHORS
index 82bb742..a5f2de8 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,5 +2,6 @@
Marek Vavruša <marek.vavrusa@nic.cz>
Jan Kadlec <jan.kadlec@nic.cz>
Daniel Salzman <daniel.salzman@nic.cz>
+Jan Včelák <jan.vcelak@nic.cz>
Ondřej Surý <ondrej.sury@nic.cz>
Ondřej Filip <ondrej.filip@nic.cz>
diff --git a/CodingStyle b/CodingStyle
deleted file mode 100644
index 13dc272..0000000
--- a/CodingStyle
+++ /dev/null
@@ -1,77 +0,0 @@
-Coding style
-============
-* Indentation: TAB (8 spaces width)
-* Braces: K&R, 1TBS
-* Max line width: 80 chars
-* Pointer asterisk attached to the name of the variable
-* Own structures/types: _t suffix (f.e. nameserver_t)
-* Header guard format: _KNOTD_HEADER_H_
-* Spaces around binary operators
-* Space between keyword and bracket (f.e. "if (predicate)")
-* No space between variable and typecast (f.e. "return (int)val;")
-
-To sum it up, Linux KNF is used, see [1].
-
-[1] Linux Coding Style:
- http://kerneltrap.org/files/Jeremy/CodingStyle.txt
-
-AStyle command format
-=====================
-astyle --style=1tbs -t8 -w -p -H -U -j --align-pointer=name
-
-Doxygen
-=======
-* Format: Qt-style
- * "\brief", not "@brief"
- * "/*!", not "/**"
-* Order of sections
- * brief description
- * long description
- * notes
- * warnings
- * parameters
- * return values
- * todos
-* Always use \brief (no autobrief)
-* Indent text (using spaces only) in multiple-line sections
-* In multi-line comments, opening line (/*!) should be empty
-* One empty line between two consecutive sections
-* Struct and union members documented on the same line if the comment fits
-* Use \retval (or more of them) instead of \return
- if the function returns some distinct values
- (such as 0 for no error, -1 for something else, etc.)
-
-Example
-=======
-/*!
- * \brief Some structure.
- *
- * Longer description.
- */
- struct some_struct {
- /*!
- * \brief This comment does not fit on the same line as the member
- * as it is rather large.
- */
- int fd;
- int flags; /*!< Flags. */
- };
-
-/*!
- * \brief Brief description of some function.
- *
- * Longer description.
- *
- * \note This function is deprecated.
- *
- * \warning Do not use this function!
- *
- * \param param1 Some parameter.
- * \param param2 Other parameter. This one has rather large comment,
- * so its next line is indented for better readability.
- *
- * \retval 0 on success.
- * \retval -1 if some error occured.
- *
- * \todo Remove (deprecated).
- */
diff --git a/Doxy.page.h b/Doxy.page.h
deleted file mode 100644
index 9d73024..0000000
--- a/Doxy.page.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*!
-
-\defgroup server Server control module.
-\defgroup threading Threading API.
-\defgroup network Socket API.
-\defgroup config Server configuration.
-\defgroup query_processing DNS query processing.
-\defgroup utils Utilities, constants and macros.
-\defgroup debugging Server debugging API.
-\defgroup logging Server logging API.
-\defgroup statistics Statistics module (optional).
-\defgroup libknot libknot - library of DNS-related functions
-\defgroup hashing Hash table and functions.
-\defgroup common_lib Common library.
-\defgroup alloc Memory allocation.
-\defgroup tests Unit tests.
-\defgroup zoneparser Zone compiler utility
-\defgroup ctl Control utility
-\defgroup zone-load-dump Zone loading and dumping
-\defgroup xfr Zone transfers
-
-\mainpage Knot API documentation.
-
-Knot is an open-source, high-performace, purely authoritative DNS server.
-
-<h2>Features</h2>
-
-Knot DNS supports the following DNS features:
-- TCP/UDP protocols
-- AXFR - master, slave
-- IXFR - master (primary master experimental), slave
-- TSIG
-- ENDS0
-- DNSSEC, including NSEC3
-- NSID
-- Unknown RR types
-
-Server features:
-- Adding/removing zones on-the-fly
-- Reconfiguring server instance on-the-fly
-- IPv4 / IPv6 support
-- Semantic checks of zones
-
-<h2>Compiling and running the server</h2>
-
-See the User manual - links to current version are provided in the
-<a href="https://git.nic.cz/redmine/projects/knot-dns/wiki">Knot DNS Wiki</a>.
-
-Alternatively you can generate the manual from the sources in Info format:
-\code
-$ make doc
-\endcode
-
-or in PDF:
-
-\code
-$ make pdf
-\endcode
-
-<h2>Server modules</h2>
-- \ref server
-- \ref threading
-- \ref network
-- \ref config
-- \ref query_processing
-- \ref utils
-- \ref debugging
-- \ref logging
-- \ref statistics
-
-<h2>DNS library</h2>
-- \ref libknot
-- \ref hashing
-- \ref xfr
-
-<h2>Zone processing</h2>
-- \ref zoneparser
-- \ref zone-load-dump
-
-<h2>Common library</h2>
-- \ref common_lib
-- \ref alloc
-
-<h2>Other modules</h2>
-- \ref tests
-- \ref ctl
- */
diff --git a/Doxyfile b/Doxyfile
deleted file mode 100644
index 1a5bb0a..0000000
--- a/Doxyfile
+++ /dev/null
@@ -1,1638 +0,0 @@
-# Doxyfile 1.7.1
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
-
-DOXYFILE_ENCODING = UTF-8
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
-
-PROJECT_NAME = Knot
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
-
-PROJECT_NUMBER = 1.1.0
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY = doc
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
-
-OUTPUT_LANGUAGE = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF = "The $name class" \
- "The $name widget" \
- "The $name file" \
- is \
- provides \
- specifies \
- contains \
- represents \
- a \
- an \
- the
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC = YES
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
-
-STRIP_FROM_PATH = \
- src/
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
-
-JAVADOC_AUTOBRIEF = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
-
-QT_AUTOBRIEF = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
-
-INHERIT_DOCS = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE = 8
-
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
-
-OPTIMIZE_FOR_FORTRAN = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
-
-OPTIMIZE_OUTPUT_VHDL = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this
-# tag. The format is ext=language, where ext is a file extension, and language
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
-
-EXTENSION_MAPPING =
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-
-CPP_CLI_SUPPORT = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
-
-SIP_SUPPORT = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
-
-IDL_PROPERTY_SUPPORT = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING = YES
-
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-
-TYPEDEF_HIDES_STRUCT = YES
-
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penality.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will rougly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols
-
-SYMBOL_CACHE_SIZE = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL = YES
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
-
-EXTRACT_STATIC = NO
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES = YES
-
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespace are hidden.
-
-EXTRACT_ANON_NSPACES = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS = NO
-
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES = NO
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES = YES
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
-
-SHOW_INCLUDE_FILES = YES
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
-
-FORCE_LOCAL_INCLUDES = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
-
-INLINE_INFO = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
-
-SORT_MEMBER_DOCS = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
-
-SORT_BRIEF_DOCS = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
-
-SORT_GROUP_NAMES = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
-
-GENERATE_TODOLIST = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
-
-GENERATE_TESTLIST = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
-
-GENERATE_BUGLIST = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES = 50
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES = YES
-
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = YES
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
-
-SHOW_FILES = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page. This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
-
-SHOW_NAMESPACES = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER =
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. The create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
-
-LAYOUT_FILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
-
-WARNINGS = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR = YES
-
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
-
-WARN_NO_PARAMDOC = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
-
-WARN_LOGFILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
-
-INPUT = src/common \
- src/libknot \
- src/common \
- src/knot \
- src/zcompile \
- Doxy.page.h
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
-
-INPUT_ENCODING = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
-
-FILE_PATTERNS = *.c \
- *.h
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
-
-RECURSIVE = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE =
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
-# from the input.
-
-EXCLUDE_SYMLINKS = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS =
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-
-EXCLUDE_SYMBOLS =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
-
-EXAMPLE_PATH =
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
-
-EXAMPLE_PATTERNS = *
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
-
-IMAGE_PATH =
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
-# ignored.
-
-INPUT_FILTER =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
-
-FILTER_PATTERNS =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER = YES
-
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
-
-REFERENCES_RELATION = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentation.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX = YES
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX = 5
-
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX =
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
-
-GENERATE_HTML = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
-
-HTML_HEADER =
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
-
-HTML_FOOTER =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET =
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the stylesheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
-
-HTML_COLORSTYLE_HUE = 220
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
-
-HTML_COLORSTYLE_SAT = 100
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
-
-HTML_COLORSTYLE_GAMMA = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
-
-HTML_TIMESTAMP = YES
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
-
-HTML_DYNAMIC_SECTIONS = NO
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-
-GENERATE_DOCSET = NO
-
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
-
-DOCSET_FEEDNAME = "Doxygen generated docs"
-
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
-
-DOCSET_BUNDLE_ID = org.doxygen.Project
-
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
-
-DOCSET_PUBLISHER_ID = org.doxygen.Publisher
-
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
-
-DOCSET_PUBLISHER_NAME = Publisher
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
-# written to the html output directory.
-
-CHM_FILE =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
-
-CHM_INDEX_ENCODING =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
-
-GENERATE_QHP = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
-
-QCH_FILE =
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
-
-QHP_NAMESPACE = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
-
-QHP_VIRTUAL_FOLDER = doc
-
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
-
-QHP_CUST_FILTER_NAME =
-
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
-
-QHP_CUST_FILTER_ATTRS =
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
-
-QHP_SECT_FILTER_ATTRS =
-
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
-
-QHG_LOCATION =
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-# will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
-
-GENERATE_ECLIPSEHELP = NO
-
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
-
-ECLIPSE_DOC_ID = org.doxygen.Project
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
-
-DISABLE_INDEX = NO
-
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE = 4
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-
-GENERATE_TREEVIEW = NO
-
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
-
-TREEVIEW_WIDTH = 250
-
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
-
-EXT_LINKS_IN_WINDOW = NO
-
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
-
-FORMULA_FONTSIZE = 10
-
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
-
-FORMULA_TRANSPARENT = YES
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
-
-SEARCHENGINE = YES
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvances is that it is more difficult to setup
-# and does not have live searching capabilities.
-
-SERVER_BASED_SEARCH = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
-
-GENERATE_LATEX = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
-
-LATEX_CMD_NAME = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
-
-MAKEINDEX_CMD_NAME = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_LATEX = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE = a4wide
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES =
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS = YES
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
-
-USE_PDFLATEX = YES
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
-
-LATEX_HIDE_INDICES = NO
-
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
-
-LATEX_SOURCE_CODE = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
-
-GENERATE_RTF = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_RTF = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE =
-
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
-
-GENERATE_MAN = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT = man
-
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
-
-GENERATE_XML = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
-
-GENERATE_PERLMOD = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY = YES
-
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
-
-ENABLE_PREPROCESSING = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
-
-INCLUDE_PATH =
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
-
-INCLUDE_FILE_PATTERNS =
-
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
-PREDEFINED =
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED =
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE =
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
-
-ALLEXTERNALS = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
-
-EXTERNAL_GROUPS = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
-# powerful graphs.
-
-CLASS_DIAGRAMS = YES
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH =
-
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT = NO
-
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
-
-DOT_NUM_THREADS = 0
-
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
-# containing the font.
-
-DOT_FONTNAME = FreeSans.ttf
-
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
-
-DOT_FONTSIZE = 10
-
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
-# can find it using this tag.
-
-DOT_FONTPATH =
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-
-UML_LOOK = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
-
-INCLUDE_GRAPH = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH = YES
-
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
-
-CALL_GRAPH = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
-
-CALLER_GRAPH = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY = YES
-
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH =
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
-
-DOTFILE_DIRS =
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-
-DOT_GRAPH_MAX_NODES = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-
-MAX_DOT_GRAPH_DEPTH = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
-
-DOT_CLEANUP = YES
diff --git a/Doxyfile.devel b/Doxyfile.devel
deleted file mode 100644
index 4b73045..0000000
--- a/Doxyfile.devel
+++ /dev/null
@@ -1,1634 +0,0 @@
-# Doxyfile 1.7.1
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-# TAG = value [value, ...]
-# For lists items can also be appended using:
-# TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the
-# iconv built into libc) for the transcoding. See
-# http://www.gnu.org/software/libiconv for the list of possible encodings.
-
-DOXYFILE_ENCODING = UTF-8
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
-
-PROJECT_NAME = Knot
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number.
-# This could be handy for archiving the generated documentation or
-# if some version control system is used.
-
-PROJECT_NUMBER = 0.1.0
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
-# base path where the generated documentation will be put.
-# If a relative path is entered, it will be relative to the location
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY = doc-devel
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
-# 4096 sub-directories (in 2 levels) under the output directory of each output
-# format and will distribute the generated files over these directories.
-# Enabling this option can be useful when feeding doxygen a huge amount of
-# source files, where putting all generated files in the same directory would
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all
-# documentation generated by doxygen is written. Doxygen will use this
-# information to generate all constant output in the proper language.
-# The default language is English, other supported languages are:
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
-
-OUTPUT_LANGUAGE = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
-# include brief member descriptions after the members that are listed in
-# the file and class documentation (similar to JavaDoc).
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
-# the brief description of a member or function before the detailed description.
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator
-# that is used to form the text in various listings. Each string
-# in this list, if found as the leading text of the brief description, will be
-# stripped from the text and the result after processing the whole list, is
-# used as the annotated text. Otherwise, the brief description is used as-is.
-# If left blank, the following values are used ("$name" is automatically
-# replaced with the name of the entity): "The $name class" "The $name widget"
-# "The $name file" "is" "provides" "specifies" "contains"
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF = "The $name class" \
- "The $name widget" \
- "The $name file" \
- is \
- provides \
- specifies \
- contains \
- represents \
- a \
- an \
- the
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
-# Doxygen will generate a detailed section even if there is only a brief
-# description.
-
-ALWAYS_DETAILED_SEC = YES
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
-# inherited members of a class in the documentation of that class as if those
-# members were ordinary class members. Constructors, destructors and assignment
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
-# path before files name in the file list and in the header files. If set
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
-# can be used to strip a user-defined part of the path. Stripping is
-# only done if one of the specified strings matches the left-hand part of
-# the path. The tag can be used to show relative paths in the file list.
-# If left blank the directory from which doxygen is run is used as the
-# path to strip.
-
-STRIP_FROM_PATH = \
- src/
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
-# the path mentioned in the documentation of a class, which tells
-# the reader which header file to include in order to use a class.
-# If left blank only the name of the header file containing the class
-# definition is used. Otherwise one should specify the include paths that
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH =
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
-# will interpret the first line (until the first dot) of a JavaDoc-style
-# comment as the brief description. If set to NO, the JavaDoc
-# comments will behave just like regular Qt-style comments
-# (thus requiring an explicit @brief command for a brief description.)
-
-JAVADOC_AUTOBRIEF = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
-# interpret the first line (until the first dot) of a Qt-style
-# comment as the brief description. If set to NO, the comments
-# will behave just like regular Qt-style comments (thus requiring
-# an explicit \brief command for a brief description.)
-
-QT_AUTOBRIEF = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
-# treat a multi-line C++ special comment block (i.e. a block of //! or ///
-# comments) as a brief description. This used to be the default behaviour.
-# The new default is to treat a multi-line C++ comment block as a detailed
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
-# member inherits the documentation from any documented member that it
-# re-implements.
-
-INHERIT_DOCS = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
-# a new page for each member. If set to NO, the documentation of a member will
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab.
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE = 8
-
-# This tag can be used to specify a number of aliases that acts
-# as commands in the documentation. An alias has the form "name=value".
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to
-# put the command \sideeffect (or @sideeffect) in the documentation, which
-# will result in a user-defined paragraph with heading "Side Effects:".
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES =
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
-# sources only. Doxygen will then generate output that is more tailored for C.
-# For instance, some of the names that are used will be different. The list
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
-# sources only. Doxygen will then generate output that is more tailored for
-# Java. For instance, namespaces will be presented as packages, qualified
-# scopes will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
-# sources only. Doxygen will then generate output that is more tailored for
-# Fortran.
-
-OPTIMIZE_FOR_FORTRAN = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
-# sources. Doxygen will then generate output that is tailored for
-# VHDL.
-
-OPTIMIZE_OUTPUT_VHDL = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this
-# tag. The format is ext=language, where ext is a file extension, and language
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
-
-EXTENSION_MAPPING =
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
-# to include (a tag file for) the STL sources as input, then you should
-# set this tag to YES in order to let doxygen match functions declarations and
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to
-# enable parsing support.
-
-CPP_CLI_SUPPORT = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
-# Doxygen will parse them like normal C++ but will assume all classes use public
-# instead of private inheritance when no explicit protection keyword is present.
-
-SIP_SUPPORT = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
-# setting a simple type. If this is not the case, or you want to show the
-# methods anyway, you should set this option to NO.
-
-IDL_PROPERTY_SUPPORT = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
-# tag is set to YES, then doxygen will reuse the documentation of the first
-# member in the group (if any) for the other members of the group. By default
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
-# the same type (for instance a group of public functions) to be put as a
-# subgroup of that type (e.g. under the Public Functions section). Set it to
-# NO to prevent subgrouping. Alternatively, this can be done per class using
-# the \nosubgrouping command.
-
-SUBGROUPING = YES
-
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
-# is documented as struct, union, or enum with the name of the typedef. So
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
-# with name TypeT. When disabled the typedef will appear as a member of a file,
-# namespace, or class. And the struct will be named TypeS. This can typically
-# be useful for C code in case the coding convention dictates that all compound
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-
-TYPEDEF_HIDES_STRUCT = YES
-
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penality.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will rougly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols
-
-SYMBOL_CACHE_SIZE = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
-# documentation are documented, even if no documentation was available.
-# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL = YES
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
-# will be included in the documentation.
-
-EXTRACT_PRIVATE = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file
-# will be included in the documentation.
-
-EXTRACT_STATIC = YES
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
-# defined locally in source files will be included in the documentation.
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES = YES
-
-# This flag is only useful for Objective-C code. When set to YES local
-# methods, which are defined in the implementation section but not in
-# the interface are included in the documentation.
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be
-# extracted and appear in the documentation as a namespace called
-# 'anonymous_namespace{file}', where file will be replaced with the base
-# name of the file that contains the anonymous namespace. By default
-# anonymous namespace are hidden.
-
-EXTRACT_ANON_NSPACES = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
-# undocumented members of documented classes, files or namespaces.
-# If set to NO (the default) these members will be included in the
-# various overviews, but no documentation section is generated.
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
-# undocumented classes that are normally visible in the class hierarchy.
-# If set to NO (the default) these classes will be included in the various
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
-# friend (class|struct|union) declarations.
-# If set to NO (the default) these declarations will be included in the
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
-# documentation blocks found inside the body of a function.
-# If set to NO (the default) these blocks will be appended to the
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS = NO
-
-# The INTERNAL_DOCS tag determines if documentation
-# that is typed after a \internal command is included. If the tag is set
-# to NO (the default) then the documentation will be excluded.
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
-# file names in lower-case letters. If set to YES upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-
-CASE_SENSE_NAMES = NO
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
-# will show members with their full class and namespace scopes in the
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES = YES
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
-# will put a list of the files that are included by a file in the documentation
-# of that file.
-
-SHOW_INCLUDE_FILES = YES
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
-# will list include files with double quotes in the documentation
-# rather than with sharp brackets.
-
-FORCE_LOCAL_INCLUDES = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
-# is inserted in the documentation for inline members.
-
-INLINE_INFO = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
-# will sort the (detailed) documentation of file and class members
-# alphabetically by member name. If set to NO the members will appear in
-# declaration order.
-
-SORT_MEMBER_DOCS = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
-# brief documentation of file, namespace and class members alphabetically
-# by member name. If set to NO (the default) the members will appear in
-# declaration order.
-
-SORT_BRIEF_DOCS = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
-# hierarchy of group names into alphabetical order. If set to NO (the default)
-# the group names will appear in their defined order.
-
-SORT_GROUP_NAMES = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
-# sorted by fully-qualified names, including namespaces. If set to
-# NO (the default), the class list will be sorted only by class name,
-# not including the namespace part.
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or
-# disable (NO) the todo list. This list is created by putting \todo
-# commands in the documentation.
-
-GENERATE_TODOLIST = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or
-# disable (NO) the test list. This list is created by putting \test
-# commands in the documentation.
-
-GENERATE_TESTLIST = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or
-# disable (NO) the bug list. This list is created by putting \bug
-# commands in the documentation.
-
-GENERATE_BUGLIST = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
-# disable (NO) the deprecated list. This list is created by putting
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS =
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
-# the documentation. If the initializer consists of more lines than specified
-# here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
-# documentation can be controlled using \showinitializer or \hideinitializer
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES = 50
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
-# at the bottom of the documentation of classes and structs. If set to YES the
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES = YES
-
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES = YES
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
-# This will remove the Files entry from the Quick Index and from the
-# Folder Tree View (if specified). The default is YES.
-
-SHOW_FILES = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
-# Namespaces page. This will remove the Namespaces entry from the Quick Index
-# and from the Folder Tree View (if specified). The default is YES.
-
-SHOW_NAMESPACES = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that
-# doxygen should invoke to get the current version for each file (typically from
-# the version control system). Doxygen will invoke the program by executing (via
-# popen()) the command <command> <input-file>, where <command> is the value of
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
-# provided by doxygen. Whatever the program writes to standard output
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER =
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
-# by doxygen. The layout file controls the global structure of the generated
-# output files in an output format independent way. The create the layout file
-# that represents doxygen's defaults, run doxygen with the -l option.
-# You can optionally specify a file name after the option, if omitted
-# DoxygenLayout.xml will be used as the name of the layout file.
-
-LAYOUT_FILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are
-# generated by doxygen. Possible values are YES and NO. If left blank
-# NO is used.
-
-WARNINGS = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some
-# parameters in a documented function, or documenting parameters that
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR = YES
-
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
-# functions that are documented, but have no documentation for their parameters
-# or return value. If set to NO (the default) doxygen will only warn about
-# wrong or incomplete parameter documentation, but not about the absence of
-# documentation.
-
-WARN_NO_PARAMDOC = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that
-# doxygen can produce. The string should contain the $file, $line, and $text
-# tags, which will be replaced by the file and line number from which the
-# warning originated and the warning text. Optionally the format may contain
-# $version, which will be replaced by the version of the file (if it could
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning
-# and error messages should be written. If left blank the output is written
-# to stderr.
-
-WARN_LOGFILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain
-# documented source files. You may enter file names like "myfile.cpp" or
-# directories like "/usr/src/myproject". Separate the files or directories
-# with spaces.
-
-INPUT = src/ \
- Doxy.page.h
-
-# This tag can be used to specify the character encoding of the source files
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
-# also the default input encoding. Doxygen uses libiconv (or the iconv built
-# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
-# the list of possible encodings.
-
-INPUT_ENCODING = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
-
-FILE_PATTERNS = *.c \
- *.h
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories
-# should be searched for input files as well. Possible values are YES and NO.
-# If left blank NO is used.
-
-RECURSIVE = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should
-# excluded from the INPUT source files. This way you can easily exclude a
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE =
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
-# from the input.
-
-EXCLUDE_SYMLINKS = NO
-
-# If the value of the INPUT tag contains directories, you can use the
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
-# certain files from those directories. Note that the wildcards are matched
-# against the file with absolute path, so to exclude all test directories
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS =
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
-# (namespaces, classes, functions, etc.) that should be excluded from the
-# output. The symbol name can be a fully qualified name, a word, or if the
-# wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
-
-EXCLUDE_SYMBOLS =
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or
-# directories that contain example code fragments that are included (see
-# the \include command).
-
-EXAMPLE_PATH =
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
-# and *.h) to filter out the source-files in the directories. If left
-# blank all files are included.
-
-EXAMPLE_PATTERNS = *
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
-# searched for input files to be used with the \include or \dontinclude
-# commands irrespective of the value of the RECURSIVE tag.
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or
-# directories that contain image that are included in the documentation (see
-# the \image command).
-
-IMAGE_PATH =
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should
-# invoke to filter for each input file. Doxygen will invoke the filter program
-# by executing (via popen()) the command <filter> <input-file>, where <filter>
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
-# input file. Doxygen will then use the output that the filter program writes
-# to standard output. If FILTER_PATTERNS is specified, this tag will be
-# ignored.
-
-INPUT_FILTER =
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
-# basis. Doxygen will compare the file name with each pattern and apply the
-# filter if there is a match. The filters are a list of the form:
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
-
-FILTER_PATTERNS =
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
-# INPUT_FILTER) will be used to filter the input files when producing source
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will
-# be generated. Documented entities will be cross-referenced with these sources.
-# Note: To get rid of all source code in the generated output, make sure also
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER = YES
-
-# Setting the INLINE_SOURCES tag to YES will include the body
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
-# doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES
-# then for each documented function all documented
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = NO
-
-# If the REFERENCES_RELATION tag is set to YES
-# then for each documented function all documented entities
-# called/used by that function will be listed.
-
-REFERENCES_RELATION = NO
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
-# link to the source code. Otherwise they will link to the documentation.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code
-# will point to the HTML generated by the htags(1) tool instead of doxygen
-# built-in source browser. The htags tool is part of GNU's global source
-# tagging system (see http://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
-# will generate a verbatim copy of the header file for each class for
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
-# of all compounds will be generated. Enable this if the project
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX = YES
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX = 5
-
-# In case all classes in a project start with a common prefix, all
-# classes will be put under the same header in the alphabetical index.
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX =
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
-# generate HTML output.
-
-GENERATE_HTML = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
-
-HTML_HEADER =
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for
-# each generated HTML page. If it is left blank doxygen will generate a
-# standard footer.
-
-HTML_FOOTER =
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
-# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET =
-
-# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
-# Doxygen will adjust the colors in the stylesheet and background images
-# according to this color. Hue is specified as an angle on a colorwheel,
-# see http://en.wikipedia.org/wiki/Hue for more information.
-# For instance the value 0 represents red, 60 is yellow, 120 is green,
-# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
-# The allowed range is 0 to 359.
-
-HTML_COLORSTYLE_HUE = 220
-
-# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
-# the colors in the HTML output. For a value of 0 the output will use
-# grayscales only. A value of 255 will produce the most vivid colors.
-
-HTML_COLORSTYLE_SAT = 100
-
-# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
-# the luminance component of the colors in the HTML output. Values below
-# 100 gradually make the output lighter, whereas values above 100 make
-# the output darker. The value divided by 100 is the actual gamma applied,
-# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
-# and 100 does not change the gamma.
-
-HTML_COLORSTYLE_GAMMA = 80
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
-# page will contain the date and time when the page was generated. Setting
-# this to NO can help when comparing the output of multiple runs.
-
-HTML_TIMESTAMP = YES
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS = YES
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
-# documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
-
-HTML_DYNAMIC_SECTIONS = NO
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files
-# will be generated that can be used as input for Apple's Xcode 3
-# integrated development environment, introduced with OSX 10.5 (Leopard).
-# To create a documentation set, doxygen will generate a Makefile in the
-# HTML output directory. Running make will produce the docset in that
-# directory and running "make install" will install the docset in
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
-# it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
-
-GENERATE_DOCSET = NO
-
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
-# feed. A documentation feed provides an umbrella under which multiple
-# documentation sets from a single provider (such as a company or product suite)
-# can be grouped.
-
-DOCSET_FEEDNAME = "Doxygen generated docs"
-
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
-# should uniquely identify the documentation set bundle. This should be a
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
-# will append .docset to the name.
-
-DOCSET_BUNDLE_ID = org.doxygen.Project
-
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
-
-DOCSET_PUBLISHER_ID = org.doxygen.Publisher
-
-# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
-
-DOCSET_PUBLISHER_NAME = Publisher
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files
-# will be generated that can be used as input for tools like the
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
-# be used to specify the file name of the resulting .chm file. You
-# can add a path in front of the file if the result should not be
-# written to the html output directory.
-
-CHM_FILE =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
-# be used to specify the location (absolute path including file name) of
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
-# controls if a separate .chi index file is generated (YES) or that
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file
-# content.
-
-CHM_INDEX_ENCODING =
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
-# controls whether a binary table of contents is generated (YES) or a
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
-# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
-# that can be used as input for Qt's qhelpgenerator to generate a
-# Qt Compressed Help (.qch) of the generated HTML documentation.
-
-GENERATE_QHP = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
-# be used to specify the file name of the resulting .qch file.
-# The path specified is relative to the HTML output folder.
-
-QCH_FILE =
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#namespace
-
-QHP_NAMESPACE = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
-# Qt Help Project output. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#virtual-folders
-
-QHP_VIRTUAL_FOLDER = doc
-
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
-# add. For more information please see
-# http://doc.trolltech.com/qthelpproject.html#custom-filters
-
-QHP_CUST_FILTER_NAME =
-
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
-# custom filter to add. For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
-# Qt Help Project / Custom Filters</a>.
-
-QHP_CUST_FILTER_ATTRS =
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
-# project's
-# filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
-# Qt Help Project / Filter Attributes</a>.
-
-QHP_SECT_FILTER_ATTRS =
-
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
-# be used to specify the location of Qt's qhelpgenerator.
-# If non-empty doxygen will try to run qhelpgenerator on the generated
-# .qhp file.
-
-QHG_LOCATION =
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
-# will be generated, which together with the HTML files, form an Eclipse help
-# plugin. To install this plugin and make it available under the help contents
-# menu in Eclipse, the contents of the directory containing the HTML and XML
-# files needs to be copied into the plugins directory of eclipse. The name of
-# the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
-
-GENERATE_ECLIPSEHELP = NO
-
-# A unique identifier for the eclipse help plugin. When installing the plugin
-# the directory name containing the HTML and XML files should also have
-# this name.
-
-ECLIPSE_DOC_ID = org.doxygen.Project
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
-
-DISABLE_INDEX = NO
-
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE = 4
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
-# structure should be generated to display hierarchical information.
-# If the tag value is set to YES, a side panel will be generated
-# containing a tree-like index structure (just like the one that
-# is generated for HTML Help). For this to work a browser that supports
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
-# Windows users are probably better off using the HTML help feature.
-
-GENERATE_TREEVIEW = NO
-
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
-# used to set the initial width (in pixels) of the frame in which the tree
-# is shown.
-
-TREEVIEW_WIDTH = 250
-
-# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
-# links to external symbols imported via tag files in a separate window.
-
-EXT_LINKS_IN_WINDOW = NO
-
-# Use this tag to change the font size of Latex formulas included
-# as images in the HTML documentation. The default is 10. Note that
-# when you change the font size after a successful doxygen run you need
-# to manually remove any form_*.png images from the HTML output directory
-# to force them to be regenerated.
-
-FORMULA_FONTSIZE = 10
-
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are
-# not supported properly for IE 6.0, but are supported on all modern browsers.
-# Note that when changing this option you need to delete any form_*.png files
-# in the HTML output before the changes have effect.
-
-FORMULA_TRANSPARENT = YES
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should
-# typically be disabled. For large projects the javascript based search engine
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
-
-SEARCHENGINE = YES
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvances is that it is more difficult to setup
-# and does not have live searching capabilities.
-
-SERVER_BASED_SEARCH = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
-# generate Latex output.
-
-GENERATE_LATEX = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
-# invoked. If left blank `latex' will be used as the default command name.
-# Note that when enabling USE_PDFLATEX this option is only used for
-# generating bitmaps for formulas in the HTML output, but not in the
-# Makefile that is written to the output directory.
-
-LATEX_CMD_NAME = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
-# generate index for LaTeX. If left blank `makeindex' will be used as the
-# default command name.
-
-MAKEINDEX_CMD_NAME = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
-# LaTeX documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_LATEX = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE = a4wide
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES =
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
-# the generated latex document. The header should contain everything until
-# the first chapter. If it is left blank doxygen will generate a
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER =
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will
-# contain links (just like the HTML output) instead of page references
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS = YES
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
-# plain latex in the generated Makefile. Set this option to YES to get a
-# higher quality PDF documentation.
-
-USE_PDFLATEX = YES
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
-# command to the generated LaTeX files. This will instruct LaTeX to keep
-# running if errors occur, instead of asking the user for help.
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not
-# include the index chapters (such as File Index, Compound Index, etc.)
-# in the output.
-
-LATEX_HIDE_INDICES = NO
-
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
-
-LATEX_SOURCE_CODE = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
-# The RTF output is optimized for Word 97 and may not look very pretty with
-# other RTF readers or editors.
-
-GENERATE_RTF = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
-# RTF documents. This may be useful for small projects and may help to
-# save some trees in general.
-
-COMPACT_RTF = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
-# will contain hyperlink fields. The RTF file will
-# contain links (just like the HTML output) instead of page references.
-# This makes the output suitable for online browsing using WORD or other
-# programs which support those fields.
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
-# config file, i.e. a series of assignments. You only have to provide
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE =
-
-# Set optional variables used in the generation of an rtf document.
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE =
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
-# generate man pages
-
-GENERATE_MAN = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT = man
-
-# The MAN_EXTENSION tag determines the extension that is added to
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
-# then it will generate one additional man file for each entity
-# documented in the real man page(s). These additional files
-# only source the real man page, but without them the man command
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will
-# generate an XML file that captures the structure of
-# the code including all documentation.
-
-GENERATE_XML = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put.
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_SCHEMA =
-
-# The XML_DTD tag can be used to specify an XML DTD,
-# which can be used by a validating XML parser to check the
-# syntax of the XML files.
-
-XML_DTD =
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
-# dump the program listings (including syntax highlighting
-# and cross-referencing information) to the XML output. Note that
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
-# generate an AutoGen Definitions (see autogen.sf.net) file
-# that captures the structure of the code including all
-# documentation. Note that this feature is still experimental
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will
-# generate a Perl module file that captures the structure of
-# the code including all documentation. Note that this
-# feature is still experimental and incomplete at the
-# moment.
-
-GENERATE_PERLMOD = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
-# nicely formatted so it can be parsed by a human reader. This is useful
-# if you want to understand what is going on. On the other hand, if this
-# tag is set to NO the size of the Perl module output will be much smaller
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY = YES
-
-# The names of the make variables in the generated doxyrules.make file
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
-# This is useful so different doxyrules.make files included by the same
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX =
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
-# evaluate all C-preprocessor directives found in the sources and include
-# files.
-
-ENABLE_PREPROCESSING = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
-# names in the source code. If set to NO (the default) only conditional
-# compilation will be performed. Macro expansion can be done in a controlled
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
-# then the macro expansion is limited to the macros specified with the
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that
-# contain include files that are not input files but should be processed by
-# the preprocessor.
-
-INCLUDE_PATH =
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
-# patterns (like *.h and *.hpp) to filter out the header-files in the
-# directories. If left blank, the patterns specified with FILE_PATTERNS will
-# be used.
-
-INCLUDE_FILE_PATTERNS =
-
-# The PREDEFINED tag can be used to specify one or more macro names that
-# are defined before the preprocessor is started (similar to the -D option of
-# gcc). The argument of the tag is a list of macros of the form: name
-# or name=definition (no spaces). If the definition and the = are
-# omitted =1 is assumed. To prevent a macro definition from being
-# undefined via #undef or recursively expanded use the := operator
-# instead of the = operator.
-
-PREDEFINED =
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
-# this tag can be used to specify a list of macro names that should be expanded.
-# The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED =
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
-# TAGFILES = file1 file2 ...
-# Adding location for the tag files is done as follows:
-# TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES =
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE =
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed
-# in the class index. If set to NO only the inherited external classes
-# will be listed.
-
-ALLEXTERNALS = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
-# in the modules index. If set to NO, only the current project's groups will
-# be listed.
-
-EXTERNAL_GROUPS = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
-# or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
-# powerful graphs.
-
-CLASS_DIAGRAMS = YES
-
-# You can define message sequence charts within doxygen comments using the \msc
-# command. Doxygen will then run the mscgen tool (see
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where
-# the mscgen tool resides. If left empty the tool is assumed to be found in the
-# default search path.
-
-MSCGEN_PATH =
-
-# If set to YES, the inheritance and collaboration graphs will hide
-# inheritance and usage relations if the target is undocumented
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
-# available from the path. This tool is part of Graphviz, a graph visualization
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT = NO
-
-# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
-# allowed to run in parallel. When set to 0 (the default) doxygen will
-# base this on the number of processors available in the system. You can set it
-# explicitly to a value larger than 0 to get control over the balance
-# between CPU load and processing speed.
-
-DOT_NUM_THREADS = 0
-
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
-# containing the font.
-
-DOT_FONTNAME = FreeSans.ttf
-
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
-# The default size is 10pt.
-
-DOT_FONTSIZE = 10
-
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
-# can find it using this tag.
-
-DOT_FONTPATH =
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for each documented class showing the direct and
-# indirect implementation dependencies (inheritance, containment, and
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
-# collaboration diagrams in a style similar to the OMG's Unified Modeling
-# Language.
-
-UML_LOOK = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
-# tags are set to YES then doxygen will generate a graph for each documented
-# file showing the direct and indirect include dependencies of the file with
-# other documented files.
-
-INCLUDE_GRAPH = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
-# documented header file showing the documented files that directly or
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH = YES
-
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then
-# doxygen will generate a call dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable call graphs
-# for selected functions only using the \callgraph command.
-
-CALL_GRAPH = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
-# doxygen will generate a caller dependency graph for every global function
-# or class method. Note that enabling this option will significantly increase
-# the time of a run. So in most cases it will be better to enable caller
-# graphs for selected functions only using the \callergraph command.
-
-CALLER_GRAPH = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY = YES
-
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
-# then doxygen will show the dependencies a directory has on other directories
-# in a graphical way. The dependency relations are determined by the #include
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH =
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that
-# contain dot files that are included in the documentation (see the
-# \dotfile command).
-
-DOTFILE_DIRS =
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
-# nodes that will be shown in the graph. If the number of nodes in a graph
-# becomes larger than this value, doxygen will truncate the graph, which is
-# visualized by representing a node as a red box. Note that doxygen if the
-# number of direct children of the root node in a graph is already larger than
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-
-DOT_GRAPH_MAX_NODES = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
-# graphs generated by dot. A depth value of 3 means that only nodes reachable
-# from the root by following a path via at most 3 edges will be shown. Nodes
-# that lay further from the root node will be omitted. Note that setting this
-# option to 1 or 2 may greatly reduce the computation time needed for large
-# code bases. Also note that the size of a graph can be further restricted by
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-
-MAX_DOT_GRAPH_DEPTH = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not
-# seem to support this out of the box. Warning: Depending on the platform used,
-# enabling this option may lead to badly anti-aliased labels on the edges of
-# a graph (i.e. they become hard to read).
-
-DOT_TRANSPARENT = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
-# files in one run (i.e. multiple -o and -T options on the command line). This
-# makes dot run faster, but since only newer versions of dot (>1.8.10)
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
-# generate a legend page explaining the meaning of the various boxes and
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
-# remove the intermediate dot files that are used to generate
-# the various graphs.
-
-DOT_CLEANUP = YES
diff --git a/INSTALL b/INSTALL
index 6e90e07..a1e89e1 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
Installation Instructions
*************************
-Copyright (C) 1994-1996, 1999-2002, 2004-2012 Free Software Foundation,
+Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
@@ -309,10 +309,9 @@ causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf limitation. Until the limitation is lifted, you can use
-this workaround:
+an Autoconf bug. Until the bug is fixed you can use this workaround:
- CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
@@ -368,3 +367,4 @@ operates.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
+
diff --git a/KNOWN_ISSUES b/KNOWN_ISSUES
deleted file mode 100644
index 4db58a7..0000000
--- a/KNOWN_ISSUES
+++ /dev/null
@@ -1,16 +0,0 @@
-Features not supported
-======================
-
-Here is a list of the most notable features that are not supported in the
-current version of Knot.
-
-* Other DNS classes than IN (CH, CS, HS)
-* Dynamic updates with signed zones have following limitations:
- - Knot DNS doesn't automatically sign incoming RRs
- - Removing of RRSIG without covered type specification
- - Deleting a last RR also removes its RRSIG
-
-Known bugs
-==========
-
-* ACL may not always find the best match so it may behave counter-intuitively.
diff --git a/Knot.config b/Knot.config
deleted file mode 100644
index 8cec188..0000000
--- a/Knot.config
+++ /dev/null
@@ -1 +0,0 @@
-// ADD PREDEFINED MACROS HERE!
diff --git a/Knot.creator b/Knot.creator
deleted file mode 100644
index e94cbbd..0000000
--- a/Knot.creator
+++ /dev/null
@@ -1 +0,0 @@
-[General]
diff --git a/Knot.files b/Knot.files
deleted file mode 100644
index c968d91..0000000
--- a/Knot.files
+++ /dev/null
@@ -1,282 +0,0 @@
-CodingStyle
-Makefile.am
-Doxy.page.h
-Doxyfile
-Doxyfile.devel
-configure.ac
-KNOWN_ISSUES
-README
-tests/querytcp.c
-src/libknot/libknot.h
-src/libknot/common.h
-src/libknot/dname.h
-src/libknot/dname.c
-src/libknot/rrset.h
-src/libknot/rrset.c
-src/libknot/rdata.h
-src/libknot/rdata.c
-src/libknot/edns.h
-src/libknot/edns.c
-src/libknot/nsec3.h
-src/libknot/nsec3.c
-src/libknot/consts.h
-src/libknot/hash/cuckoo-hash-table.c
-src/libknot/hash/cuckoo-hash-table.h
-src/libknot/hash/hash-functions.c
-src/libknot/hash/hash-functions.h
-src/libknot/hash/universal-system.c
-src/libknot/hash/universal-system.h
-src/libknot/nameserver/name-server.c
-src/libknot/nameserver/name-server.h
-src/libknot/packet/packet.h
-src/libknot/packet/packet.c
-src/libknot/packet/query.h
-src/libknot/packet/query.c
-src/libknot/packet/response.h
-src/libknot/packet/response.c
-src/libknot/updates/changesets.h
-src/libknot/updates/changesets.c
-src/libknot/updates/ddns.h
-src/libknot/updates/ddns.c
-src/libknot/updates/xfr-in.h
-src/libknot/updates/xfr-in.c
-src/libknot/util/wire.h
-src/libknot/util/debug.h
-src/libknot/util/debug.c
-src/libknot/util/tolower.h
-src/libknot/util/tolower.c
-src/libknot/util/utils.h
-src/libknot/util/utils.c
-src/libknot/util/descriptor.h
-src/libknot/util/descriptor.c
-src/libknot/zone/zonedb.h
-src/libknot/zone/zonedb.c
-src/libknot/zone/node.h
-src/libknot/zone/node.c
-src/libknot/zone/zone.h
-src/libknot/zone/zone.c
-src/libknot/zone/zone-contents.c
-src/libknot/zone/zone-contents.h
-src/libknot/zone/zone-tree.h
-src/libknot/zone/zone-tree.c
-src/libknot/zone/dname-table.h
-src/libknot/zone/dname-table.c
-src/Makefile.am
-src/common/hattrie/murmurhash3.c
-src/common/hattrie/murmurhash3.h
-src/common/slab/slab.c
-src/common/slab/slab.h
-src/common/slab/alloc-common.h
-src/common/libtap/tap.c
-src/common/libtap/tap.h
-src/common/libtap/tap_unit.h
-src/common/mempattern.c
-src/common/mempattern.h
-src/common/lists.h
-src/common/lists.c
-src/common/heap.h
-src/common/heap.c
-src/common/base32.h
-src/common/base32.c
-src/common/print.c
-src/common/print.h
-src/common/latency.c
-src/common/latency.h
-src/common/skip-list.c
-src/common/skip-list.h
-src/common/tree.h
-src/common/base32hex.h
-src/common/base32hex.c
-src/common/evqueue.c
-src/common/evqueue.h
-src/common/evsched.c
-src/common/evsched.h
-src/common/errcode.h
-src/common/errcode.c
-src/common/errors.h
-src/common/errors.c
-src/common/acl.c
-src/common/acl.h
-src/common/sockaddr.h
-src/common/sockaddr.c
-src/common/crc.h
-src/common/ref.c
-src/common/ref.h
-src/common/modified_tree.h
-src/common/general-tree.h
-src/common/general-tree.c
-src/common/dSFMT.c
-src/common/dSFMT.h
-src/common/dSFMT-params.h
-src/common/dSFMT-params521.h
-src/common/prng.c
-src/common/prng.h
-src/common/fdset.h
-src/common/fdset.c
-src/common/fdset_poll.h
-src/common/fdset_poll.c
-src/common/fdset_epoll.h
-src/common/fdset_epoll.c
-src/common/fdset_kqueue.h
-src/common/fdset_kqueue.c
-src/common/log.c
-src/common/log.h
-src/zcompile/parser-descriptor.h
-src/zcompile/parser-descriptor.c
-src/zcompile/parser-util.h
-src/zcompile/parser-util.c
-src/zcompile/zcompile.c
-src/zcompile/zcompile.h
-src/zcompile/zparser.y
-src/zcompile/zlexer.l
-src/zcompile/zcompile-error.h
-src/zcompile/zcompile_main.c
-src/knot/common.h
-src/knot/main.c
-src/knot/ctl/knotc_main.c
-src/knot/ctl/process.c
-src/knot/ctl/process.h
-src/knot/ctl/remote.c
-src/knot/ctl/remote.h
-src/knot/other/debug.h
-src/knot/stat/gatherer.c
-src/knot/stat/gatherer.h
-src/knot/stat/stat.h
-src/knot/stat/stat.c
-src/knot/stat/stat-common.h
-src/knot/server/dthreads.c
-src/knot/server/dthreads.h
-src/knot/server/server.c
-src/knot/server/server.h
-src/knot/server/socket.c
-src/knot/server/socket.h
-src/knot/server/tcp-handler.c
-src/knot/server/tcp-handler.h
-src/knot/server/xfr-handler.c
-src/knot/server/xfr-handler.h
-src/knot/server/udp-handler.c
-src/knot/server/udp-handler.h
-src/knot/server/zones.c
-src/knot/server/zones.h
-src/knot/server/journal.c
-src/knot/server/journal.h
-src/knot/server/notify.c
-src/knot/server/notify.h
-src/knot/server/rrl.c
-src/knot/server/rrl.h
-src/knot/ctl/process.c
-src/knot/ctl/process.h
-src/knot/conf/cf-lex.l
-src/knot/conf/cf-parse.y
-src/knot/conf/conf.c
-src/knot/conf/conf.h
-src/knot/conf/logconf.c
-src/knot/conf/logconf.h
-src/knot/zone/zone-dump.c
-src/knot/zone/zone-dump.h
-src/knot/zone/zone-load.c
-src/knot/zone/zone-load.h
-src/knot/zone/zone-dump-text.h
-src/knot/zone/zone-dump-text.c
-src/zcompile/tests/unittests_zp_main.c
-src/zcompile/tests/zcompile_tests.c
-src/zcompile/zcompile-error.c
-src/tests/unittests_main.c
-src/tests/common/acl_tests.c
-src/tests/common/acl_tests.h
-src/tests/common/events_tests.c
-src/tests/common/events_tests.h
-src/tests/common/skiplist_tests.c
-src/tests/common/skiplist_tests.h
-src/tests/common/slab_tests.c
-src/tests/common/slab_tests.h
-src/tests/common/fdset_tests.c
-src/tests/common/fdset_tests.h
-src/tests/knot/dthreads_tests.c
-src/tests/knot/dthreads_tests.h
-src/tests/knot/conf_tests.c
-src/tests/knot/conf_tests.h
-src/tests/knot/journal_tests.c
-src/tests/knot/journal_tests.h
-src/tests/knot/server_tests.c
-src/tests/knot/server_tests.h
-src/tests/knot/rrl_tests.c
-src/tests/knot/rrl_tests.h
-src/tests/libknot/unittests_libknot.c
-src/tests/libknot/libknot/dname_tests.c
-src/tests/libknot/libknot/dname_tests.h
-src/tests/libknot/libknot/edns_tests.c
-src/tests/libknot/libknot/edns_tests.h
-src/tests/libknot/libknot/node_tests.c
-src/tests/libknot/libknot/node_tests.h
-src/tests/libknot/libknot/rdata_tests.c
-src/tests/libknot/libknot/rdata_tests.h
-src/tests/libknot/libknot/response_tests.c
-src/tests/libknot/libknot/response_tests.h
-src/tests/libknot/libknot/rrset_tests.c
-src/tests/libknot/libknot/rrset_tests.h
-src/tests/libknot/libknot/zone_tests.c
-src/tests/libknot/libknot/zone_tests.h
-src/tests/libknot/libknot/zonedb_tests.c
-src/tests/libknot/libknot/zonedb_tests.h
-src/tests/libknot/libknot/cuckoo_tests.c
-src/tests/libknot/libknot/cuckoo_tests.h
-src/tests/libknot/libknot/dname_table_tests.h
-src/tests/libknot/libknot/dname_table_tests.c
-src/tests/libknot/libknot/packet_tests.c
-src/tests/libknot/libknot/packet_tests.h
-src/tests/libknot/libknot/query_tests.c
-src/tests/libknot/libknot/query_tests.h
-src/tests/libknot/libknot/nsec3_tests.c
-src/tests/libknot/libknot/nsec3_tests.h
-src/tests/libknot/realdata/unittests_libknot_realdata.c
-src/tests/libknot/realdata/libknot/packet_tests_realdata.c
-src/tests/libknot/realdata/libknot/packet_tests_realdata.h
-src/tests/libknot/realdata/libknot/dname_tests_realdata.c
-src/tests/libknot/realdata/libknot/dname_tests_realdata.h
-src/tests/libknot/realdata/libknot/edns_tests_realdata.c
-src/tests/libknot/realdata/libknot/edns_tests_realdata.h
-src/tests/libknot/realdata/libknot/node_tests_realdata.c
-src/tests/libknot/realdata/libknot/node_tests_realdata.h
-src/tests/libknot/realdata/libknot/rdata_tests_realdata.c
-src/tests/libknot/realdata/libknot/rdata_tests_realdata.h
-src/tests/libknot/realdata/libknot/response_tests_realdata.c
-src/tests/libknot/realdata/libknot/response_tests_realdata.h
-src/tests/libknot/realdata/libknot/rrset_tests_realdata.c
-src/tests/libknot/realdata/libknot/rrset_tests_realdata.h
-src/tests/libknot/realdata/libknot/zone_tests_realdata.c
-src/tests/libknot/realdata/libknot/zone_tests_realdata.h
-src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c
-src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h
-src/tests/libknot/realdata/libknot_tests_loader_realdata.c
-src/tests/libknot/realdata/libknot_tests_loader_realdata.h
-src/tests/libknot/libknot/zone_tree_tests.c
-src/tests/libknot/libknot/zone_tree_tests.h
-samples/Makefile.am
-src/libknot/tsig.h
-src/libknot/tsig.c
-src/libknot/tsig-op.c
-src/libknot/tsig-op.h
-src/tests/libknot/libknot/tsig_tests.h
-src/tests/libknot/libknot/tsig_tests.c
-src/knot/zone/semantic-check.c
-src/knot/zone/semantic-check.h
-src/tests/xfr_tests.h
-src/tests/xfr_tests.c
-src/common/base64.c
-src/common/base64.h
-doc/knot.texi
-doc/configuration.texi
-doc/indices.texi
-doc/installation.texi
-doc/introduction.texi
-doc/migration.texi
-doc/reference.texi
-doc/requirements.texi
-doc/security.texi
-doc/troubleshooting.texi
-doc/version.texi
-src/libknot/zone/zone-diff.h
-src/libknot/zone/zone-diff.c
-
-doc/running.texi
diff --git a/Knot.includes b/Knot.includes
deleted file mode 100644
index 8184956..0000000
--- a/Knot.includes
+++ /dev/null
@@ -1,13 +0,0 @@
-obj
-src/alloc
-src/ctl
-src/dnslib
-src/hash
-src/lib
-src/other
-src/server
-src/stat
-src/tests/libtap
-src/tests
-src/zoneparser
-src \ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
index a3ae405..282a5c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,2 +1,3 @@
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = src samples doc
+SUBDIRS = src samples doc man
+EXTRA_DIST = resource.sh
diff --git a/Makefile.in b/Makefile.in
index 4135b77..9bf4b44 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.12.6 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
-
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -51,25 +52,39 @@ build_triplet = @build@
host_triplet = @host@
subdir = .
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in $(top_srcdir)/configure AUTHORS COPYING \
- ChangeLog INSTALL NEWS ar-lib config.guess config.sub \
- install-sh ltmain.sh missing
+ $(srcdir)/Makefile.in $(top_srcdir)/configure \
+ $(top_srcdir)/src/zscanner/test/cases/06-0_INCLUDE.inin \
+ $(top_srcdir)/src/zscanner/test/cases/06-3_INCLUDE.inin \
+ $(top_srcdir)/src/zscanner/test/cases/06-4_INCLUDE.inin \
+ $(top_srcdir)/src/zscanner/test/run_tests.sh.in AUTHORS \
+ COPYING ChangeLog INSTALL NEWS THANKS ar-lib compile \
+ config.guess config.sub depcomp install-sh ltmain.sh missing \
+ ylwrap
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compiler_flags.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_ext.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_recvmmsg.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/src/config.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = src/zscanner/test/run_tests.sh \
+ src/zscanner/test/cases/06-3_INCLUDE.in \
+ src/zscanner/test/cases/06-4_INCLUDE.in \
+ src/zscanner/test/cases/06-0_INCLUDE.in
CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
@@ -88,10 +103,9 @@ RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
$(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
- cscope distdir dist dist-all distcheck
+ distdir dist dist-all distcheck
ETAGS = etags
CTAGS = ctags
-CSCOPE = cscope
DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
distdir = $(PACKAGE)-$(VERSION)
@@ -102,7 +116,6 @@ am__remove_distdir = \
&& rm -rf "$(distdir)" \
|| { sleep 5 && rm -rf "$(distdir)"; }; \
else :; fi
-am__post_remove_distdir = $(am__remove_distdir)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
@@ -128,15 +141,15 @@ am__relativize = \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
-DIST_ARCHIVES = $(distdir).tar.gz
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 $(distdir).tar.xz
GZIP_ENV = --best
-DIST_TARGETS = dist-gzip
distuninstallcheck_listfiles = find . -type f -print
am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
| sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
distcleancheck_listfiles = find . -type f -print
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -145,6 +158,7 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -159,7 +173,9 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+FSM_TYPE = @FSM_TYPE@
GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -193,6 +209,10 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RAGEL = @RAGEL@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -235,8 +255,12 @@ htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
+libcrypto_CFLAGS = @libcrypto_CFLAGS@
+libcrypto_LIBS = @libcrypto_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+liburcu_CFLAGS = @liburcu_CFLAGS@
+liburcu_LIBS = @liburcu_LIBS@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
@@ -246,16 +270,19 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+run_dir = @run_dir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
+storage_dir = @storage_dir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = src samples doc
+SUBDIRS = src samples doc man
+EXTRA_DIST = resource.sh
all: all-recursive
.SUFFIXES:
@@ -265,15 +292,15 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
- $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnits'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnits \
&& exit 0; \
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu Makefile
+ $(AUTOMAKE) --gnits Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -293,6 +320,14 @@ $(top_srcdir)/configure: $(am__configure_deps)
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
+src/zscanner/test/run_tests.sh: $(top_builddir)/config.status $(top_srcdir)/src/zscanner/test/run_tests.sh.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/zscanner/test/cases/06-3_INCLUDE.in: $(top_builddir)/config.status $(top_srcdir)/src/zscanner/test/cases/06-3_INCLUDE.inin
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/zscanner/test/cases/06-4_INCLUDE.in: $(top_builddir)/config.status $(top_srcdir)/src/zscanner/test/cases/06-4_INCLUDE.inin
+ cd $(top_builddir) && $(SHELL) ./config.status $@
+src/zscanner/test/cases/06-0_INCLUDE.in: $(top_builddir)/config.status $(top_srcdir)/src/zscanner/test/cases/06-0_INCLUDE.inin
+ cd $(top_builddir) && $(SHELL) ./config.status $@
mostlyclean-libtool:
-rm -f *.lo
@@ -304,12 +339,12 @@ distclean-libtool:
-rm -f libtool config.lt
# This directory's subdirectories are mostly independent; you can cd
-# into them and run 'make' without going through this Makefile.
-# To change the values of 'make' variables: instead of editing Makefiles,
-# (1) if the variable is set in 'config.status', edit 'config.status'
-# (which will cause the Makefiles to be regenerated when you run 'make');
-# (2) otherwise, pass the desired values on the 'make' command line.
-$(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS):
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
@fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
@@ -319,11 +354,7 @@ $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS):
done; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
- case "$@" in \
- distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
- *) list='$(SUBDIRS)' ;; \
- esac; \
- for subdir in $$list; do \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
@@ -337,6 +368,37 @@ $(RECURSIVE_TARGETS) $(RECURSIVE_CLEAN_TARGETS):
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
@@ -345,10 +407,6 @@ ctags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
done
-cscopelist-recursive:
- list='$(SUBDIRS)'; for subdir in $$list; do \
- test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) cscopelist); \
- done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -412,34 +470,16 @@ GTAGS:
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
-cscope: cscope.files
- test ! -s cscope.files \
- || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
-
-clean-cscope:
- -rm -f cscope.files
-
-cscope.files: clean-cscope cscopelist-recursive cscopelist
-
-cscopelist: cscopelist-recursive $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS) $(LISP)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
- -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
distdir: $(DISTFILES)
+ @case `sed 15q $(srcdir)/NEWS` in \
+ *"$(VERSION)"*) : ;; \
+ *) \
+ echo "NEWS not updated; not releasing" 1>&2; \
+ exit 1;; \
+ esac
$(am__remove_distdir)
test -d "$(distdir)" || mkdir "$(distdir)"
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -505,36 +545,40 @@ distdir: $(DISTFILES)
|| chmod -R a+r "$(distdir)"
dist-gzip: distdir
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
- $(am__post_remove_distdir)
-
+ $(am__remove_distdir)
dist-bzip2: distdir
tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
- $(am__post_remove_distdir)
+ $(am__remove_distdir)
dist-lzip: distdir
tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
- $(am__post_remove_distdir)
+ $(am__remove_distdir)
+dist-lzma: distdir
+ tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+ $(am__remove_distdir)
dist-xz: distdir
tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
- $(am__post_remove_distdir)
+ $(am__remove_distdir)
dist-tarZ: distdir
tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
- $(am__post_remove_distdir)
+ $(am__remove_distdir)
dist-shar: distdir
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
- $(am__post_remove_distdir)
+ $(am__remove_distdir)
dist-zip: distdir
-rm -f $(distdir).zip
zip -rq $(distdir).zip $(distdir)
- $(am__post_remove_distdir)
+ $(am__remove_distdir)
-dist dist-all:
- $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
- $(am__post_remove_distdir)
+dist dist-all: distdir
+ tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+ tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+ tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+ $(am__remove_distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
@@ -545,6 +589,8 @@ distcheck: dist
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
*.tar.bz2*) \
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lzma*) \
+ lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
*.tar.lz*) \
lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
*.tar.xz*) \
@@ -556,9 +602,9 @@ distcheck: dist
*.zip*) \
unzip $(distdir).zip ;;\
esac
- chmod -R a-w $(distdir)
- chmod u+w $(distdir)
- mkdir $(distdir)/_build $(distdir)/_inst
+ chmod -R a-w $(distdir); chmod u+w $(distdir)
+ mkdir $(distdir)/_build
+ mkdir $(distdir)/_inst
chmod a-w $(distdir)
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
@@ -590,7 +636,7 @@ distcheck: dist
&& $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
&& cd "$$am__cwd" \
|| exit 1
- $(am__post_remove_distdir)
+ $(am__remove_distdir)
@(echo "$(distdir) archives ready for distribution: "; \
list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
@@ -725,15 +771,13 @@ ps-am:
uninstall-am:
-.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) \
- cscopelist-recursive ctags-recursive install-am install-strip \
- tags-recursive
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
- all all-am am--refresh check check-am clean clean-cscope \
- clean-generic clean-libtool cscope cscopelist \
- cscopelist-recursive ctags ctags-recursive dist dist-all \
- dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ dist-xz \
+ all all-am am--refresh check check-am clean clean-generic \
+ clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \
+ dist-gzip dist-lzip dist-lzma dist-shar dist-tarZ dist-xz \
dist-zip distcheck distclean distclean-generic \
distclean-libtool distclean-tags distcleancheck distdir \
distuninstallcheck dvi dvi-am html html-am info info-am \
diff --git a/NEWS b/NEWS
index e69de29..f3c7909 100644
--- a/NEWS
+++ b/NEWS
@@ -0,0 +1,400 @@
+Knot DNS NEWS
+
+v1.3.0-rc3 - Jun 28, 2013
+-------------------------
+
+Features:
+ * Utility to estimate memory consumption (see 'knotc memstats')
+ * PID file is not created when running on foreground
+ * UNIX sockets support for knotc
+ * Configurable 'rundir' and 'storage'
+
+Bugfixes:
+ * IXFR with an arbitrary number of diffs
+ * Processing of knotc TSIG keyfile
+ * Atomic PID file writing, removed deprecated 'knotc start'
+ * Performance regression when RRSIGs came before covered RRs in AXFR
+
+v1.3.0-rc2 - Jun 14, 2013
+-------------------------
+
+Bugfixes:
+ * Label compression related bug
+ * Proper resolution of some CNAME chains
+ * Unstable response rate in rare cases
+ * Several log messages
+
+v1.3.0-rc1 - Jun 4, 2013
+---------------------------
+
+Features:
+ * Faster zone parser
+ * Full support for EUI and ILNP resource records
+ * Lower memory footprint for large zones
+ * No compilation of zones
+ * Improved scheduling of zone transfers
+ * Logging of serials and timing information for zone transfers
+ * Config: 'groups' keyword allowing to create groups of remotes
+ * Config: 'include' keyword allowing other file includes
+ * Client utilities: kdig, khost, knsupdate
+ * Server identification using TXT/CH queries (RFC 4892)
+ * Improved build scripts
+ * Improved dname compression and performance
+Bugfixes:
+ * Fixed creating of PID file when dropping privileges
+
+v1.2.0 - Mar 29, 2013
+---------------------
+
+Bugfixes:
+ * Memory leaks
+
+v1.2.0-rc4 - Mar 22, 2013
+-------------------------
+
+Features:
+ * knotc 'zonestatus' command
+
+Bugfixes:
+ * Check for broken recvmmsg() implementation
+ * Changing logfile ownership before dropping privileges
+ * knotc respects 'control' section from configuration
+ * RRL: resolved bucket collisions
+ * RRL: updated bucket mapping to conform RRL technical memo
+
+v1.2.0-rc3 - Mar 1, 2013
+------------------------
+
+Features:
+ * Response rate limiting (see documentation)
+
+Bugfixes:
+ * Fixed OpenBSD build
+ * Responses to ANY should contain RRSIGs
+
+v1.2.0-rc2 - Feb 15, 2013
+-------------------------
+
+Bugfixes:
+ * Fixed processing of some non-standard dnames.
+ * Correct checking of label length bounds in some cases.
+ * More compliant rcodes in case of DDNS/TSIG failures.
+ * Correct processing of malformed DDNS prereq section.
+
+v1.2.0-rc1 - Jan 4, 2013
+------------------
+
+Features:
+ * Dynamic updates, including forwarding (limited on signed zones)
+ * Updated remote control utility
+ * Configurable TCP timeouts
+ * LOC RR support
+
+v1.1.3 - Dec 19, 2012
+---------------------
+
+Bugfixes:
+ * Updated manpage.
+
+v1.1.3-rc1 - Dec 6, 2012
+------------------------
+
+Bugfixes:
+ * Fixed answering DS queries (RRSIGs not together with DS, AA bit
+ missing).
+ * Fixed setting ARCOUNT in some error responses with EDNS enabled.
+ * Fixed crash when compiling zone zone with NSEC3PARAM but no NSEC3
+ and semantic checks enabled.
+
+
+v1.1.2 - Nov 21, 2012
+---------------------
+
+Bugfixes:
+ * Fixed debug message.
+
+
+v1.1.2-rc1 - Nov 14, 2012
+-------------------------
+
+Bugfixes:
+ * Fixed crash on reload when config contained duplicate zones.
+ * Fixed scheduling of transfers.
+
+
+v1.1.1 - Oct 31, 2012
+---------------------
+
+Bugfixes:
+ * Fixed assertion failing when asking directly for a wildcard name.
+
+
+v1.1.1-rc1 - Oct 23, 2012
+-------------------------
+
+Bugfixes:
+ * Crash after IXFR in certain cases when adding RRSIG in an IXFR.
+ * Fixed behaviour when incoming IXFR removes a zone cut. Previously
+ occluded names now become properly visible. Previously lead to a
+ crash when the server was asked for the previously occluded name.
+ * Fixed handling of zero-length strings in text zone dump. Caused the
+ compilation to fail.
+ * Fixed TSIG algorithm name comparison - the names should be in
+ canonical form.
+ * Fixed handling unknown RR types with type less than 251.
+
+Features:
+ * Improved compression of packets. Out-of-zone dnames present in RDATA
+ were not compressed.
+ * Slave zones are now automatically refreshed after startup.
+ * Proper response to IXFR/UDP query (returns SOA in Authority section).
+
+
+v1.1.0 - Aug 31, 2012
+---------------------
+
+Bugfixes:
+ * Syncing journal to zone was not updating the compiled zone database.
+
+Other improvements:
+ * Better checks of corrupted zone database.
+
+
+v1.1.0-rc2 - Aug 23, 2012
+-------------------------
+
+New features:
+ * Signing SOA with TSIG queries when checking zone version with master.
+
+Bugfixes:
+ * Fixed ixfr-from-differences journal generation in case of IPSECKEY
+ and APL records.
+ * Fixed possible leak on server shutdown with a pending transfer.
+
+Other improvements:
+ * Improved user manual.
+
+
+v1.1.0-rc1 - Aug 17, 2012
+-------------------------
+
+New features:
+ * Optionally disable ANY queries for authoritative answers.
+ * Dropping identical records in zone and incoming transfers.
+ * Support for '/' in zone names.
+ * Generating journal from reloaded zone (EXPERIMENTAL).
+ * Outgoing-only interfaces in configuration file.
+ * Following DNAME if the synthetized name is in the same zone.
+
+Bugfixes:
+ * Crash when zone contained RRSIG signing a CNAME, but did not
+ contain the CNAME.
+ * Malformed packets parsing.
+ * Failed IXFR caused memory leaks.
+ * Failed IXFR might have resulted in inconsistent zone structures.
+ * Fixed answering to +dnssec queries when NSEC3 chain is corrupted.
+ * Fixed answering when transitioning from NSEC3 to NSEC.
+ * Fixed answering when zone contains multiple NSEC3 chains.
+ * Handling RRSets with different TTLs - TTL from the first RR is used.
+ * Synchronization of zone reload and zone transfers.
+ * Fixed build on NetBSD 5 and FreeBSD.
+ * Fixed binding to both IPv4 and IPv6 at the same time on special
+ interfaces.
+ * Fixed access rights of created files.
+ * Semantic checks corrupted RDATA domain names which are covered by
+ wildcard in the same zone.
+
+Other improvements:
+ * IXFR-in optimized.
+ * Many zones loading optimized.
+ * More detailed log messages (mostly transfer-related).
+ * Copying Question section to error responses.
+ * Using zone name from config file as default origin in zone file.
+ * Additional records are now added to response also from
+ wildcard-covered names.
+
+v1.0.6 - Jun 13, 2012
+---------------------
+
+Bugfixes
+ * Fixed potential problems with RCU synchronization.
+ * Adding NSEC/NSEC3 for all wildcard CNAMEs in the response.
+
+
+v1.0.5 - May 17, 2012
+---------------------
+
+Bugfixes:
+ * Fixed bug with creating journal files.
+
+
+v1.0.4 - May 16, 2012
+---------------------
+
+New features:
+ * Parallel loading of zones to the server.
+ * RFC3339-complaint format of log time.
+ * Support for TLSA (RR type 52).
+ * knotc checkzone (as a dry-run of zone compile).
+ * knotc refresh for forcing Knot to update all zones from master
+ servers.
+ * Reopening log files upon start (used to truncate them).
+
+Bugfixes:
+ * Copying OPCODE and RD bit from query to NOTIMPL responses.
+ * Corrected response to CNAME queries if the canonical name was also
+ an alias (was adding the whole CNAME chain to the response).
+ * Fixed crash when NS or MX points to an alias.
+ * Fixed problem with early closing of filedescriptors (lead to crash
+ when compiling and loading or bootstrapping and restarting the server
+ with a lot of zones).
+
+Other improvements:
+ * Significantly sped up IXFR-in and reduced its memory requirements.
+
+
+v1.0.3 - Apr 17, 2012
+---------------------
+
+Bugfixes:
+ * Corrected handling of EDNS0 when TCP is used (was applying the UDP size limit).
+ * Fixed slow compilation of zones.
+ * Fixed potential crash with many concurrent transfers.
+ * Fixed missing include for FreeBSD.
+
+
+v1.0.2 - Apr 13, 2012
+---------------------
+
+New features:
+ * Configuration checker (invoked via knotc).
+ * Specifying source interface for transfers and NOTIFY requests directly.
+
+Bugfixes:
+ * Fixed leak when querying non-existing name and zone SOA TTL > minimal.
+ * Fixed some minor bugs in tansfers.
+
+Other improvements:
+ * Improved log messages (added date and time, better specification of XFR remote).
+ * Improved saving incoming IXFR to journal (memory optimized).
+ * Now using system scheduler (better for Linux).
+ * Decreased thread stack size.
+
+
+v1.0.1 - Mar 9, 2012
+--------------------
+
+New features:
+ * Implemented jitter to REFRESH/RETRY timers.
+ * Implemented magic bytes for journal.
+ * Improved error messages.
+
+Bugfixes:
+ * Problem with creating IXFR journal for bootstrapped zone.
+ * Race condition in processing NOTIFY/SOA queries.
+ * Leak when reloading zone with NSEC3.
+ * Processing of APL RR.
+ * TSIG improper assignment of algorithm type.
+
+
+v1.0.0 - Feb 29, 2012
+---------------------
+
+New features:
+ * Support for subnets in ACL.
+ * Debug messages enabling in configure.
+ * Optimized memory consuption of zone structures.
+
+Bugfixes:
+ * Memory errors and leaks.
+ * Fixed improper handling of failed IXFR/IN.
+ * Several other minor bugfixes.
+
+
+v1.0-rc1 - Feb 14, 2012
+-----------------------
+
+New features:
+ * NSID support (RFC5001).
+ * Root zone support.
+ * Automatic zone compiling on server start.
+ * Setting user to run Knot under in config file.
+ * Dropping privileges after binding to port 53.
+ + Support for Linux capabilities(7).
+ * Setting source address of outgoing transfers in config file.
+ * Custom PID file.
+ * CNAME loop detection.
+ * Timeout on TCP connections.
+ * Basic defense against DoS attacks.
+
+Bugfixes:
+ * Fixed IXFR processing.
+ * Patched URCU so that it compiles on architectures without TLS in compiler (NetBSD, OpenBSD).
+ * Fixed response to DS query at parent zone.
+ * A lot of other bugfixes.
+
+
+v0.9.1 - Jan 20, 2012
+---------------------
+
+New features:
+ * RRSet rotation
+
+Bugfixes:
+ * Fixed build on BSD.
+ * Fixes in parsing and dumping of zone
+ - types IPSECKEY, WKS, DLV, APL, NSAP
+
+Other changes:
+ * Replaced pseudo-random number generator by one with MIT/BSD license.
+
+
+v0.9 - Jan 13, 2012
+-------------------
+
+New features:
+ * TSIG support in both client and server.
+ * Use of sendmmsg() on Linux 3.0+ (improves performance).
+
+Bugfixes:
+ * Knot was not accepting AXFR-style IXFR with first SOA in a separate
+ packet (i.e. from Power DNS).
+ * Wrong SOA TTL in negative answers.
+ * Wrong max packet size for outgoing transfers (was causing the
+ packets to be malformed).
+ * Wrong handling of WKS record in zone compiler.
+ * Problems with zone bootstrapping.
+
+
+v0.8.1 - Dec 1, 2011
+--------------------
+
+Bugfixes:
+ * Handling SPF record.
+ * Wrong text dump of unknown records.
+
+
+v0.8.0 - Beta Release - Nov 3, 2011
+-----------------------------------
+
+Features:
+ * AXFR-in/-out
+ * IXFR-in/-out
+ * EDNS0
+ * DNSSEC
+ * NSEC3
+ * IPv6
+ * Runtime reconfiguration
+
+Known issues:
+ * Missing support for TSIG
+ * Root zone support
+ * NSID support
+ * Other DNS classes than IN
+ * RRSet rotation not implmented
+ * Dynamic update support
+ * IXFR code might be flaky sometimes
+ * IXFR may be slow when too much (10 000+) RRSets are transfered at once
+
+Platforms (tested on):
+ * Linux (2.6.x and newer), FreeBSD 8.2, Mac OS X 10.6, 10.7
diff --git a/README b/README
index d50168f..74dea58 100644
--- a/README
+++ b/README
@@ -1,19 +1,45 @@
Dependencies
============
+
Knot DNS has several dependencies:
* libtool
* autoconf > 2.65
* flex >= 2.5.31
* bison >= 2.3
* libssl >= 0.9.8
-* liburcu >= 0.5.4 (available as packages or as a sources from http://lttng.org/urcu)
+* liburcu >= 0.5.4
Optional packages:
-* libcap-ng >= 0.6.4 for POSIX 1003.1e capabilites(7)
+* libcap-ng >= 0.6.4 (for POSIX 1003.1e capabilites(7))
+* ragel (for fast zone parsing)
+
+Dependencies for building documentation:
+* texinfo
+
+Knot DNS requires compiler to support atomic intrinsics.
+GCC version at least 4.1 supports legacy atomic builtins, however 4.7
+or newer is preferred.
+Clang supports atomics since version 2.9.
+
+By default Knot DNS is distributed with a slower zone file parser because of
+smaller source file and quick compile time. In most cases it is sufficient.
+If you plan to process large zone files, it is recomended to build Knot DNS
+using ./configure --enable-fastparser. In this case Ragel compiler is required
+and it is normal if the C compiler takes much more time (minutes).
Installation
============
+Knot DNS may be already included in your operating system distribution and
+therefore can be installed from packages (Linux) or ports (BSD). This is
+always preferred unless you want to test the latest features, contribute to
+Knot development, or you just know what you are doing.
+
+Following sections describe how to build Knot DNS from the source code.
+
+Installation on Debian based distributions
+==========================================
+
The following steps should work (verified in VirtualBox only)
on the distribution/architecture/release combinations as listed bellow.
@@ -49,7 +75,7 @@ $ sudo make install
$ sudo ldconfig
Alternative packages for I386:
-$ # the required version of liburcu is not available in the default package
+$ # the required version of liburcu is not available in the default package
$ # sources.
$
$ wget http://bd.archive.ubuntu.com/ubuntu/pool/universe/libu/liburcu/liburcu0_0.5.4-1_i386.deb
@@ -57,6 +83,38 @@ $ wget http://bd.archive.ubuntu.com/ubuntu/pool/universe/libu/liburcu/liburcu-de
$ sudo dpkg -i liburcu0_0.5.4-1_i386.deb
$ sudo dpkg -i liburcu-dev_0.5.4-1_i386.deb
+Installation on Fedora
+======================
+
+Notice: Knot DNS is available in official distribution repositories since
+Fedora 18 (Spherical Cow). Search for 'knot' package.
+
+All commands with the '#' prompt should be run as the root user, commands with
+the '$' prompt should be run as a regular non-root user.
+
+Update the system:
+# yum upgrade
+
+Ensure all base development tools are available:
+# yum install @buildsys-build
+
+Ensure all prerequisites are installed:
+# yum install libtool autoconf flex bison openssl-devel userspace-rcu-devel
+
+You can also install optional packages:
+# yum install libcap-ng-devel ragel
+
+Download the latest source code from Git and compile it:
+$ git clone git://git.nic.cz/knot-dns.git
+$ cd knot
+$ autoreconf -if
+$ ./configure
+$ make
+
+Install Knot DNS into system (run only if you really know what these commands do):
+# make install
+# ldconfig
+
Installation on BSD
===================
@@ -81,16 +139,18 @@ $ sudo make install
Installation on OpenBSD/NetBSD
==============================
+
Also works for OS X, if you don't want to install gcc from ports.
Prerequisites:
- liburcu needs patch for absent compiler TLS capability
- patch is located in "scripts/urcu-tls-compat.patch"
- patch compatible with liburcu-0.6.7
- liburcu >= 0.7.0 works out of the box
+- flex and bison from packages
$ mkdir liburcu && cd liburcu
$ wget "http://lttng.org/files/urcu/userspace-rcu-0.6.7.tar.bz2"
-$ patch -p1 < ../scripts/urcu-tls-compat.patch
+$ patch -p1 < ../scripts/urcu-tls-compat.patch
$ autoconf && ./configure && make && sudo make install
$ # or follow installation instructions in INSTALL
@@ -105,14 +165,16 @@ Not all prerequisites are preinstalled for OS X.
- liburcu requires gcc-4.6 from MacPorts, as it depends on __thread keyword
$ CC=gcc-mp-4.6 ARCH=x86_64 ./configure
$ make && sudo make install
+- liburcu >= 0.7.0 works with supplied compiler, however ARCH must still be set
+ - alternative is to set it with configure parameter --target
-Compiling Knot DNS with gcc-mp-4.6 is recommended, but not necessary.
+Compiling Knot DNS with gcc-mp-4.6 is recommended, but not necessary.
Running
=======
-First, each server needs configuration file.
-Please see samples/knot.sample.conf for reference.
+First, each server needs configuration file.
+Please see samples/knot.sample.conf for reference.
Minimal configuration can be found in samples/knot.min.conf
Configuration zone has to specify:
* storage for PID files, compiled zones etc.
@@ -121,19 +183,11 @@ Configuration zone has to specify:
$ cp samples/knot.min.conf myserver.conf
$ vim myserver.conf # or your favourite text editor
-
-Second, zone files have to be compiled to binary form in order for server to
-load them. Binary 'knotc' (controller) offers functionality for everything from
-zone file management to controlling server instance. Most important parameter
-is '-c' that specifies config file for our server. Compiled zones are saved to
-storage defined in 'storage' variable in configuration.
-
$ knotc -h # see what it can do
-Copy zone to the specified directory and compile.
+Prepare working directory.
$ mkdir -p /tmp/knot-minimal/samples; cp samples/example.com.zone /tmp/knot-minimal/samples/
-$ knotc -c myserver.conf compile # compile zone files to binary format
Third, lets load server. You can do this by running 'knotd' directly, or with
'knotc' as well. Server is able to run in daemonized or interactive mode.
@@ -146,37 +200,10 @@ Running as daemon
Controller runs server in daemonized mode as default. Disadvantage is, that
it closes stdout/stderr so you need to set up either syslog or logging to
-own files in the configuration. Controller parameter '-w' waits for the
+own files in the configuration. Controller parameter '-w' waits for the
operation to finish. Let's test server functionality.
$ knotc -c myserver.conf -w start # start server
$ dig @$ADDR -p $PORT example.com # issue a query and see result
$ ...
$ knotc -c myserver.conf -w stop # stop server
-
-Also, keep in mind that zone files have to be compiled before they are loaded
-to server. Workflow is as follows:
-
-$ knotc -c myserver.conf -w start
-$ <edit zonefile>
-$ knotc -c myserver.conf compile # compile zones to binary format
-$ knotc -c myserver.conf reload # reconfigures server on-the-fly
-$ dig @$ADDR -p $PORT example.com # issue a query and see result
-$ ...
-$ knotc -c myserver.conf stop
-
-Supported features
-==================
-
-DNS functions:
-* AXFR/IXFR (master and slave)
-* EDNS0
-* DNSSEC
-* NSEC3
-* Unknown RR types
-
-Server features:
-* Adding/removing zones on-the-fly
-* Reconfiguring server instance on-the-fly
-* IPv6 support
-* Semantic checks of loaded zone
diff --git a/RELNOTES b/RELNOTES
deleted file mode 100644
index a5b04ce..0000000
--- a/RELNOTES
+++ /dev/null
@@ -1,355 +0,0 @@
-v1.2.0 - Mar 29, 2013
----------------------
-
-Bugfixes:
- * Memory leaks
-
-v1.2.0-rc4 - Mar 22, 2013
--------------------------
-
-Features:
- * knotc 'zonestatus' command
-
-Bugfixes:
- * Check for broken recvmmsg() implementation
- * Changing logfile ownership before dropping privileges
- * knotc respects 'control' section from configuration
- * RRL: resolved bucket collisions
- * RRL: updated bucket mapping to conform RRL technical memo
-
-v1.2.0-rc3 - Mar 1, 2013
-------------------------
-
-Features:
- * Response rate limiting (see documentation)
-
-Bugfixes:
- * Fixed OpenBSD build
- * Responses to ANY should contain RRSIGs
-
-v1.2.0-rc2 - Feb 15, 2013
--------------------------
-
-Bugfixes:
- * Fixed processing of some non-standard dnames.
- * Correct checking of label length bounds in some cases.
- * More compliant rcodes in case of DDNS/TSIG failures.
- * Correct processing of malformed DDNS prereq section.
-
-v1.2.0-rc1 - Jan 4, 2013
-------------------
-
-Features:
- * Dynamic updates, including forwarding (limited on signed zones)
- * Updated remote control utility
- * Configurable TCP timeouts
- * LOC RR support
-
-v1.1.3 - Dec 19, 2012
----------------------
-
-Bugfixes:
- * Updated manpage.
-
-v1.1.3-rc1 - Dec 6, 2012
-------------------------
-
-Bugfixes:
- * Fixed answering DS queries (RRSIGs not together with DS, AA bit
- missing).
- * Fixed setting ARCOUNT in some error responses with EDNS enabled.
- * Fixed crash when compiling zone zone with NSEC3PARAM but no NSEC3
- and semantic checks enabled.
-
-
-v1.1.2 - Nov 21, 2012
----------------------
-
-Bugfixes:
- * Fixed debug message.
-
-
-v1.1.2-rc1 - Nov 14, 2012
--------------------------
-
-Bugfixes:
- * Fixed crash on reload when config contained duplicate zones.
- * Fixed scheduling of transfers.
-
-
-v1.1.1 - Oct 31, 2012
----------------------
-
-Bugfixes:
- * Fixed assertion failing when asking directly for a wildcard name.
-
-
-v1.1.1-rc1 - Oct 23, 2012
--------------------------
-
-Bugfixes:
- * Crash after IXFR in certain cases when adding RRSIG in an IXFR.
- * Fixed behaviour when incoming IXFR removes a zone cut. Previously
- occluded names now become properly visible. Previously lead to a
- crash when the server was asked for the previously occluded name.
- * Fixed handling of zero-length strings in text zone dump. Caused the
- compilation to fail.
- * Fixed TSIG algorithm name comparison - the names should be in
- canonical form.
- * Fixed handling unknown RR types with type less than 251.
-
-Features:
- * Improved compression of packets. Out-of-zone dnames present in RDATA
- were not compressed.
- * Slave zones are now automatically refreshed after startup.
- * Proper response to IXFR/UDP query (returns SOA in Authority section).
-
-
-v1.1.0 - Aug 31, 2012
----------------------
-
-Bugfixes:
- * Syncing journal to zone was not updating the compiled zone database.
-
-Other improvements:
- * Better checks of corrupted zone database.
-
-
-v1.1.0-rc2 - Aug 23, 2012
--------------------------
-
-New features:
- * Signing SOA with TSIG queries when checking zone version with master.
-
-Bugfixes:
- * Fixed ixfr-from-differences journal generation in case of IPSECKEY
- and APL records.
- * Fixed possible leak on server shutdown with a pending transfer.
-
-Other improvements:
- * Improved user manual.
-
-
-v1.1.0-rc1 - Aug 17, 2012
--------------------------
-
-New features:
- * Optionally disable ANY queries for authoritative answers.
- * Dropping identical records in zone and incoming transfers.
- * Support for '/' in zone names.
- * Generating journal from reloaded zone (EXPERIMENTAL).
- * Outgoing-only interfaces in configuration file.
- * Following DNAME if the synthetized name is in the same zone.
-
-Bugfixes:
- * Crash when zone contained RRSIG signing a CNAME, but did not
- contain the CNAME.
- * Malformed packets parsing.
- * Failed IXFR caused memory leaks.
- * Failed IXFR might have resulted in inconsistent zone structures.
- * Fixed answering to +dnssec queries when NSEC3 chain is corrupted.
- * Fixed answering when transitioning from NSEC3 to NSEC.
- * Fixed answering when zone contains multiple NSEC3 chains.
- * Handling RRSets with different TTLs - TTL from the first RR is used.
- * Synchronization of zone reload and zone transfers.
- * Fixed build on NetBSD 5 and FreeBSD.
- * Fixed binding to both IPv4 and IPv6 at the same time on special
- interfaces.
- * Fixed access rights of created files.
- * Semantic checks corrupted RDATA domain names which are covered by
- wildcard in the same zone.
-
-Other improvements:
- * IXFR-in optimized.
- * Many zones loading optimized.
- * More detailed log messages (mostly transfer-related).
- * Copying Question section to error responses.
- * Using zone name from config file as default origin in zone file.
- * Additional records are now added to response also from
- wildcard-covered names.
-
-v1.0.6 - Jun 13, 2012
----------------------
-
-Bugfixes
- * Fixed potential problems with RCU synchronization.
- * Adding NSEC/NSEC3 for all wildcard CNAMEs in the response.
-
-
-v1.0.5 - May 17, 2012
----------------------
-
-Bugfixes:
- * Fixed bug with creating journal files.
-
-
-v1.0.4 - May 16, 2012
----------------------
-
-New features:
- * Parallel loading of zones to the server.
- * RFC3339-complaint format of log time.
- * Support for TLSA (RR type 52).
- * knotc checkzone (as a dry-run of zone compile).
- * knotc refresh for forcing Knot to update all zones from master
- servers.
- * Reopening log files upon start (used to truncate them).
-
-Bugfixes:
- * Copying OPCODE and RD bit from query to NOTIMPL responses.
- * Corrected response to CNAME queries if the canonical name was also
- an alias (was adding the whole CNAME chain to the response).
- * Fixed crash when NS or MX points to an alias.
- * Fixed problem with early closing of filedescriptors (lead to crash
- when compiling and loading or bootstrapping and restarting the server
- with a lot of zones).
-
-Other improvements:
- * Significantly sped up IXFR-in and reduced its memory requirements.
-
-
-v1.0.3 - Apr 17, 2012
----------------------
-
-Bugfixes:
- * Corrected handling of EDNS0 when TCP is used (was applying the UDP size limit).
- * Fixed slow compilation of zones.
- * Fixed potential crash with many concurrent transfers.
- * Fixed missing include for FreeBSD.
-
-
-v1.0.2 - Apr 13, 2012
----------------------
-
-New features:
- * Configuration checker (invoked via knotc).
- * Specifying source interface for transfers and NOTIFY requests directly.
-
-Bugfixes:
- * Fixed leak when querying non-existing name and zone SOA TTL > minimal.
- * Fixed some minor bugs in tansfers.
-
-Other improvements:
- * Improved log messages (added date and time, better specification of XFR remote).
- * Improved saving incoming IXFR to journal (memory optimized).
- * Now using system scheduler (better for Linux).
- * Decreased thread stack size.
-
-
-v1.0.1 - Mar 9, 2012
---------------------
-
-New features:
- * Implemented jitter to REFRESH/RETRY timers.
- * Implemented magic bytes for journal.
- * Improved error messages.
-
-Bugfixes:
- * Problem with creating IXFR journal for bootstrapped zone.
- * Race condition in processing NOTIFY/SOA queries.
- * Leak when reloading zone with NSEC3.
- * Processing of APL RR.
- * TSIG improper assignment of algorithm type.
-
-
-v1.0.0 - Feb 29, 2012
----------------------
-
-New features:
- * Support for subnets in ACL.
- * Debug messages enabling in configure.
- * Optimized memory consuption of zone structures.
-
-Bugfixes:
- * Memory errors and leaks.
- * Fixed improper handling of failed IXFR/IN.
- * Several other minor bugfixes.
-
-
-v1.0-rc1 - Feb 14, 2012
------------------------
-
-New features:
- * NSID support (RFC5001).
- * Root zone support.
- * Automatic zone compiling on server start.
- * Setting user to run Knot under in config file.
- * Dropping privileges after binding to port 53.
- + Support for Linux capabilities(7).
- * Setting source address of outgoing transfers in config file.
- * Custom PID file.
- * CNAME loop detection.
- * Timeout on TCP connections.
- * Basic defense against DoS attacks.
-
-Bugfixes:
- * Fixed IXFR processing.
- * Patched URCU so that it compiles on architectures without TLS in compiler (NetBSD, OpenBSD).
- * Fixed response to DS query at parent zone.
- * A lot of other bugfixes.
-
-
-v0.9.1 - Jan 20, 2012
----------------------
-
-New features:
- * RRSet rotation
-
-Bugfixes:
- * Fixed build on BSD.
- * Fixes in parsing and dumping of zone
- - types IPSECKEY, WKS, DLV, APL, NSAP
-
-Other changes:
- * Replaced pseudo-random number generator by one with MIT/BSD license.
-
-
-v0.9 - Jan 13, 2012
--------------------
-
-New features:
- * TSIG support in both client and server.
- * Use of sendmmsg() on Linux 3.0+ (improves performance).
-
-Bugfixes:
- * Knot was not accepting AXFR-style IXFR with first SOA in a separate
- packet (i.e. from Power DNS).
- * Wrong SOA TTL in negative answers.
- * Wrong max packet size for outgoing transfers (was causing the
- packets to be malformed).
- * Wrong handling of WKS record in zone compiler.
- * Problems with zone bootstrapping.
-
-
-v0.8.1 - Dec 1, 2011
---------------------
-
-Bugfixes:
- * Handling SPF record.
- * Wrong text dump of unknown records.
-
-
-v0.8.0 - Beta Release - Nov 3, 2011
------------------------------------
-
-Features:
- * AXFR-in/-out
- * IXFR-in/-out
- * EDNS0
- * DNSSEC
- * NSEC3
- * IPv6
- * Runtime reconfiguration
-
-Known issues:
- * Missing support for TSIG
- * Root zone support
- * NSID support
- * Other DNS classes than IN
- * RRSet rotation not implmented
- * Dynamic update support
- * IXFR code might be flaky sometimes
- * IXFR may be slow when too much (10 000+) RRSets are transfered at once
-
-Platforms (tested on):
- * Linux (2.6.x and newer), FreeBSD 8.2, Mac OS X 10.6, 10.7
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..7708731
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,37 @@
+Knot DNS THANKS file
+
+Knot DNS was originally written by CZ.NIC Labs. It would not be what
+it is today without the invaluable help of these people, who have
+reported problems, suggested improvements, or submitted actual code.
+Please help us keep this list complete and free from errors. Also see
+the AUTHORS file for the list of people with contributions significant
+enough to warrant copyright assignment.
+
+Anton Shterenlikht mexas@bristol.ac.uk
+Geert Hendrickx geert@hendrickx.be
+Michal 'vorner' Vaner vorner@ucw.cz
+Ondřej Caletka ondrej@caletka.cz
+Anand Buddhdev anandb@ripe.net
+
+================
+
+Local Variables:
+mode: text
+coding: utf-8
+End:
+
+
+Copyright (C) 2011 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/>.
diff --git a/aclocal.m4 b/aclocal.m4
index f6f3c23..4dcf33a 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,7 +1,8 @@
-# generated automatically by aclocal 1.12.6 -*- Autoconf -*-
-
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
+# Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -17,24 +18,187 @@ m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
[m4_warning([this file was generated for autoconf 2.69.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
-To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
-# Copyright (C) 2002-2012 Free Software Foundation, Inc.
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 1 (pkg-config-0.24)
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+# only at the first occurence in configure.ac, so if the first place
+# it's called might be skipped (such as if it is within an "if", you
+# have to call PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])# PKG_CHECK_MODULES
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.12'
+[am__api_version='1.11'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
-m4_if([$1], [1.12.6], [],
+m4_if([$1], [1.11.6], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
@@ -50,17 +214,19 @@ m4_define([_AM_AUTOCONF_VERSION], [])
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.12.6])dnl
+[AM_AUTOMAKE_VERSION([1.11.6])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
-# Copyright (C) 2011-2012 Free Software Foundation, Inc.
+# Copyright (C) 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_PROG_AR([ACT-IF-FAIL])
# -------------------------
# Try to determine the archiver interface, and trigger the ar-lib wrapper
@@ -116,15 +282,17 @@ AC_SUBST([AR])dnl
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
-# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
-# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
@@ -143,7 +311,7 @@ AC_SUBST([AR])dnl
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
-# harmless because $srcdir is '.', but things will broke when you
+# harmless because $srcdir is `.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
@@ -169,19 +337,22 @@ am_aux_dir=`cd $ac_aux_dir && pwd`
# AM_CONDITIONAL -*- Autoconf -*-
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 9
+
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
-[AC_PREREQ([2.52])dnl
- m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
- [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
@@ -200,14 +371,16 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009,
+# 2010, 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 12
-# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
# will think it sees a *use*, and therefore will trigger all it's
# C support machinery. Also note that it means that autoscan, seeing
@@ -217,7 +390,7 @@ fi])])
# _AM_DEPENDENCIES(NAME)
# ----------------------
# See how the compiler implements dependency checking.
-# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
# We try a few techniques and use that to set a single cache variable.
#
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
@@ -230,13 +403,12 @@ AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
AC_REQUIRE([AM_DEP_TRACK])dnl
-m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
- [$1], [CXX], [depcc="$CXX" am_compiler_list=],
- [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
- [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
- [$1], [UPC], [depcc="$UPC" am_compiler_list=],
- [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
- [depcc="$$1" am_compiler_list=])
+ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
+ [$1], CXX, [depcc="$CXX" am_compiler_list=],
+ [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], UPC, [depcc="$UPC" am_compiler_list=],
+ [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
AC_CACHE_CHECK([dependency style of $depcc],
[am_cv_$1_dependencies_compiler_type],
@@ -244,8 +416,8 @@ AC_CACHE_CHECK([dependency style of $depcc],
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
- # making a dummy file named 'D' -- because '-MD' means "put the output
- # in D".
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
@@ -285,16 +457,16 @@ AC_CACHE_CHECK([dependency style of $depcc],
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
- # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
- # Solaris 10 /bin/sh.
- echo '/* dummy */' > sub/conftst$i.h
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
- # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
- # handle '-M -o', and we need to detect this. Also, some Intel
- # versions had trouble with output in subdirs.
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
@@ -303,8 +475,8 @@ AC_CACHE_CHECK([dependency style of $depcc],
test "$am__universal" = false || continue
;;
nosideeffect)
- # After this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested.
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
if test "x$enable_dependency_tracking" = xyes; then
continue
else
@@ -312,7 +484,7 @@ AC_CACHE_CHECK([dependency style of $depcc],
fi
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
- # This compiler won't grok '-c -o', but also, the minuso test has
+ # This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
@@ -360,7 +532,7 @@ AM_CONDITIONAL([am__fastdep$1], [
# AM_SET_DEPDIR
# -------------
# Choose a directory name for dependency files.
-# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
AC_DEFUN([AM_SET_DEPDIR],
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
@@ -370,13 +542,9 @@ AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
# AM_DEP_TRACK
# ------------
AC_DEFUN([AM_DEP_TRACK],
-[AC_ARG_ENABLE([dependency-tracking], [dnl
-AS_HELP_STRING(
- [--enable-dependency-tracking],
- [do not reject slow dependency extractors])
-AS_HELP_STRING(
- [--disable-dependency-tracking],
- [speeds up one-time build])])
+[AC_ARG_ENABLE(dependency-tracking,
+[ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors])
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
@@ -391,12 +559,14 @@ _AM_SUBST_NOTMAKE([am__nodep])dnl
# Generate code to set up dependency tracking. -*- Autoconf -*-
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+#serial 5
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
@@ -415,7 +585,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
- # We used to match only the files named 'Makefile.in', but
+ # We used to match only the files named `Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
@@ -427,19 +597,21 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
- # from the Makefile without running 'make'.
+ # from the Makefile without running `make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
@@ -457,7 +629,7 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
# This macro should only be invoked once -- use via AC_REQUIRE.
#
# This code is only required when automatic dependency tracking
-# is enabled. FIXME. This creates each '.P' file that we will
+# is enabled. FIXME. This creates each `.P' file that we will
# need in order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles],
@@ -467,12 +639,15 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
# Do all the work for Automake. -*- Autoconf -*-
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 16
+
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
@@ -517,41 +692,31 @@ AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
-[AC_DIAGNOSE([obsolete],
-[$0: two- and three-arguments forms are deprecated. For more info, see:
-http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation])
-m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
-m4_if(
- m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
- [ok:ok],,
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
-[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
- AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
-AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
-AM_MISSING_PROG([AUTOCONF], [autoconf])
-AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
-AM_MISSING_PROG([AUTOHEADER], [autoheader])
-AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
-AC_REQUIRE([AC_PROG_MKDIR_P])dnl
-# For better backward compatibility. To be removed once Automake 1.9.x
-# dies out for good. For more background, see:
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
-AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
@@ -562,35 +727,28 @@ _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
- [_AM_DEPENDENCIES([CC])],
- [m4_define([AC_PROG_CC],
- m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+ [_AM_DEPENDENCIES(CC)],
+ [define([AC_PROG_CC],
+ defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
- [_AM_DEPENDENCIES([CXX])],
- [m4_define([AC_PROG_CXX],
- m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+ [_AM_DEPENDENCIES(CXX)],
+ [define([AC_PROG_CXX],
+ defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
- [_AM_DEPENDENCIES([OBJC])],
- [m4_define([AC_PROG_OBJC],
- m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
-dnl Support for Objective C++ was only introduced in Autoconf 2.65,
-dnl but we still cater to Autoconf 2.62.
-m4_ifdef([AC_PROG_OBJCXX],
-[AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
- [_AM_DEPENDENCIES([OBJCXX])],
- [m4_define([AC_PROG_OBJCXX],
- m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])])dnl
+ [_AM_DEPENDENCIES(OBJC)],
+ [define([AC_PROG_OBJC],
+ defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
])
_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
-dnl The 'parallel-tests' driver may need to know about EXEEXT, so add the
-dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
])
-dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
@@ -618,12 +776,15 @@ for _am_header in $config_headers :; do
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation,
+# Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
@@ -637,14 +798,16 @@ if test x"${install_sh}" != xset; then
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
-AC_SUBST([install_sh])])
+AC_SUBST(install_sh)])
-# Copyright (C) 2003-2012 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 2
+
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
@@ -658,18 +821,21 @@ fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
-# Copyright (C) 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
+# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 5
+
# AM_PROG_LEX
# -----------
# Autoconf leaves LEX=: if lex or flex can't be found. Change that to a
# "missing" invocation, for better error output.
AC_DEFUN([AM_PROG_LEX],
-[AC_PREREQ([2.50])dnl
+[AC_PREREQ(2.50)dnl
AC_REQUIRE([AM_MISSING_HAS_RUN])dnl
AC_REQUIRE([AC_PROG_LEX])dnl
if test "$LEX" = :; then
@@ -678,12 +844,14 @@ fi])
# Check to see how 'make' treats includes. -*- Autoconf -*-
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 4
+
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
@@ -701,7 +869,7 @@ am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
-# Ignore all kinds of additional output from 'make'.
+# Ignore all kinds of additional output from `make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
@@ -726,14 +894,52 @@ AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
+# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_PROG_CC_C_O
+# --------------
+# Like AC_PROG_CC_C_O, but changed for automake.
+AC_DEFUN([AM_PROG_CC_C_O],
+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+if test "$am_t" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+dnl Make sure AC_PROG_CC is never called again, or it will override our
+dnl setting of CC.
+m4_define([AC_PROG_CC],
+ [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
+])
+
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
-# Copyright (C) 1997-2012 Free Software Foundation, Inc.
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 6
+
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
@@ -741,6 +947,7 @@ AC_DEFUN([AM_MISSING_PROG],
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
+
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it supports --run.
@@ -761,18 +968,50 @@ if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
else
am_missing_run=
- AC_MSG_WARN(['missing' script is too old or missing])
+ AC_MSG_WARN([`missing' script is too old or missing])
fi
])
+# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation,
+# Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 1
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+ [[\\/$]]* | ?:[[\\/]]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
# Helper functions for option handling. -*- Autoconf -*-
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software
+# Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 5
+
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
@@ -782,7 +1021,7 @@ AC_DEFUN([_AM_MANGLE_OPTION],
# --------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
-[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
# ------------------------
@@ -798,16 +1037,22 @@ AC_DEFUN([_AM_IF_OPTION],
# Check to make sure that the build environment is sane. -*- Autoconf -*-
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 5
+
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
@@ -818,40 +1063,32 @@ case `pwd` in
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
- AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+ AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
esac
-# Do 'set' in a subshell so we don't clobber the current shell's
+# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
- am_has_slept=no
- for am_try in 1 2; do
- echo "timestamp, slept: $am_has_slept" > conftest.file
- set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
- if test "$[*]" = "X"; then
- # -L didn't work.
- set X `ls -t "$srcdir/configure" conftest.file`
- fi
- if test "$[*]" != "X $srcdir/configure conftest.file" \
- && test "$[*]" != "X conftest.file $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
- alias in your environment])
- fi
- if test "$[2]" = conftest.file || test $am_try -eq 2; then
- break
- fi
- # Just in case.
- sleep 1
- am_has_slept=yes
- done
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+alias in your environment])
+ fi
+
test "$[2]" = conftest.file
)
then
@@ -861,58 +1098,103 @@ else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
-AC_MSG_RESULT([yes])
-# If we didn't sleep, we still need to ensure time stamps of config.status and
-# generated files are strictly newer.
-am_sleep_pid=
-if grep 'slept: no' conftest.file >/dev/null 2>&1; then
- ( sleep 1 ) &
- am_sleep_pid=$!
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2009, 2011 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# (`yes' being less verbose, `no' or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules],
+[ --enable-silent-rules less verbose build output (undo: `make V=1')
+ --disable-silent-rules verbose build output (undo: `make V=0')])
+case $enable_silent_rules in
+yes) AM_DEFAULT_VERBOSITY=0;;
+no) AM_DEFAULT_VERBOSITY=1;;
+*) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few `make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using `$V' instead of `$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
fi
-AC_CONFIG_COMMANDS_PRE(
- [AC_MSG_CHECKING([that generated files are newer than configure])
- if test -n "$am_sleep_pid"; then
- # Hide warnings about reused PIDs.
- wait $am_sleep_pid 2>/dev/null
- fi
- AC_MSG_RESULT([done])])
-rm -f conftest.file
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
])
-# Copyright (C) 2001-2012 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 1
+
# AM_PROG_INSTALL_STRIP
# ---------------------
-# One issue with vendor 'install' (even GNU) is that you can't
+# One issue with vendor `install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
-# always use install-sh in "make install-strip", and initialize
+# always use install-sh in `make install-strip', and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
-# Installed binaries are usually stripped using 'strip' when the user
-# run "make install-strip". However 'strip' might not be the right
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
-# will honor the 'STRIP' environment variable to overrule this program.
-dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
-# Copyright (C) 2006-2012 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 3
+
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
@@ -926,16 +1208,18 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
-# Copyright (C) 2004-2012 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
+# serial 2
+
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
-# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+# FORMAT should be one of `v7', `ustar', or `pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
@@ -958,7 +1242,7 @@ AC_MSG_CHECKING([how to create a $1 tar archive])
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
# Do not fold the above two line into one, because Tru64 sh and
-# Solaris sh will not grok spaces in the rhs of '-'.
+# Solaris sh will not grok spaces in the rhs of `-'.
for _am_tool in $_am_tools
do
case $_am_tool in
@@ -1019,7 +1303,7 @@ AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
-m4_include([m4/ax_check_compiler_flags.m4])
+m4_include([m4/ax_check_compile_flag.m4])
m4_include([m4/ax_ext.m4])
m4_include([m4/ax_gcc_x86_cpuid.m4])
m4_include([m4/ax_recvmmsg.m4])
@@ -1028,3 +1312,4 @@ m4_include([m4/ltoptions.m4])
m4_include([m4/ltsugar.m4])
m4_include([m4/ltversion.m4])
m4_include([m4/lt~obsolete.m4])
+m4_include([m4/visibility.m4])
diff --git a/ar-lib b/ar-lib
index 67f5f36..0f62c6f 100755
--- a/ar-lib
+++ b/ar-lib
@@ -4,7 +4,7 @@
me=ar-lib
scriptversion=2012-03-01.08; # UTC
-# Copyright (C) 2010-2012 Free Software Foundation, Inc.
+# Copyright (C) 2010, 2012 Free Software Foundation, Inc.
# Written by Peter Rosin <peda@lysator.liu.se>.
#
# This program is free software; you can redistribute it and/or modify
diff --git a/astylerc b/astylerc
deleted file mode 100644
index 95703db..0000000
--- a/astylerc
+++ /dev/null
@@ -1,12 +0,0 @@
---style=1tbs
---indent=tab=8
---indent-preprocessor
---pad-oper
---pad-header
---unpad-paren
---add-brackets
---convert-tabs
---align-pointer=name
---mode=c
---lineend=linux
-
diff --git a/compile b/compile
new file mode 100755
index 0000000..862a14e
--- /dev/null
+++ b/compile
@@ -0,0 +1,343 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2012-03-05.13; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
+# Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" "" $nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv/,$2, in
+ *,$file_conv,*)
+ ;;
+ mingw/*)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin/*)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine/*)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+ func_file_conv "$1"
+ if test -z "$lib_path"; then
+ lib_path=$file
+ else
+ lib_path="$lib_path;$file"
+ fi
+ linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+ lib=$1
+ found=no
+ save_IFS=$IFS
+ IFS=';'
+ for dir in $lib_path $LIB
+ do
+ IFS=$save_IFS
+ if $shared && test -f "$dir/$lib.dll.lib"; then
+ found=yes
+ lib=$dir/$lib.dll.lib
+ break
+ fi
+ if test -f "$dir/$lib.lib"; then
+ found=yes
+ lib=$dir/$lib.lib
+ break
+ fi
+ done
+ IFS=$save_IFS
+
+ if test "$found" != yes; then
+ lib=$lib.lib
+ fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+ # Assume a capable shell
+ lib_path=
+ shared=:
+ linker_opts=
+ for arg
+ do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ eat=1
+ case $2 in
+ *.o | *.[oO][bB][jJ])
+ func_file_conv "$2"
+ set x "$@" -Fo"$file"
+ shift
+ ;;
+ *)
+ func_file_conv "$2"
+ set x "$@" -Fe"$file"
+ shift
+ ;;
+ esac
+ ;;
+ -I)
+ eat=1
+ func_file_conv "$2" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -I*)
+ func_file_conv "${1#-I}" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -l)
+ eat=1
+ func_cl_dashl "$2"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -l*)
+ func_cl_dashl "${1#-l}"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -L)
+ eat=1
+ func_cl_dashL "$2"
+ ;;
+ -L*)
+ func_cl_dashL "${1#-L}"
+ ;;
+ -static)
+ shared=false
+ ;;
+ -Wl,*)
+ arg=${1#-Wl,}
+ save_ifs="$IFS"; IFS=','
+ for flag in $arg; do
+ IFS="$save_ifs"
+ linker_opts="$linker_opts $flag"
+ done
+ IFS="$save_ifs"
+ ;;
+ -Xlinker)
+ eat=1
+ linker_opts="$linker_opts $2"
+ ;;
+ -*)
+ set x "$@" "$1"
+ shift
+ ;;
+ *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+ func_file_conv "$1"
+ set x "$@" -Tp"$file"
+ shift
+ ;;
+ *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+ func_file_conv "$1" mingw
+ set x "$@" "$file"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+ done
+ if test -n "$linker_opts"; then
+ linker_opts="-link$linker_opts"
+ fi
+ exec "$@" $linker_opts
+ exit 1
+}
+
+eat=
+
+case $1 in
+ '')
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "compile $scriptversion"
+ exit $?
+ ;;
+ cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
+ func_cl_wrapper "$@" # Doesn't return...
+ ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ # So we strip '-o arg' only if arg is an object.
+ eat=1
+ case $2 in
+ *.o | *.obj)
+ ofile=$2
+ ;;
+ *)
+ set x "$@" -o "$2"
+ shift
+ ;;
+ esac
+ ;;
+ *.c)
+ cfile=$1
+ set x "$@" "$1"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+ # If no '-o' option was seen then we might have been invoked from a
+ # pattern rule where we don't need one. That is ok -- this is a
+ # normal compilation that the losing compiler can handle. If no
+ # '.c' file was seen then we are probably linking. That is also
+ # ok.
+ exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file. Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+ if mkdir "$lockdir" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+ test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/config.guess b/config.guess
index 0e30d56..d622a44 100755
--- a/config.guess
+++ b/config.guess
@@ -1,9 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+# 2011, 2012 Free Software Foundation, Inc.
-timestamp='2003-07-02'
+timestamp='2012-02-10'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -16,24 +17,24 @@ timestamp='2003-07-02'
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
-# Originally written by Per Bothner <per@bothner.com>.
-# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
+
+# Originally written by Per Bothner. Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
#
-# The plan is that this can be called by configure scripts if you
-# don't specify an explicit build system type.
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -53,7 +54,8 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
@@ -66,11 +68,11 @@ Try \`$me --help' for more information."
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
- echo "$timestamp" ; exit 0 ;;
+ echo "$timestamp" ; exit ;;
--version | -v )
- echo "$version" ; exit 0 ;;
+ echo "$version" ; exit ;;
--help | --h* | -h )
- echo "$usage"; exit 0 ;;
+ echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
@@ -104,7 +106,7 @@ set_cc_for_build='
trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
@@ -123,7 +125,7 @@ case $CC_FOR_BUILD,$HOST_CC,$CC in
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ;'
+esac ; set_cc_for_build= ;'
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
@@ -141,7 +143,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
- # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -158,6 +160,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
@@ -166,7 +169,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
- | grep __ELF__ >/dev/null
+ | grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
@@ -176,7 +179,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
fi
;;
*)
- os=netbsd
+ os=netbsd
;;
esac
# The OS release
@@ -196,50 +199,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
echo "${machine}-${os}${release}"
- exit 0 ;;
- amiga:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- arc:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- hp300:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mac68k:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- macppc:OpenBSD:*:*)
- echo powerpc-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvme68k:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvme88k:OpenBSD:*:*)
- echo m88k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- mvmeppc:OpenBSD:*:*)
- echo powerpc-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- pmax:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- sgi:OpenBSD:*:*)
- echo mipseb-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- sun3:OpenBSD:*:*)
- echo m68k-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
- wgrisc:OpenBSD:*:*)
- echo mipsel-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:OpenBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
- exit 0 ;;
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ exit ;;
+ *:SolidBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
+ *:MirBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ exit ;;
alpha:OSF1:*:*)
- if test $UNAME_RELEASE = "V4.0"; then
+ case $UNAME_RELEASE in
+ *4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
- fi
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
@@ -277,42 +262,52 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
"EV7.9 (21364A)")
UNAME_MACHINE="alphaev79" ;;
esac
+ # A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- exit 0 ;;
- Alpha*:OpenVMS:*:*)
- echo alpha-hp-vms
- exit 0 ;;
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
# of the specific Alpha model?
echo alpha-pc-interix
- exit 0 ;;
+ exit ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
- exit 0 ;;
+ exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
- exit 0;;
+ exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-amigaos
- exit 0 ;;
+ exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
echo ${UNAME_MACHINE}-unknown-morphos
- exit 0 ;;
+ exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
- exit 0 ;;
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
- exit 0;;
+ exit ;;
+ arm:riscos:*:*|arm:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
- exit 0;;
+ exit ;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
@@ -320,32 +315,51 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
else
echo pyramid-pyramid-bsd
fi
- exit 0 ;;
+ exit ;;
NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
- exit 0 ;;
+ exit ;;
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
- exit 0 ;;
- DRS?6000:UNIX_SV:4.2*:7*)
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
- sparc) echo sparc-icl-nx7 && exit 0 ;;
+ sparc) echo sparc-icl-nx7; exit ;;
esac ;;
+ s390x:SunOS:*:*)
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
+ exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
- i86pc:SunOS:5.*:*)
- echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux${UNAME_RELEASE}
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval $set_cc_for_build
+ SUN_ARCH="i386"
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH="x86_64"
+ fi
+ fi
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
+ exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
Series*|S4*)
@@ -354,10 +368,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
- exit 0 ;;
+ exit ;;
sun3*:SunOS:*:*)
echo m68k-sun-sunos${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
@@ -369,10 +383,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo sparc-sun-sunos${UNAME_RELEASE}
;;
esac
- exit 0 ;;
+ exit ;;
aushp:SunOS:*:*)
echo sparc-auspex-sunos${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
@@ -382,38 +396,41 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
- exit 0 ;;
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
- exit 0 ;;
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
- exit 0 ;;
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
- exit 0 ;;
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten${UNAME_RELEASE}
+ exit ;;
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
- exit 0 ;;
+ exit ;;
RISC*:ULTRIX:*:*)
echo mips-dec-ultrix${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
@@ -437,35 +454,36 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
exit (-1);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c \
- && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
- && exit 0
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+ dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`$dummy $dummyarg` &&
+ { echo "$SYSTEM_NAME"; exit; }
echo mips-mips-riscos${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
- exit 0 ;;
+ exit ;;
Motorola:*:4.3:PL8-*)
echo powerpc-harris-powermax
- exit 0 ;;
+ exit ;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
echo powerpc-harris-powermax
- exit 0 ;;
+ exit ;;
Night_Hawk:Power_UNIX:*:*)
echo powerpc-harris-powerunix
- exit 0 ;;
+ exit ;;
m88k:CX/UX:7*:*)
echo m88k-harris-cxux7
- exit 0 ;;
+ exit ;;
m88k:*:4*:R4*)
echo m88k-motorola-sysv4
- exit 0 ;;
+ exit ;;
m88k:*:3*:R3*)
echo m88k-motorola-sysv3
- exit 0 ;;
+ exit ;;
AViiON:dgux:*:*)
- # DG/UX returns AViiON for all architectures
- UNAME_PROCESSOR=`/usr/bin/uname -p`
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -478,29 +496,29 @@ EOF
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
- exit 0 ;;
+ exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
- exit 0 ;;
+ exit ;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
echo m88k-motorola-sysv3
- exit 0 ;;
+ exit ;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
echo m88k-tektronix-sysv3
- exit 0 ;;
+ exit ;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
echo m68k-tektronix-bsd
- exit 0 ;;
+ exit ;;
*:IRIX*:*:*)
echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
- exit 0 ;;
+ exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
- echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
- exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
echo i386-ibm-aix
- exit 0 ;;
+ exit ;;
ia64:AIX:*:*)
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
@@ -508,7 +526,7 @@ EOF
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
- exit 0 ;;
+ exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
eval $set_cc_for_build
@@ -523,15 +541,19 @@ EOF
exit(0);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
- echo rs6000-ibm-aix3.2.5
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
else
echo rs6000-ibm-aix3.2
fi
- exit 0 ;;
- *:AIX:*:[45])
+ exit ;;
+ *:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
@@ -544,28 +566,28 @@ EOF
IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
fi
echo ${IBM_ARCH}-ibm-aix${IBM_REV}
- exit 0 ;;
+ exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
- exit 0 ;;
+ exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
echo romp-ibm-bsd4.4
- exit 0 ;;
+ exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
- exit 0 ;; # report: romp-ibm BSD 4.3
+ exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
- exit 0 ;;
+ exit ;;
DPX/2?00:B.O.S.:*:*)
echo m68k-bull-sysv3
- exit 0 ;;
+ exit ;;
9000/[34]??:4.3bsd:1.*:*)
echo m68k-hp-bsd
- exit 0 ;;
+ exit ;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
- exit 0 ;;
+ exit ;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
@@ -574,52 +596,52 @@ EOF
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
- sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
- 532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
- esac ;;
- esac
+ esac ;;
+ esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ sed 's/^ //' << EOF >$dummy.c
- #define _HPUX_SOURCE
- #include <stdlib.h>
- #include <unistd.h>
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
- int main ()
- {
- #if defined(_SC_KERNEL_BITS)
- long bits = sysconf(_SC_KERNEL_BITS);
- #endif
- long cpu = sysconf (_SC_CPU_VERSION);
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
- switch (cpu)
- {
- case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
- case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
- case CPU_PA_RISC2_0:
- #if defined(_SC_KERNEL_BITS)
- switch (bits)
- {
- case 64: puts ("hppa2.0w"); break;
- case 32: puts ("hppa2.0n"); break;
- default: puts ("hppa2.0"); break;
- } break;
- #else /* !defined(_SC_KERNEL_BITS) */
- puts ("hppa2.0"); break;
- #endif
- default: puts ("hppa1.0"); break;
- }
- exit (0);
- }
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -627,9 +649,19 @@ EOF
esac
if [ ${HP_ARCH} = "hppa2.0w" ]
then
- # avoid double evaluation of $set_cc_for_build
- test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+ eval $set_cc_for_build
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
@@ -637,11 +669,11 @@ EOF
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
- exit 0 ;;
+ exit ;;
ia64:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ia64-hp-hpux${HPUX_REV}
- exit 0 ;;
+ exit ;;
3050*:HI-UX:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
@@ -669,211 +701,266 @@ EOF
exit (0);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
- exit 0 ;;
+ exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
echo hppa1.1-hp-bsd
- exit 0 ;;
+ exit ;;
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
- exit 0 ;;
+ exit ;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
- exit 0 ;;
+ exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
- exit 0 ;;
+ exit ;;
hp8??:OSF1:*:*)
echo hppa1.0-hp-osf
- exit 0 ;;
+ exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
echo ${UNAME_MACHINE}-unknown-osf1mk
else
echo ${UNAME_MACHINE}-unknown-osf1
fi
- exit 0 ;;
+ exit ;;
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
- exit 0 ;;
+ exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
- exit 0 ;;
+ exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
- exit 0 ;;
+ exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
- exit 0 ;;
+ exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
- exit 0 ;;
+ exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
- exit 0 ;;
+ exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
+ exit ;;
CRAY*[A-Z]90:*:*:*)
echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
- exit 0 ;;
+ exit ;;
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
+ exit ;;
CRAY*T3E:*:*:*)
echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
+ exit ;;
CRAY*SV1:*:*:*)
echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
+ exit ;;
*:UNICOS/mp:*:*)
- echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
- exit 0 ;;
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
- echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
- exit 0 ;;
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
sparc*:BSD/OS:*:*)
echo sparc-unknown-bsdi${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:BSD/OS:*:*)
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
- exit 0 ;;
- *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
- # Determine whether the default compiler uses glibc.
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #if __GLIBC__ >= 2
- LIBC=gnu
- #else
- LIBC=
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- # GNU/FreeBSD systems have a "k" prefix to indicate we are using
- # FreeBSD's kernel, but not the complete OS.
- case ${LIBC} in gnu) kernel_only='k' ;; esac
- echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
- exit 0 ;;
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case ${UNAME_PROCESSOR} in
+ amd64)
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ *)
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ esac
+ exit ;;
i*:CYGWIN*:*)
echo ${UNAME_MACHINE}-pc-cygwin
- exit 0 ;;
- i*:MINGW*:*)
+ exit ;;
+ *:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
- exit 0 ;;
+ exit ;;
+ i*:MSYS*:*)
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+ i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
+ exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
- exit 0 ;;
- x86:Interix*:[34]*)
- echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
- exit 0 ;;
+ exit ;;
+ *:Interix*:*)
+ case ${UNAME_MACHINE} in
+ x86)
+ echo i586-pc-interix${UNAME_RELEASE}
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix${UNAME_RELEASE}
+ exit ;;
+ esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
- exit 0 ;;
+ exit ;;
+ 8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
- exit 0 ;;
+ exit ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
- exit 0 ;;
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
- exit 0 ;;
+ exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
- exit 0 ;;
+ exit ;;
*:GNU:*:*)
+ # the GNU system
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
- exit 0 ;;
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+ exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
- exit 0 ;;
+ exit ;;
+ aarch64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit ;;
arm*:Linux:*:*)
+ eval $set_cc_for_build
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+ else
+ echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
+ exit ;;
cris:Linux:*:*)
- echo cris-axis-linux-gnu
- exit 0 ;;
- ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-gnu
+ exit ;;
+ crisv32:Linux:*:*)
+ echo ${UNAME_MACHINE}-axis-linux-gnu
+ exit ;;
+ frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- m68*:Linux:*:*)
+ exit ;;
+ hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
- mips:Linux:*:*)
+ exit ;;
+ i*86:Linux:*:*)
+ LIBC=gnu
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
- #undef CPU
- #undef mips
- #undef mipsel
- #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mipsel
- #else
- #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips
- #else
- CPU=
- #endif
+ #ifdef __dietlibc__
+ LIBC=dietlibc
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
- ;;
- mips64:Linux:*:*)
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+ echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+ exit ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m32r*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
- #undef mips64
- #undef mips64el
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=mips64el
+ CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=mips64
+ CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
- test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
- ppc:Linux:*:*)
- echo powerpc-unknown-linux-gnu
- exit 0 ;;
- ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-gnu
- exit 0 ;;
- alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
- EV5) UNAME_MACHINE=alphaev5 ;;
- EV56) UNAME_MACHINE=alphaev56 ;;
- PCA56) UNAME_MACHINE=alphapca56 ;;
- PCA57) UNAME_MACHINE=alphapca56 ;;
- EV6) UNAME_MACHINE=alphaev6 ;;
- EV67) UNAME_MACHINE=alphaev67 ;;
- EV68*) UNAME_MACHINE=alphaev68 ;;
- esac
- objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
- if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
- echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
- exit 0 ;;
+ or32:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-gnu
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
@@ -881,109 +968,71 @@ EOF
PA8*) echo hppa2.0-unknown-linux-gnu ;;
*) echo hppa-unknown-linux-gnu ;;
esac
- exit 0 ;;
- parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-gnu
- exit 0 ;;
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
- exit 0 ;;
+ exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
+ exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
- exit 0 ;;
+ exit ;;
+ tile*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ vax:Linux:*:*)
+ echo ${UNAME_MACHINE}-dec-linux-gnu
+ exit ;;
x86_64:Linux:*:*)
- echo x86_64-unknown-linux-gnu
- exit 0 ;;
- i*86:Linux:*:*)
- # The BFD linker knows what the default object file format is, so
- # first see if it will tell us. cd to the root directory to prevent
- # problems with other programs or directories called `ld' in the path.
- # Set LC_ALL=C to ensure ld outputs messages in English.
- ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
- | sed -ne '/supported targets:/!d
- s/[ ][ ]*/ /g
- s/.*supported targets: *//
- s/ .*//
- p'`
- case "$ld_supported_targets" in
- elf32-i386)
- TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
- ;;
- a.out-i386-linux)
- echo "${UNAME_MACHINE}-pc-linux-gnuaout"
- exit 0 ;;
- coff-i386)
- echo "${UNAME_MACHINE}-pc-linux-gnucoff"
- exit 0 ;;
- "")
- # Either a pre-BFD a.out linker (linux-gnuoldld) or
- # one that does not give us useful --help.
- echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
- exit 0 ;;
- esac
- # Determine whether the default compiler is a.out or elf
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
- #include <features.h>
- #ifdef __ELF__
- # ifdef __GLIBC__
- # if __GLIBC__ >= 2
- LIBC=gnu
- # else
- LIBC=gnulibc1
- # endif
- # else
- LIBC=gnulibc1
- # endif
- #else
- #ifdef __INTEL_COMPILER
- LIBC=gnu
- #else
- LIBC=gnuaout
- #endif
- #endif
-EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
- test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
- test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
- ;;
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
echo i386-sequent-sysv4
- exit 0 ;;
+ exit ;;
i*86:UNIX_SV:4.2MP:2.*)
- # Unixware is an offshoot of SVR4, but it has its own version
- # number series starting with 2...
- # I am not positive that other SVR4 systems won't match this,
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
- # Use sysv4.2uw... so that sysv4* matches it.
+ # Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
- exit 0 ;;
+ exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
echo ${UNAME_MACHINE}-pc-os2-emx
- exit 0 ;;
+ exit ;;
i*86:XTS-300:*:STOP)
echo ${UNAME_MACHINE}-unknown-stop
- exit 0 ;;
+ exit ;;
i*86:atheos:*:*)
echo ${UNAME_MACHINE}-unknown-atheos
- exit 0 ;;
- i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ exit ;;
+ i*86:syllable:*:*)
+ echo ${UNAME_MACHINE}-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
- exit 0 ;;
+ exit ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
@@ -991,15 +1040,16 @@ EOF
else
echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
fi
- exit 0 ;;
- i*86:*:5:[78]*)
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
- exit 0 ;;
+ exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
@@ -1017,73 +1067,86 @@ EOF
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
- exit 0 ;;
+ exit ;;
pc:*:*:*)
# Left here for compatibility:
- # uname -m prints for DJGPP always 'pc', but it prints nothing about
- # the processor, so we play safe by assuming i386.
- echo i386-pc-msdosdjgpp
- exit 0 ;;
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configury will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
- exit 0 ;;
+ exit ;;
paragon:*:*:*)
echo i860-intel-osf1
- exit 0 ;;
+ exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
fi
- exit 0 ;;
+ exit ;;
mini*:CTIX:SYS*5:*)
# "miniframe"
echo m68010-convergent-sysv
- exit 0 ;;
+ exit ;;
mc68k:UNIX:SYSTEM5:3.51m)
echo m68k-convergent-sysv
- exit 0 ;;
+ exit ;;
M680?0:D-NIX:5.3:*)
echo m68k-diab-dnix
- exit 0 ;;
- M68*:*:R3V[567]*:*)
- test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
- 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
- /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && echo i486-ncr-sysv4 && exit 0 ;;
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
- exit 0 ;;
+ exit ;;
TSUNAMI:LynxOS:2.*:*)
echo sparc-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
- PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
- exit 0 ;;
+ exit ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
- exit 0 ;;
+ exit ;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
@@ -1091,68 +1154,94 @@ EOF
else
echo ns32k-sni-sysv
fi
- exit 0 ;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
- # says <Richard.M.Bartel@ccMail.Census.GOV>
- echo i586-unisys-sysv4
- exit 0 ;;
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
echo hppa1.1-stratus-sysv4
- exit 0 ;;
+ exit ;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
echo i860-stratus-sysv4
- exit 0 ;;
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo ${UNAME_MACHINE}-stratus-vos
+ exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
- exit 0 ;;
+ exit ;;
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
- exit 0 ;;
+ exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ echo mips-nec-sysv${UNAME_RELEASE}
else
- echo mips-unknown-sysv${UNAME_RELEASE}
+ echo mips-unknown-sysv${UNAME_RELEASE}
fi
- exit 0 ;;
+ exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
- exit 0 ;;
+ exit ;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
echo powerpc-apple-beos
- exit 0 ;;
+ exit ;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
- exit 0 ;;
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
SX-5:SUPER-UX:*:*)
echo sx5-nec-superux${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
SX-6:SUPER-UX:*:*)
echo sx6-nec-superux${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux${UNAME_RELEASE}
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux${UNAME_RELEASE}
+ exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:Rhapsody:*:*)
echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:Darwin:*:*)
- case `uname -p` in
- *86) UNAME_PROCESSOR=i686 ;;
- powerpc) UNAME_PROCESSOR=powerpc ;;
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ case $UNAME_PROCESSOR in
+ i386)
+ eval $set_cc_for_build
+ if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ UNAME_PROCESSOR="x86_64"
+ fi
+ fi ;;
+ unknown) UNAME_PROCESSOR=powerpc ;;
esac
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = "x86"; then
@@ -1160,22 +1249,28 @@ EOF
UNAME_MACHINE=pc
fi
echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
- exit 0 ;;
- NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
+ exit ;;
+ NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSE-?:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk${UNAME_RELEASE}
+ exit ;;
+ NSR-?:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
- exit 0 ;;
+ exit ;;
BS2000:POSIX*:*:*)
echo bs2000-siemens-sysv
- exit 0 ;;
+ exit ;;
DS/*:UNIX_System_V:*:*)
echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
- exit 0 ;;
+ exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
@@ -1186,28 +1281,53 @@ EOF
UNAME_MACHINE="$cputype"
fi
echo ${UNAME_MACHINE}-unknown-plan9
- exit 0 ;;
+ exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
- exit 0 ;;
+ exit ;;
*:TENEX:*:*)
echo pdp10-unknown-tenex
- exit 0 ;;
+ exit ;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
echo pdp10-dec-tops20
- exit 0 ;;
+ exit ;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
echo pdp10-xkl-tops20
- exit 0 ;;
+ exit ;;
*:TOPS-20:*:*)
echo pdp10-unknown-tops20
- exit 0 ;;
+ exit ;;
*:ITS:*:*)
echo pdp10-unknown-its
- exit 0 ;;
+ exit ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
- exit 0 ;;
+ echo mips-sei-seiux${UNAME_RELEASE}
+ exit ;;
+ *:DragonFly:*:*)
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "${UNAME_MACHINE}" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ exit ;;
+ i*86:rdos:*:*)
+ echo ${UNAME_MACHINE}-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo ${UNAME_MACHINE}-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo ${UNAME_MACHINE}-unknown-esx
+ exit ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1230,16 +1350,16 @@ main ()
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
- "4"
+ "4"
#else
- ""
+ ""
#endif
- ); exit (0);
+ ); exit (0);
#endif
#endif
#if defined (__arm) && defined (__acorn) && defined (__unix)
- printf ("arm-acorn-riscix"); exit (0);
+ printf ("arm-acorn-riscix\n"); exit (0);
#endif
#if defined (hp300) && !defined (hpux)
@@ -1328,11 +1448,12 @@ main ()
}
EOF
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
# Convex versions that predate uname can use getsysinfo(1)
@@ -1341,22 +1462,22 @@ then
case `getsysinfo -f cpu_type` in
c1*)
echo c1-convex-bsd
- exit 0 ;;
+ exit ;;
c2*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
- exit 0 ;;
+ exit ;;
c34*)
echo c34-convex-bsd
- exit 0 ;;
+ exit ;;
c38*)
echo c38-convex-bsd
- exit 0 ;;
+ exit ;;
c4*)
echo c4-convex-bsd
- exit 0 ;;
+ exit ;;
esac
fi
@@ -1367,7 +1488,9 @@ This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
- ftp://ftp.gnu.org/pub/gnu/config/
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
If the version you run ($0) is already up to date, please
send the following data and any information you think might be
diff --git a/config.sub b/config.sub
index 9d7f733..6205f84 100755
--- a/config.sub
+++ b/config.sub
@@ -1,9 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-# 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+# 2011, 2012 Free Software Foundation, Inc.
-timestamp='2003-07-04'
+timestamp='2012-04-18'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -20,23 +21,25 @@ timestamp='2003-07-04'
# 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., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
+
# Please send patches to <config-patches@gnu.org>. Submit a context
-# diff and a properly formatted ChangeLog entry.
+# diff and a properly formatted GNU ChangeLog entry.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
@@ -70,7 +73,8 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
@@ -83,11 +87,11 @@ Try \`$me --help' for more information."
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
- echo "$timestamp" ; exit 0 ;;
+ echo "$timestamp" ; exit ;;
--version | -v )
- echo "$version" ; exit 0 ;;
+ echo "$version" ; exit ;;
--help | --h* | -h )
- echo "$usage"; exit 0 ;;
+ echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
@@ -99,7 +103,7 @@ while test $# -gt 0 ; do
*local*)
# First pass through any local machine types.
echo $1
- exit 0;;
+ exit ;;
* )
break ;;
@@ -118,10 +122,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | kfreebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
+ kopensolaris*-gnu* | \
+ storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
+ android-linux)
+ os=-linux-android
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+ ;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -144,10 +156,13 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis)
+ -apple | -axis | -knuth | -cray | -microblaze)
os=
basic_machine=$1
;;
+ -bluegene*)
+ os=-cnk
+ ;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
@@ -162,13 +177,17 @@ case $os in
os=-chorusos
basic_machine=$1
;;
- -chorusrdb)
- os=-chorusrdb
+ -chorusrdb)
+ os=-chorusrdb
basic_machine=$1
- ;;
+ ;;
-hiux*)
os=-hiuxwe2
;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
-sco5)
os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -185,6 +204,10 @@ case $os in
# Don't forget version if it is 3.2v4 or newer.
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
-sco*)
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -202,6 +225,12 @@ case $os in
-isc*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
-lynx*)
os=-lynxos
;;
@@ -226,55 +255,103 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
+ | aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | am33_2.0 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | be32 | be64 \
+ | bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
- | fr30 | frv \
+ | epiphany \
+ | fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
| i370 | i860 | i960 | ia64 \
- | ip2k \
- | m32r | m68000 | m68k | m88k | mcore \
+ | ip2k | iq2000 \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
- | mips64vr | mips64vrel \
+ | mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
| mipsisa32 | mipsisa32el \
| mipsisa32r2 | mipsisa32r2el \
| mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
| mipsisa64sb1 | mipsisa64sb1el \
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
+ | moxie \
+ | mt \
| msp430 \
+ | nds32 | nds32le | nds32be \
+ | nios | nios2 \
| ns16k | ns32k \
- | openrisc | or32 \
+ | open8 \
+ | or32 \
| pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
- | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
- | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
- | strongarm \
- | tahoe | thumb | tic4x | tic80 | tron \
- | v850 | v850e \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
- | x86 | xscale | xstormy16 | xtensa \
- | z8k)
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
basic_machine=$basic_machine-unknown
;;
- m6811 | m68hc11 | m6812 | m68hc12)
- # Motorola 68HC11/12.
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
@@ -290,58 +367,80 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
+ | aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | amd64-* | arc-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* \
- | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
- | clipper-* | cydra-* \
+ | avr-* | avr32-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
- | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* \
- | m32r-* \
+ | ip2k-* | iq2000-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | mcore-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
- | mips64vr-* | mips64vrel-* \
+ | mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
| mipsisa32-* | mipsisa32el-* \
| mipsisa32r2-* | mipsisa32r2el-* \
| mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
| mipsisa64sb1-* | mipsisa64sb1el-* \
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
| mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
| msp430-* \
- | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nios-* | nios2-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
- | romp-* | rs6000-* \
- | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
- | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
- | tahoe-* | thumb-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
| tron-* \
- | v850-* | v850e-* | vax-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
| we32k-* \
- | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
- | xtensa-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
| ymp-* \
- | z8k-*)
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
@@ -359,6 +458,9 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
adobe68k)
basic_machine=m68010-adobe
os=-scout
@@ -376,6 +478,9 @@ case $basic_machine in
amd64)
basic_machine=x86_64-pc
;;
+ amd64-*)
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
amdahl)
basic_machine=580-amdahl
os=-sysv
@@ -399,6 +504,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-bsd
;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -407,10 +516,35 @@ case $basic_machine in
basic_machine=ns32k-sequent
os=-dynix
;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
c90)
basic_machine=c90-cray
os=-unicos
;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
convex-c1)
basic_machine=c1-convex
os=-bsd
@@ -435,12 +569,27 @@ case $basic_machine in
basic_machine=j90-cray
os=-unicos
;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
crds | unos)
basic_machine=m68k-crds
;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
cris | cris-* | etrax*)
basic_machine=cris-axis
;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
da30 | da30-*)
basic_machine=m68k-da30
;;
@@ -463,6 +612,14 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
dpx20 | dpx20-*)
basic_machine=rs6000-bull
os=-bosx
@@ -574,7 +731,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
-# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -613,6 +769,14 @@ case $basic_machine in
basic_machine=m68k-isi
os=-sysv
;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
m88k-omron*)
basic_machine=m88k-omron
;;
@@ -624,10 +788,17 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
+ microblaze)
+ basic_machine=microblaze-xilinx
+ ;;
mingw32)
basic_machine=i386-pc
os=-mingw32
;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
miniframe)
basic_machine=m68000-convergent
;;
@@ -641,10 +812,6 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
- mmix*)
- basic_machine=mmix-knuth
- os=-mmixware
- ;;
monitor)
basic_machine=m68k-rom68k
os=-coff
@@ -657,10 +824,21 @@ case $basic_machine in
basic_machine=i386-pc
os=-msdos
;;
+ ms1-*)
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i386-pc
+ os=-msys
+ ;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -725,9 +903,11 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
- nv1)
- basic_machine=nv1-cray
- os=-unicosmp
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
@@ -736,9 +916,12 @@ case $basic_machine in
basic_machine=hppa1.1-oki
os=-proelf
;;
- or32 | or32-*)
+ openrisc | openrisc-*)
basic_machine=or32-unknown
- os=-coff
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
@@ -756,6 +939,14 @@ case $basic_machine in
basic_machine=i860-intel
os=-osf
;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
pbd)
basic_machine=sparc-tti
;;
@@ -765,6 +956,12 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
pentium | p5 | k5 | k6 | nexgen | viac3)
basic_machine=i586-pc
;;
@@ -794,9 +991,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
- ppc) basic_machine=powerpc-unknown
+ ppc | ppcbe) basic_machine=powerpc-unknown
;;
- ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -821,6 +1019,10 @@ case $basic_machine in
basic_machine=i586-unknown
os=-pw32
;;
+ rdos)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
rom68k)
basic_machine=m68k-rom68k
os=-coff
@@ -847,6 +1049,10 @@ case $basic_machine in
sb1el)
basic_machine=mipsisa64sb1el-unknown
;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
sei)
basic_machine=mips-sei
os=-seiux
@@ -858,6 +1064,9 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
sh64)
basic_machine=sh64-unknown
;;
@@ -879,6 +1088,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
sun2)
basic_machine=m68000-sun
;;
@@ -935,17 +1147,9 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
- tic54x | c54x*)
- basic_machine=tic54x-unknown
- os=-coff
- ;;
- tic55x | c55x*)
- basic_machine=tic55x-unknown
- os=-coff
- ;;
- tic6x | c6x*)
- basic_machine=tic6x-unknown
- os=-coff
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
;;
tx39)
basic_machine=mipstx39-unknown
@@ -960,6 +1164,10 @@ case $basic_machine in
tower | tower-32)
basic_machine=m68k-ncr
;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
udi29k)
basic_machine=a29k-amd
os=-udi
@@ -1003,9 +1211,16 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
xps | xps100)
basic_machine=xps100-honeywell
;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1014,6 +1229,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
none)
basic_machine=none-none
os=-none
@@ -1033,6 +1252,9 @@ case $basic_machine in
romp)
basic_machine=romp-ibm
;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
rs6000)
basic_machine=rs6000-ibm
;;
@@ -1049,13 +1271,10 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
- sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
- sh64)
- basic_machine=sh64-unknown
- ;;
- sparc | sparcv9 | sparcv9b)
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
basic_machine=sparc-sun
;;
cydra)
@@ -1099,9 +1318,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
+ # First match some system type aliases
+ # that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1122,25 +1344,31 @@ case $os in
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* \
+ | -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -netbsd* | -openbsd* | -kfreebsd* | -freebsd* | -riscix* \
- | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -openbsd* | -solidbsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* \
- | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -chorusos* | -chorusrdb* | -cegcc* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1158,12 +1386,15 @@ case $os in
os=`echo $os | sed -e 's|nto|nto-qnx|'`
;;
-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
| -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
;;
-mac*)
os=`echo $os | sed -e 's|mac|macos|'`
;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
-linux*)
os=`echo $os | sed -e 's|linux|linux-gnu|'`
;;
@@ -1176,6 +1407,9 @@ case $os in
-opened*)
os=-openedition
;;
+ -os400*)
+ os=-os400
+ ;;
-wince*)
os=-wince
;;
@@ -1197,6 +1431,9 @@ case $os in
-atheos*)
os=-atheos
;;
+ -syllable*)
+ os=-syllable
+ ;;
-386bsd)
os=-bsd
;;
@@ -1219,6 +1456,9 @@ case $os in
-sinix*)
os=-sysv4
;;
+ -tpf*)
+ os=-tpf
+ ;;
-triton*)
os=-sysv3
;;
@@ -1255,6 +1495,14 @@ case $os in
-kaos*)
os=-kaos
;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -nacl*)
+ ;;
-none)
;;
*)
@@ -1277,6 +1525,12 @@ else
# system, and we'll never get to this point.
case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
*-acorn)
os=-riscix1.2
;;
@@ -1286,9 +1540,21 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
- c4x-* | tic4x-*)
- os=-coff
- ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
+ ;;
# This must come before the *-dec entry.
pdp10-*)
os=-tops20
@@ -1307,13 +1573,13 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
- # This also exists in the configure program, but was not the
- # default.
- # os=-sunos4
;;
m68*-cisco)
os=-aout
;;
+ mep-*)
+ os=-elf
+ ;;
mips*-cisco)
os=-elf
;;
@@ -1332,9 +1598,15 @@ case $basic_machine in
*-be)
os=-beos
;;
+ *-haiku)
+ os=-haiku
+ ;;
*-ibm)
os=-aix
;;
+ *-knuth)
+ os=-mmixware
+ ;;
*-wec)
os=-proelf
;;
@@ -1437,7 +1709,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
- -aix*)
+ -cnk*|-aix*)
vendor=ibm
;;
-beos*)
@@ -1467,9 +1739,15 @@ case $basic_machine in
-mvs* | -opened*)
vendor=ibm
;;
+ -os400*)
+ vendor=ibm
+ ;;
-ptx*)
vendor=sequent
;;
+ -tpf*)
+ vendor=ibm
+ ;;
-vxsim* | -vxworks* | -windiss*)
vendor=wrs
;;
@@ -1494,7 +1772,7 @@ case $basic_machine in
esac
echo $basic_machine$os
-exit 0
+exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
diff --git a/configure b/configure
index 1e25f68..3630ebb 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for knot 1.2.0.
+# Generated by GNU Autoconf 2.69 for knot 1.3.0-rc3.
#
# Report bugs to <knot-dns@labs.nic.cz>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='knot'
PACKAGE_TARNAME='knot'
-PACKAGE_VERSION='1.2.0'
-PACKAGE_STRING='knot 1.2.0'
+PACKAGE_VERSION='1.3.0-rc3'
+PACKAGE_STRING='knot 1.3.0-rc3'
PACKAGE_BUGREPORT='knot-dns@labs.nic.cz'
PACKAGE_URL=''
@@ -637,11 +637,26 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+HAVE_VISIBILITY
+CFLAG_VISIBILITY
+libcrypto_LIBS
+libcrypto_CFLAGS
+liburcu_LIBS
+liburcu_CFLAGS
+storage_dir
+run_dir
+FSM_TYPE
+HAVE_RAGEL_FALSE
+HAVE_RAGEL_TRUE
+RAGEL
YFLAGS
YACC
LEXLIB
LEX_OUTPUT_ROOT
LEX
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
OTOOL64
OTOOL
LIPO
@@ -690,6 +705,10 @@ CPPFLAGS
LDFLAGS
CFLAGS
CC
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
am__untar
am__tar
AMTAR
@@ -754,19 +773,25 @@ SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
+enable_silent_rules
enable_dependency_tracking
-enable_shared
enable_static
+enable_shared
with_pic
enable_fast_install
with_gnu_ld
with_sysroot
enable_libtool_lock
-enable_ldns
+enable_fastparser
enable_debug
enable_debuglevel
enable_recvmmsg
enable_lto
+enable_microseconds_log
+with_rundir
+with_storage
+with_urcu
+with_openssl
'
ac_precious_vars='build_alias
host_alias
@@ -777,8 +802,15 @@ LDFLAGS
LIBS
CPPFLAGS
CPP
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
YACC
-YFLAGS'
+YFLAGS
+liburcu_CFLAGS
+liburcu_LIBS
+libcrypto_CFLAGS
+libcrypto_LIBS'
# Initialize some variables set by options.
@@ -1319,7 +1351,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures knot 1.2.0 to adapt to many kinds of systems.
+\`configure' configures knot 1.3.0-rc3 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1389,7 +1421,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of knot 1.2.0:";;
+ short | recursive ) echo "Configuration of knot 1.3.0-rc3:";;
esac
cat <<\_ACEOF
@@ -1397,16 +1429,16 @@ Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --enable-dependency-tracking
- do not reject slow dependency extractors
- --disable-dependency-tracking
- speeds up one-time build
+ --enable-silent-rules less verbose build output (undo: `make V=1')
+ --disable-silent-rules verbose build output (undo: `make V=0')
+ --disable-dependency-tracking speeds up one-time build
+ --enable-dependency-tracking do not reject slow dependency extractors
+ --enable-static[=PKGS] build static libraries [default=no]
--enable-shared[=PKGS] build shared libraries [default=yes]
- --enable-static[=PKGS] build static libraries [default=yes]
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
- --enable-ldns=yes|no Enable tests with ldns [default=no]
+ --enable-fastparser Generate fast zone parser (requires Ragel!)
--enable-debug=server,zones,xfr,packet,dname,rr,ns,hash,compiler,stash
compile selected debug modules [default=none]
--enable-debuglevel=brief|verbose|details
@@ -1417,6 +1449,8 @@ Optional Features:
running server under valgrind) [default=yes]
--enable-lto=yes|no enable link-time optimizations, enable if not broken
for some extra speed [default=no]
+ --enable-microseconds-log
+ enable microseconds in log messages [default=no]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1426,6 +1460,12 @@ Optional Packages:
--with-gnu-ld assume the C compiler uses GNU ld [default=no]
--with-sysroot=DIR Search for dependent libraries within DIR
(or the compiler's sysroot if not specified).
+ --with-rundir=path Path to run-time variable data (pid, sockets...).
+ [default=`eval echo ${localstatedir}`/run/knot]
+ --with-storage=path Default storage directory (slave zones, persistent
+ data). [default=$(sharedstatedir)/knot]
+ --with-urcu=DIR where to find userspace-rcu library
+ --with-openssl=DIR where to find openssl library
Some influential environment variables:
CC C compiler command
@@ -1436,12 +1476,25 @@ Some influential environment variables:
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
CPP C preprocessor
+ PKG_CONFIG path to pkg-config utility
+ PKG_CONFIG_PATH
+ directories to add to pkg-config's search path
+ PKG_CONFIG_LIBDIR
+ path overriding pkg-config's built-in search path
YACC The `Yet Another Compiler Compiler' implementation to use.
Defaults to the first program found out of: `bison -y', `byacc',
`yacc'.
YFLAGS The list of arguments that will be passed by default to $YACC.
This script will default YFLAGS to the empty string to avoid a
default value of `-d' given by some make applications.
+ liburcu_CFLAGS
+ C compiler flags for liburcu, overriding pkg-config
+ liburcu_LIBS
+ linker flags for liburcu, overriding pkg-config
+ libcrypto_CFLAGS
+ C compiler flags for libcrypto, overriding pkg-config
+ libcrypto_LIBS
+ linker flags for libcrypto, overriding pkg-config
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1509,7 +1562,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-knot configure 1.2.0
+knot configure 1.3.0-rc3
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1928,141 +1981,11 @@ $as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
-
-# ac_fn_c_find_intX_t LINENO BITS VAR
-# -----------------------------------
-# Finds a signed integer type with width BITS, setting cache variable VAR
-# accordingly.
-ac_fn_c_find_intX_t ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
-$as_echo_n "checking for int$2_t... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=no"
- # Order is important - never check a type that is potentially smaller
- # than half of the expected target width.
- for ac_type in int$2_t 'int' 'long int' \
- 'long long int' 'short int' 'signed char'; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$ac_includes_default
- enum { N = $2 / 2 - 1 };
-int
-main ()
-{
-static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
-test_array [0] = 0;
-return test_array [0];
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$ac_includes_default
- enum { N = $2 / 2 - 1 };
-int
-main ()
-{
-static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
- < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
-test_array [0] = 0;
-return test_array [0];
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
- case $ac_type in #(
- int$2_t) :
- eval "$3=yes" ;; #(
- *) :
- eval "$3=\$ac_type" ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- if eval test \"x\$"$3"\" = x"no"; then :
-
-else
- break
-fi
- done
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_find_intX_t
-
-# ac_fn_c_find_uintX_t LINENO BITS VAR
-# ------------------------------------
-# Finds an unsigned integer type with width BITS, setting cache variable VAR
-# accordingly.
-ac_fn_c_find_uintX_t ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
-$as_echo_n "checking for uint$2_t... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=no"
- # Order is important - never check a type that is potentially smaller
- # than half of the expected target width.
- for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
- 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
-test_array [0] = 0;
-return test_array [0];
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- case $ac_type in #(
- uint$2_t) :
- eval "$3=yes" ;; #(
- *) :
- eval "$3=\$ac_type" ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- if eval test \"x\$"$3"\" = x"no"; then :
-
-else
- break
-fi
- done
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_find_uintX_t
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by knot $as_me 1.2.0, which was
+It was created by knot $as_me 1.3.0-rc3, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2342,9 +2265,14 @@ $as_echo "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
-as_fn_append ac_header_list " stdlib.h"
-as_fn_append ac_header_list " unistd.h"
-as_fn_append ac_header_list " sys/param.h"
+as_fn_append ac_header_list " cap-ng.h"
+as_fn_append ac_header_list " netinet/in_systm.h"
+as_fn_append ac_header_list " pthread_np.h"
+as_fn_append ac_header_list " signal.h"
+as_fn_append ac_header_list " sys/select.h"
+as_fn_append ac_header_list " sys/time.h"
+as_fn_append ac_header_list " sys/wait.h"
+as_fn_append ac_header_list " sys/uio.h"
# Check that the precious variables saved in the cache have kept the same
# value.
ac_cache_corrupted=false
@@ -2413,7 +2341,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-am__api_version='1.12'
+am__api_version='1.11'
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@@ -2539,6 +2467,9 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
@@ -2549,40 +2480,32 @@ case `pwd` in
esac
case $srcdir in
*[\\\"\#\$\&\'\`$am_lf\ \ ]*)
- as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+ as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;;
esac
-# Do 'set' in a subshell so we don't clobber the current shell's
+# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
- am_has_slept=no
- for am_try in 1 2; do
- echo "timestamp, slept: $am_has_slept" > conftest.file
- set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
- if test "$*" = "X"; then
- # -L didn't work.
- set X `ls -t "$srcdir/configure" conftest.file`
- fi
- if test "$*" != "X $srcdir/configure conftest.file" \
- && test "$*" != "X conftest.file $srcdir/configure"; then
-
- # If neither matched, then we have a broken ls. This can happen
- # if, for instance, CONFIG_SHELL is bash and it inherits a
- # broken ls alias from the environment. This has actually
- # happened. Such a system could not be considered "sane".
- as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
- alias in your environment" "$LINENO" 5
- fi
- if test "$2" = conftest.file || test $am_try -eq 2; then
- break
- fi
- # Just in case.
- sleep 1
- am_has_slept=yes
- done
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ rm -f conftest.file
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+alias in your environment" "$LINENO" 5
+ fi
+
test "$2" = conftest.file
)
then
@@ -2594,16 +2517,6 @@ Check your system clock" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
-# If we didn't sleep, we still need to ensure time stamps of config.status and
-# generated files are strictly newer.
-am_sleep_pid=
-if grep 'slept: no' conftest.file >/dev/null 2>&1; then
- ( sleep 1 ) &
- am_sleep_pid=$!
-fi
-
-rm -f conftest.file
-
test "$program_prefix" != NONE &&
program_transform_name="s&^&$program_prefix&;$program_transform_name"
# Use a double $ so make ignores it.
@@ -2630,8 +2543,8 @@ if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
else
am_missing_run=
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
-$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
fi
if test x"${install_sh}" != xset; then
@@ -2643,10 +2556,10 @@ if test x"${install_sh}" != xset; then
esac
fi
-# Installed binaries are usually stripped using 'strip' when the user
-# run "make install-strip". However 'strip' might not be the right
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'. However `strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
-# will honor the 'STRIP' environment variable to overrule this program.
+# will honor the `STRIP' environment variable to overrule this program.
if test "$cross_compiling" != no; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
@@ -2785,6 +2698,12 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
$as_echo "$MKDIR_P" >&6; }
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+ [\\/$]* | ?:[\\/]*) ;;
+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
for ac_prog in gawk mawk nawk awk
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
@@ -2889,7 +2808,7 @@ fi
# Define the identity of the package.
PACKAGE='knot'
- VERSION='1.2.0'
+ VERSION='1.3.0-rc3'
cat >>confdefs.h <<_ACEOF
@@ -2917,12 +2836,6 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
-# For better backward compatibility. To be removed once Automake 1.9.x
-# dies out for good. For more background, see:
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
-# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
-mkdir_p='$(MKDIR_P)'
-
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
# Always define AMTAR for backward compatibility. Yes, it's still used
@@ -2935,6 +2848,45 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in
+yes) AM_DEFAULT_VERBOSITY=0;;
+no) AM_DEFAULT_VERBOSITY=1;;
+*) AM_DEFAULT_VERBOSITY=0;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
ac_config_headers="$ac_config_headers src/config.h"
@@ -2958,7 +2910,7 @@ am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
-# Ignore all kinds of additional output from 'make'.
+# Ignore all kinds of additional output from `make'.
case `$am_make -s -f confmf 2> /dev/null` in #(
*the\ am__doit\ target*)
am__include=include
@@ -3802,8 +3754,8 @@ else
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
- # making a dummy file named 'D' -- because '-MD' means "put the output
- # in D".
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
rm -rf conftest.dir
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
@@ -3838,16 +3790,16 @@ else
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
- # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
- # Solaris 10 /bin/sh.
- echo '/* dummy */' > sub/conftst$i.h
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
- # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
- # handle '-M -o', and we need to detect this. Also, some Intel
- # versions had trouble with output in subdirs.
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
am__obj=sub/conftest.${OBJEXT-o}
am__minus_obj="-o $am__obj"
case $depmode in
@@ -3856,8 +3808,8 @@ else
test "$am__universal" = false || continue
;;
nosideeffect)
- # After this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested.
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
if test "x$enable_dependency_tracking" = xyes; then
continue
else
@@ -3865,7 +3817,7 @@ else
fi
;;
msvc7 | msvc7msys | msvisualcpp | msvcmsys)
- # This compiler won't grok '-c -o', but also, the minuso test has
+ # This compiler won't grok `-c -o', but also, the minuso test has
# not run yet. These depmodes are late enough in the game, and
# so weak that their functioning should not be impacted.
am__obj=conftest.${OBJEXT-o}
@@ -4379,6 +4331,8 @@ $as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+# Check SSE, SSE2 and SSE3 support
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -4629,15 +4583,15 @@ $as_echo "$ax_cv_have_ssse3_ext" >&6; }
$as_echo "#define HAVE_MMX /**/" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -mmmx" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -mmmx" >&5
$as_echo_n "checking whether C compiler accepts -mmmx... " >&6; }
-if ${ax_cv_c_flags__mmmx+:} false; then :
+if ${ax_cv_check_cflags___mmmx+:} false; then :
$as_echo_n "(cached) " >&6
else
- ax_save_FLAGS=$CFLAGS
- CFLAGS="-mmmx"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -mmmx"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -4649,21 +4603,19 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- ax_cv_c_flags__mmmx=yes
+ ax_cv_check_cflags___mmmx=yes
else
- ax_cv_c_flags__mmmx=no
+ ax_cv_check_cflags___mmmx=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CFLAGS=$ax_save_FLAGS
+ CFLAGS=$ax_check_save_flags
fi
-
-eval ax_check_compiler_flags=$ax_cv_c_flags__mmmx
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
-$as_echo "$ax_check_compiler_flags" >&6; }
-if test "x$ax_check_compiler_flags" = xyes; then
- SIMD_FLAGS="$SIMD_FLAGS -mmmx"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___mmmx" >&5
+$as_echo "$ax_cv_check_cflags___mmmx" >&6; }
+if test x"$ax_cv_check_cflags___mmmx" = xyes; then :
+ SIMD_FLAGS="$SIMD_FLAGS -mmmx"
else
- :
+ :
fi
fi
@@ -4672,15 +4624,15 @@ fi
$as_echo "#define HAVE_SSE /**/" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse" >&5
$as_echo_n "checking whether C compiler accepts -msse... " >&6; }
-if ${ax_cv_c_flags__msse+:} false; then :
+if ${ax_cv_check_cflags___msse+:} false; then :
$as_echo_n "(cached) " >&6
else
- ax_save_FLAGS=$CFLAGS
- CFLAGS="-msse"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -msse"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -4692,21 +4644,19 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- ax_cv_c_flags__msse=yes
+ ax_cv_check_cflags___msse=yes
else
- ax_cv_c_flags__msse=no
+ ax_cv_check_cflags___msse=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CFLAGS=$ax_save_FLAGS
+ CFLAGS=$ax_check_save_flags
fi
-
-eval ax_check_compiler_flags=$ax_cv_c_flags__msse
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
-$as_echo "$ax_check_compiler_flags" >&6; }
-if test "x$ax_check_compiler_flags" = xyes; then
- SIMD_FLAGS="$SIMD_FLAGS -msse"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse" >&5
+$as_echo "$ax_cv_check_cflags___msse" >&6; }
+if test x"$ax_cv_check_cflags___msse" = xyes; then :
+ SIMD_FLAGS="$SIMD_FLAGS -msse"
else
- :
+ :
fi
fi
@@ -4715,15 +4665,15 @@ fi
$as_echo "#define HAVE_SSE2 /**/" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse2" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse2" >&5
$as_echo_n "checking whether C compiler accepts -msse2... " >&6; }
-if ${ax_cv_c_flags__msse2+:} false; then :
+if ${ax_cv_check_cflags___msse2+:} false; then :
$as_echo_n "(cached) " >&6
else
- ax_save_FLAGS=$CFLAGS
- CFLAGS="-msse2"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -msse2"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -4735,21 +4685,19 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- ax_cv_c_flags__msse2=yes
+ ax_cv_check_cflags___msse2=yes
else
- ax_cv_c_flags__msse2=no
+ ax_cv_check_cflags___msse2=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CFLAGS=$ax_save_FLAGS
+ CFLAGS=$ax_check_save_flags
fi
-
-eval ax_check_compiler_flags=$ax_cv_c_flags__msse2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
-$as_echo "$ax_check_compiler_flags" >&6; }
-if test "x$ax_check_compiler_flags" = xyes; then
- SIMD_FLAGS="$SIMD_FLAGS -msse2"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse2" >&5
+$as_echo "$ax_cv_check_cflags___msse2" >&6; }
+if test x"$ax_cv_check_cflags___msse2" = xyes; then :
+ SIMD_FLAGS="$SIMD_FLAGS -msse2"
else
- :
+ :
fi
fi
@@ -4758,15 +4706,15 @@ fi
$as_echo "#define HAVE_SSE3 /**/" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse3" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts -msse3" >&5
$as_echo_n "checking whether C compiler accepts -msse3... " >&6; }
-if ${ax_cv_c_flags__msse3+:} false; then :
+if ${ax_cv_check_cflags___msse3+:} false; then :
$as_echo_n "(cached) " >&6
else
- ax_save_FLAGS=$CFLAGS
- CFLAGS="-msse3"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS -msse3"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -4778,21 +4726,19 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- ax_cv_c_flags__msse3=yes
+ ax_cv_check_cflags___msse3=yes
else
- ax_cv_c_flags__msse3=no
+ ax_cv_check_cflags___msse3=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CFLAGS=$ax_save_FLAGS
+ CFLAGS=$ax_check_save_flags
fi
-
-eval ax_check_compiler_flags=$ax_cv_c_flags__msse3
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
-$as_echo "$ax_check_compiler_flags" >&6; }
-if test "x$ax_check_compiler_flags" = xyes; then
- SIMD_FLAGS="$SIMD_FLAGS -msse3"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_check_cflags___msse3" >&5
+$as_echo "$ax_cv_check_cflags___msse3" >&6; }
+if test x"$ax_cv_check_cflags___msse3" = xyes; then :
+ SIMD_FLAGS="$SIMD_FLAGS -msse3"
else
- :
+ :
fi
fi
@@ -4805,526 +4751,170 @@ $as_echo "#define HAVE_SSSE3 /**/" >>confdefs.h
+CFLAGS="$CFLAGS $SIMD_FLAGS"
-# Checks for programs.
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
- ac_ct_CC=$CC
- # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-else
- CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- fi
-fi
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# != 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
- fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
- if test -n "$ac_tool_prefix"; then
- for ac_prog in cl.exe
- do
- # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$CC" && break
- done
-fi
-if test -z "$CC"; then
- ac_ct_CC=$CC
- for ac_prog in cl.exe
-do
- # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
+# Set compiler compatibility flags
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
+$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
+if ${ac_cv_prog_cc_c99+:} false; then :
$as_echo_n "(cached) " >&6
else
- if test -n "$ac_ct_CC"; then
- ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
- test -n "$ac_ct_CC" && break
-done
-
- if test "x$ac_ct_CC" = x; then
- CC=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- CC=$ac_ct_CC
- fi
-fi
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
-fi
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ your preprocessor is broken;
+#endif
+#if BIG_OK
+#else
+ your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
- { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_compiler $ac_option >&5") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- sed '10a\
-... rest of stderr output deleted ...
- 10q' conftest.err >conftest.er1
- cat conftest.er1 >&5
- fi
- rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }
-done
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
+typedef const char *ccp;
-int
-main ()
+static inline int
+test_restrict (ccp restrict text)
{
-#ifndef __GNUC__
- choke me
-#endif
-
- ;
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+ continue;
return 0;
}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_compiler_gnu=yes
-else
- ac_compiler_gnu=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
- GCC=yes
-else
- GCC=
-fi
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_save_c_werror_flag=$ac_c_werror_flag
- ac_c_werror_flag=yes
- ac_cv_prog_cc_g=no
- CFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
- ;
- return 0;
+ const char *str;
+ int number;
+ float fnumber;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case 's': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case 'd': // int
+ number = va_arg (args_copy, int);
+ break;
+ case 'f': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_g=yes
-else
- CFLAGS=""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
int
main ()
{
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+ // Check bool.
+ _Bool success = false;
-else
- ac_c_werror_flag=$ac_save_c_werror_flag
- CFLAGS="-g"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
-int
-main ()
-{
+ // Check varargs.
+ test_varargs ("s, d' f .", "string", 65, 34.234);
+ test_varargs_macros ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_g=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- ac_c_werror_flag=$ac_save_c_werror_flag
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
- CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
- if test "$GCC" = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-g"
- fi
-else
- if test "$GCC" = yes; then
- CFLAGS="-O2"
- else
- CFLAGS=
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+ || dynamic_array[ni.number - 1] != 543);
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
;
return 0;
}
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
do
CC="$ac_save_CC $ac_arg"
if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_c89=$ac_arg
+ ac_cv_prog_cc_c99=$ac_arg
fi
rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c89" != "xno" && break
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
fi
# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
+case "x$ac_cv_prog_cc_c99" in
x)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
$as_echo "none needed" >&6; } ;;
@@ -5332,149 +4922,144 @@ $as_echo "none needed" >&6; } ;;
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
$as_echo "unsupported" >&6; } ;;
*)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+ CC="$CC $ac_cv_prog_cc_c99"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c99" != xno; then :
fi
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-depcc="$CC" am_compiler_list=
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
-$as_echo_n "checking dependency style of $depcc... " >&6; }
-if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+if test "x$CC" != xcc; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
+$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5
+$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
+fi
+set dummy $CC; ac_cc=`$as_echo "$2" |
+ sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then :
$as_echo_n "(cached) " >&6
else
- if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
- # We make a subdir and do the tests there. Otherwise we can end up
- # making bogus files that we don't know about and never remove. For
- # instance it was reported that on HP-UX the gcc test will end up
- # making a dummy file named 'D' -- because '-MD' means "put the output
- # in D".
- rm -rf conftest.dir
- mkdir conftest.dir
- # Copy depcomp to subdir because otherwise we won't find it if we're
- # using a relative directory.
- cp "$am_depcomp" conftest.dir
- cd conftest.dir
- # We will build objects and dependencies in a subdirectory because
- # it helps to detect inapplicable dependency modes. For instance
- # both Tru64's cc and ICC support -MD to output dependencies as a
- # side effect of compilation, but ICC will put the dependencies in
- # the current directory while Tru64 will put them in the object
- # directory.
- mkdir sub
-
- am_cv_CC_dependencies_compiler_type=none
- if test "$am_compiler_list" = ""; then
- am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
- fi
- am__universal=false
- case " $depcc " in #(
- *\ -arch\ *\ -arch\ *) am__universal=true ;;
- esac
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
- for depmode in $am_compiler_list; do
- # Setup a source with many dependencies, because some compilers
- # like to wrap large dependency lists on column 80 (with \), and
- # we should not choose a depcomp mode which is confused by this.
- #
- # We need to recreate these files for each test, as the compiler may
- # overwrite some of them when testing with obscure command lines.
- # This happens at least with the AIX C compiler.
- : > sub/conftest.c
- for i in 1 2 3 4 5 6; do
- echo '#include "conftst'$i'.h"' >> sub/conftest.c
- # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
- # Solaris 10 /bin/sh.
- echo '/* dummy */' > sub/conftst$i.h
- done
- echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+int
+main ()
+{
- # We check with '-c' and '-o' for the sake of the "dashmstdout"
- # mode. It turns out that the SunPro C++ compiler does not properly
- # handle '-M -o', and we need to detect this. Also, some Intel
- # versions had trouble with output in subdirs.
- am__obj=sub/conftest.${OBJEXT-o}
- am__minus_obj="-o $am__obj"
- case $depmode in
- gcc)
- # This depmode causes a compiler race in universal mode.
- test "$am__universal" = false || continue
- ;;
- nosideeffect)
- # After this tag, mechanisms are not by side-effect, so they'll
- # only be used when explicitly requested.
- if test "x$enable_dependency_tracking" = xyes; then
- continue
+ ;
+ return 0;
+}
+_ACEOF
+# Make sure it works both with $CC and with simple cc.
+# We do the test twice because some compilers refuse to overwrite an
+# existing .o file with -o, though they will create one.
+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+rm -f conftest2.*
+if { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } &&
+ test -f conftest2.$ac_objext && { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; };
+then
+ eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+ if test "x$CC" != xcc; then
+ # Test first that cc exists at all.
+ if { ac_try='cc -c conftest.$ac_ext >&5'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+ rm -f conftest2.*
+ if { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } &&
+ test -f conftest2.$ac_objext && { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; };
+ then
+ # cc works too.
+ :
else
- break
- fi
- ;;
- msvc7 | msvc7msys | msvisualcpp | msvcmsys)
- # This compiler won't grok '-c -o', but also, the minuso test has
- # not run yet. These depmodes are late enough in the game, and
- # so weak that their functioning should not be impacted.
- am__obj=conftest.${OBJEXT-o}
- am__minus_obj=
- ;;
- none) break ;;
- esac
- if depmode=$depmode \
- source=sub/conftest.c object=$am__obj \
- depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
- $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
- >/dev/null 2>conftest.err &&
- grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
- grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
- grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
- ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
- # icc doesn't choke on unknown options, it will just issue warnings
- # or remarks (even with -Werror). So we grep stderr for any message
- # that says an option was ignored or not supported.
- # When given -MP, icc 7.0 and 7.1 complain thusly:
- # icc: Command line warning: ignoring option '-M'; no argument required
- # The diagnosis changed in icc 8.0:
- # icc: Command line remark: option '-MP' not supported
- if (grep 'ignoring option' conftest.err ||
- grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
- am_cv_CC_dependencies_compiler_type=$depmode
- break
+ # cc exists but doesn't like -o.
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
fi
fi
- done
-
- cd ..
- rm -rf conftest.dir
+ fi
else
- am_cv_CC_dependencies_compiler_type=none
+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
fi
+rm -f core conftest*
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
-$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
-CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
-
- if
- test "x$enable_dependency_tracking" != xno \
- && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
- am__fastdepCC_TRUE=
- am__fastdepCC_FALSE='#'
+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
else
- am__fastdepCC_TRUE='#'
- am__fastdepCC_FALSE=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
+
+fi
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+if test "$am_t" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
fi
- # for automake 1.12
+ac_c_preproc_warn_flag=yes
+
+# Checks for programs.
if test -n "$ac_tool_prefix"; then
for ac_prog in ar lib "link -lib"
do
@@ -5634,9 +5219,40 @@ unknown)
as_fn_error $? "could not determine $AR interface" "$LINENO" 5
;;
esac
-
+ # call AM_PROG_AR only if available
# Initialize libtool
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+ for pkg in $enableval; do
+ IFS="$lt_save_ifs"
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS="$lt_save_ifs"
+ ;;
+ esac
+else
+ enable_static=no
+fi
+
+
+
+
+
+
+
+
+
case `pwd` in
*\ * | *\ *)
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
@@ -6793,10 +6409,6 @@ freebsd* | dragonfly*)
fi
;;
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
haiku*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -6835,11 +6447,11 @@ irix5* | irix6* | nonstopux*)
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
-netbsd*)
+netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
else
@@ -8858,36 +8470,6 @@ fi
- # Check whether --enable-static was given.
-if test "${enable_static+set}" = set; then :
- enableval=$enable_static; p=${PACKAGE-default}
- case $enableval in
- yes) enable_static=yes ;;
- no) enable_static=no ;;
- *)
- enable_static=no
- # Look at the argument we got. We use all the common list separators.
- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
- for pkg in $enableval; do
- IFS="$lt_save_ifs"
- if test "X$pkg" = "X$p"; then
- enable_static=yes
- fi
- done
- IFS="$lt_save_ifs"
- ;;
- esac
-else
- enable_static=yes
-fi
-
-
-
-
-
-
-
-
# Check whether --with-pic was given.
@@ -9494,7 +9076,7 @@ lt_prog_compiler_static=
lt_prog_compiler_static='-non_shared'
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
# old Intel for x86_64 which still supported -KPIC.
ecc*)
@@ -9972,6 +9554,9 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie
openbsd*)
with_gnu_ld=no
;;
+ linux* | k*bsd*-gnu | gnu*)
+ link_all_deplibs=no
+ ;;
esac
ld_shlibs=yes
@@ -10193,7 +9778,7 @@ _LT_EOF
fi
;;
- netbsd*)
+ netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
@@ -10370,6 +9955,7 @@ _LT_EOF
if test "$aix_use_runtimelinking" = yes; then
shared_flag="$shared_flag "'${wl}-G'
fi
+ link_all_deplibs=no
else
# not using gcc
if test "$host_cpu" = ia64; then
@@ -10823,7 +10409,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; }
link_all_deplibs=yes
;;
- netbsd*)
+ netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
@@ -11660,17 +11246,6 @@ freebsd* | dragonfly*)
esac
;;
-gnu*)
- version_type=linux # correct to gnu/linux during the next big refactor
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
haiku*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
@@ -11787,7 +11362,7 @@ linux*oldld* | linux*aout* | linux*coff*)
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
@@ -11851,6 +11426,18 @@ fi
dynamic_linker='GNU/Linux ld.so'
;;
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
netbsd*)
version_type=sunos
need_lib_prefix=no
@@ -12823,6 +12410,128 @@ CC="$lt_save_CC"
+# Use pkg-config
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for reentrant lex" >&5
$as_echo_n "checking for reentrant lex... " >&6; }
if ${ac_cv_path_LEX+:} false; then :
@@ -13099,254 +12808,64 @@ if test "x$YACC_BISON" != "xbison"; then :
fi
-# Set compiler compatibility flags
-ac_c_preproc_warn_flag=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
-$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
-if ${ac_cv_prog_cc_c99+:} false; then :
+# Check for Ragel
+# Extract the first word of "ragel", so it can be a program name with args.
+set dummy ragel; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_RAGEL+:} false; then :
$as_echo_n "(cached) " >&6
else
- ac_cv_prog_cc_c99=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <stdio.h>
-
-// Check varargs macros. These examples are taken from C99 6.10.3.5.
-#define debug(...) fprintf (stderr, __VA_ARGS__)
-#define showlist(...) puts (#__VA_ARGS__)
-#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
-static void
-test_varargs_macros (void)
-{
- int x = 1234;
- int y = 5678;
- debug ("Flag");
- debug ("X = %d\n", x);
- showlist (The first, second, and third items.);
- report (x>y, "x is %d but y is %d", x, y);
-}
-
-// Check long long types.
-#define BIG64 18446744073709551615ull
-#define BIG32 4294967295ul
-#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
-#if !BIG_OK
- your preprocessor is broken;
-#endif
-#if BIG_OK
-#else
- your preprocessor is broken;
-#endif
-static long long int bignum = -9223372036854775807LL;
-static unsigned long long int ubignum = BIG64;
-
-struct incomplete_array
-{
- int datasize;
- double data[];
-};
-
-struct named_init {
- int number;
- const wchar_t *name;
- double average;
-};
-
-typedef const char *ccp;
-
-static inline int
-test_restrict (ccp restrict text)
-{
- // See if C++-style comments work.
- // Iterate through items via the restricted pointer.
- // Also check for declarations in for loops.
- for (unsigned int i = 0; *(text+i) != '\0'; ++i)
- continue;
- return 0;
-}
-
-// Check varargs and va_copy.
-static void
-test_varargs (const char *format, ...)
-{
- va_list args;
- va_start (args, format);
- va_list args_copy;
- va_copy (args_copy, args);
-
- const char *str;
- int number;
- float fnumber;
-
- while (*format)
- {
- switch (*format++)
- {
- case 's': // string
- str = va_arg (args_copy, const char *);
- break;
- case 'd': // int
- number = va_arg (args_copy, int);
- break;
- case 'f': // float
- fnumber = va_arg (args_copy, double);
- break;
- default:
- break;
- }
- }
- va_end (args_copy);
- va_end (args);
-}
-
-int
-main ()
-{
-
- // Check bool.
- _Bool success = false;
-
- // Check restrict.
- if (test_restrict ("String literal") == 0)
- success = true;
- char *restrict newvar = "Another string";
-
- // Check varargs.
- test_varargs ("s, d' f .", "string", 65, 34.234);
- test_varargs_macros ();
-
- // Check flexible array members.
- struct incomplete_array *ia =
- malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
- ia->datasize = 10;
- for (int i = 0; i < ia->datasize; ++i)
- ia->data[i] = i * 1.234;
-
- // Check named initializers.
- struct named_init ni = {
- .number = 34,
- .name = L"Test wide string",
- .average = 543.34343,
- };
-
- ni.number = 58;
-
- int dynamic_array[ni.number];
- dynamic_array[ni.number - 1] = 543;
-
- // work around unused variable warnings
- return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
- || dynamic_array[ni.number - 1] != 543);
-
- ;
- return 0;
-}
-_ACEOF
-for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
+ case $RAGEL in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_RAGEL="$RAGEL" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
do
- CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_c99=$ac_arg
-fi
-rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c99" != "xno" && break
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_RAGEL="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
+ done
+IFS=$as_save_IFS
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c99" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c99"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
-$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
+ test -z "$ac_cv_path_RAGEL" && ac_cv_path_RAGEL="true"
+ ;;
esac
-if test "x$ac_cv_prog_cc_c99" != xno; then :
-
fi
-
-
-
-# Check whether --enable-ldns was given.
-if test "${enable_ldns+set}" = set; then :
- enableval=$enable_ldns; case "${enableval}" in
- yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ldns_rr_list_pop_rrset" >&5
-$as_echo_n "checking for library containing ldns_rr_list_pop_rrset... " >&6; }
-if ${ac_cv_search_ldns_rr_list_pop_rrset+:} false; then :
- $as_echo_n "(cached) " >&6
+RAGEL=$ac_cv_path_RAGEL
+if test -n "$RAGEL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RAGEL" >&5
+$as_echo "$RAGEL" >&6; }
else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char ldns_rr_list_pop_rrset ();
-int
-main ()
-{
-return ldns_rr_list_pop_rrset ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' ldns; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_ldns_rr_list_pop_rrset=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_ldns_rr_list_pop_rrset+:} false; then :
- break
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
-done
-if ${ac_cv_search_ldns_rr_list_pop_rrset+:} false; then :
+
+ if test "$RAGEL" != "true"; then
+ HAVE_RAGEL_TRUE=
+ HAVE_RAGEL_FALSE='#'
else
- ac_cv_search_ldns_rr_list_pop_rrset=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
+ HAVE_RAGEL_TRUE='#'
+ HAVE_RAGEL_FALSE=
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ldns_rr_list_pop_rrset" >&5
-$as_echo "$ac_cv_search_ldns_rr_list_pop_rrset" >&6; }
-ac_res=$ac_cv_search_ldns_rr_list_pop_rrset
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-$as_echo "#define HAVE_LDNS 1" >>confdefs.h
-else
- as_fn_error $? "ldns not found" "$LINENO" 5
-fi
- ;;
- no) ldns=false ;;
- *) as_fn_error $? "bad value ${enableval} for --enable-ldns" "$LINENO" 5 ;;
- esac
-else
- ldns=false
+# Set FSM type for Ragel
+FSM_TYPE=-T0
+
+# Check whether --enable-fastparser was given.
+if test "${enable_fastparser+set}" = set; then :
+ enableval=$enable_fastparser; touch src/zscanner/scanner.rl; FSM_TYPE=-G2
+
fi
@@ -13407,7 +12926,7 @@ $as_echo "#define DEBUG_ENABLE_VERBOSE 1" >>confdefs.h
$as_echo "#define DEBUG_ENABLE_BRIEF 1" >>confdefs.h
- ;;
+ ;;
xverbose)
$as_echo "#define DEBUG_ENABLE_VERBOSE 1" >>confdefs.h
@@ -13415,7 +12934,7 @@ $as_echo "#define DEBUG_ENABLE_VERBOSE 1" >>confdefs.h
$as_echo "#define DEBUG_ENABLE_BRIEF 1" >>confdefs.h
- ;;
+ ;;
xbrief)
$as_echo "#define DEBUG_ENABLE_BRIEF 1" >>confdefs.h
@@ -13582,11 +13101,16 @@ fi
# Check whether --enable-lto was given.
if test "${enable_lto+set}" = set; then :
enableval=$enable_lto; case "${enableval}" in
- yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts \"-flto\"" >&5
+ yes) as_CACHEVAR=`$as_echo "ax_cv_check_cflags__"-flto"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts \"-flto\"" >&5
$as_echo_n "checking whether C compiler accepts \"-flto\"... " >&6; }
-ax_save_FLAGS=$CFLAGS
- CFLAGS=""-flto""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS "-flto""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -13598,19 +13122,20 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- eval `$as_echo "ax_cv_c_flags_"-flto"" | $as_tr_sh`=yes
+ eval "$as_CACHEVAR=yes"
else
- eval `$as_echo "ax_cv_c_flags_"-flto"" | $as_tr_sh`=no
+ eval "$as_CACHEVAR=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CFLAGS=$ax_save_FLAGS
-eval ax_check_compiler_flags=$`$as_echo "ax_cv_c_flags_"-flto"" | $as_tr_sh`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
-$as_echo "$ax_check_compiler_flags" >&6; }
-if test "x$ax_check_compiler_flags" = xyes; then
- CFLAGS="$CFLAGS -flto"
+ CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then :
+ CFLAGS="$CFLAGS -flto"
else
- :
+ :
fi
;;
no) ;;
@@ -13619,11 +13144,25 @@ fi
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts \"-fpredictive-commoning\"" >&5
+# Check for enable microseconds in log messages
+# Check whether --enable-microseconds-log was given.
+if test "${enable_microseconds_log+set}" = set; then :
+ enableval=$enable_microseconds_log;
+$as_echo "#define ENABLE_MICROSECONDS_LOG 1" >>confdefs.h
+
+fi
+
+
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags_"-Werror"_"-fpredictive-commoning"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts \"-fpredictive-commoning\"" >&5
$as_echo_n "checking whether C compiler accepts \"-fpredictive-commoning\"... " >&6; }
-ax_save_FLAGS=$CFLAGS
- CFLAGS=""-fpredictive-commoning""
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+if eval \${$as_CACHEVAR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS "-Werror" "-fpredictive-commoning""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
@@ -13635,86 +13174,176 @@ main ()
}
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
- eval `$as_echo "ax_cv_c_flags_"-fpredictive-commoning"" | $as_tr_sh`=yes
+ eval "$as_CACHEVAR=yes"
else
- eval `$as_echo "ax_cv_c_flags_"-fpredictive-commoning"" | $as_tr_sh`=no
+ eval "$as_CACHEVAR=no"
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CFLAGS=$ax_save_FLAGS
-eval ax_check_compiler_flags=$`$as_echo "ax_cv_c_flags_"-fpredictive-commoning"" | $as_tr_sh`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_check_compiler_flags" >&5
-$as_echo "$ax_check_compiler_flags" >&6; }
-if test "x$ax_check_compiler_flags" = xyes; then
- CFLAGS="$CFLAGS -fpredictive-commoning"
+ CFLAGS=$ax_check_save_flags
+fi
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then :
+ CFLAGS="$CFLAGS -fpredictive-commoning"
else
- :
+ :
fi
-# Checks for libraries.
-# FIXME: Replace `main' with a function in `-lm':
-# TODO: check if paths exist before appending
-CFLAGS="$CFLAGS -I/usr/local/include $SIMD_FLAGS"
-LDFLAGS="$LDFLAGS -L/usr/local/lib"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pow" >&5
-$as_echo_n "checking for library containing pow... " >&6; }
-if ${ac_cv_search_pow+:} false; then :
+# Disable strict aliasing
+# FIXME: we break strict aliasing on many occurenes, disable it until resolved or kept
+as_CACHEVAR=`$as_echo "ax_cv_check_cflags__"-fno-strict-aliasing"" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler accepts \"-fno-strict-aliasing\"" >&5
+$as_echo_n "checking whether C compiler accepts \"-fno-strict-aliasing\"... " >&6; }
+if eval \${$as_CACHEVAR+:} false; then :
$as_echo_n "(cached) " >&6
else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+
+ ax_check_save_flags=$CFLAGS
+ CFLAGS="$CFLAGS "-fno-strict-aliasing""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pow ();
int
main ()
{
-return pow ();
+
;
return 0;
}
_ACEOF
-for ac_lib in '' m; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_pow=$ac_res
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$as_CACHEVAR=yes"
+else
+ eval "$as_CACHEVAR=no"
fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_pow+:} false; then :
- break
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$ax_check_save_flags
fi
-done
-if ${ac_cv_search_pow+:} false; then :
+eval ac_res=\$$as_CACHEVAR
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if test x"`eval 'as_val=${'$as_CACHEVAR'};$as_echo "$as_val"'`" = xyes; then :
+ CFLAGS="$CFLAGS -fno-strict-aliasing"
+else
+ :
+fi
+
+
+# Default directories
+run_dir="${localstatedir}/run/knot"
+
+# Check whether --with-rundir was given.
+if test "${with_rundir+set}" = set; then :
+ withval=$with_rundir; run_dir=$withval
+fi
+
+
+
+storage_dir="${sharedstatedir}/knot"
+
+# Check whether --with-storage was given.
+if test "${with_storage+set}" = set; then :
+ withval=$with_storage; storage_dir=$withval
+fi
+
+
+
+# Checks for libraries.
+# FIXME: Replace `main' with a function in `-lm':
+
+# Check whether --with-urcu was given.
+if test "${with_urcu+set}" = set; then :
+ withval=$with_urcu;
+fi
+
+
+if test "$with_urcu" != "no"; then :
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for liburcu" >&5
+$as_echo_n "checking for liburcu... " >&6; }
+
+if test -n "$liburcu_CFLAGS"; then
+ pkg_cv_liburcu_CFLAGS="$liburcu_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liburcu\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liburcu") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_liburcu_CFLAGS=`$PKG_CONFIG --cflags "liburcu" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
else
- ac_cv_search_pow=no
+ pkg_failed=yes
fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
+ else
+ pkg_failed=untried
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pow" >&5
-$as_echo "$ac_cv_search_pow" >&6; }
-ac_res=$ac_cv_search_pow
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+if test -n "$liburcu_LIBS"; then
+ pkg_cv_liburcu_LIBS="$liburcu_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"liburcu\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "liburcu") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_liburcu_LIBS=`$PKG_CONFIG --libs "liburcu" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
fi
+ if test $_pkg_short_errors_supported = yes; then
+ liburcu_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "liburcu" 2>&1`
+ else
+ liburcu_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "liburcu" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$liburcu_PKG_ERRORS" >&5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
-$as_echo_n "checking for library containing pthread_create... " >&6; }
-if ${ac_cv_search_pthread_create+:} false; then :
+
+ for try_urcu in "$with_urcu" "" "/usr/local"; do
+ save_LIBS="$LIBS"
+ save_CPPFLAGS="$CPPFLAGS"
+
+ if test -d "$try_urcu"; then :
+
+ liburcu_CFLAGS="-I$try_urcu/include"
+ liburcu_LIBS="-L$try_urcu/lib"
+
+else
+
+ liburcu_CFLAGS=""
+ liburcu_LIBS=""
+
+fi
+
+ CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS"
+ LIBS="$LIBS $liburcu_LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing rcu_set_pointer_sym" >&5
+$as_echo_n "checking for library containing rcu_set_pointer_sym... " >&6; }
+if ${ac_cv_search_rcu_set_pointer_sym+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
@@ -13727,16 +13356,16 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char pthread_create ();
+char rcu_set_pointer_sym ();
int
main ()
{
-return pthread_create ();
+return rcu_set_pointer_sym ();
;
return 0;
}
_ACEOF
-for ac_lib in '' pthread; do
+for ac_lib in '' urcu; do
if test -z "$ac_lib"; then
ac_res="none required"
else
@@ -13744,33 +13373,73 @@ for ac_lib in '' pthread; do
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_pthread_create=$ac_res
+ ac_cv_search_rcu_set_pointer_sym=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
- if ${ac_cv_search_pthread_create+:} false; then :
+ if ${ac_cv_search_rcu_set_pointer_sym+:} false; then :
break
fi
done
-if ${ac_cv_search_pthread_create+:} false; then :
+if ${ac_cv_search_rcu_set_pointer_sym+:} false; then :
else
- ac_cv_search_pthread_create=no
+ ac_cv_search_rcu_set_pointer_sym=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5
-$as_echo "$ac_cv_search_pthread_create" >&6; }
-ac_res=$ac_cv_search_pthread_create
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_rcu_set_pointer_sym" >&5
+$as_echo "$ac_cv_search_rcu_set_pointer_sym" >&6; }
+ac_res=$ac_cv_search_rcu_set_pointer_sym
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ with_urcu=yes
+ break
+
else
- as_fn_error $? "pthreads not found" "$LINENO" 5
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LIBS="$save_LIBS"
+ with_urcu=no
+ # do not cache result of AC_SEARCH_LIBS test
+ unset ac_cv_search_rcu_set_pointer_sym
+
+fi
+
+ done
+
+ if test "$with_urcu" = "no"; then :
+
+ as_fn_error $? "liburcu is required" "$LINENO" 5
+
+fi
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ for try_urcu in "$with_urcu" "" "/usr/local"; do
+ save_LIBS="$LIBS"
+ save_CPPFLAGS="$CPPFLAGS"
+
+ if test -d "$try_urcu"; then :
+
+ liburcu_CFLAGS="-I$try_urcu/include"
+ liburcu_LIBS="-L$try_urcu/lib"
+
+else
+
+ liburcu_CFLAGS=""
+ liburcu_LIBS=""
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing rcu_set_pointer_sym" >&5
+ CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS"
+ LIBS="$LIBS $liburcu_LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing rcu_set_pointer_sym" >&5
$as_echo_n "checking for library containing rcu_set_pointer_sym... " >&6; }
if ${ac_cv_search_rcu_set_pointer_sym+:} false; then :
$as_echo_n "(cached) " >&6
@@ -13824,8 +13493,39 @@ ac_res=$ac_cv_search_rcu_set_pointer_sym
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ with_urcu=yes
+ break
+
else
- as_fn_error $? "liburcu not found" "$LINENO" 5
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LIBS="$save_LIBS"
+ with_urcu=no
+ # do not cache result of AC_SEARCH_LIBS test
+ unset ac_cv_search_rcu_set_pointer_sym
+
+fi
+
+ done
+
+ if test "$with_urcu" = "no"; then :
+
+ as_fn_error $? "liburcu is required" "$LINENO" 5
+
+fi
+
+else
+ liburcu_CFLAGS=$pkg_cv_liburcu_CFLAGS
+ liburcu_LIBS=$pkg_cv_liburcu_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS"
+ LIBS="$LIBS $liburcu_LIBS"
+ with_urcu=yes
+
+fi
+
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing urcu_init" >&5
@@ -13884,9 +13584,99 @@ if test "$ac_res" != no; then :
as_fn_error $? "liburcu is too old (< 0.4.0), urcu_init symbol found" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
-$as_echo_n "checking for library containing dlopen... " >&6; }
-if ${ac_cv_search_dlopen+:} false; then :
+
+
+# Check whether --with-openssl was given.
+if test "${with_openssl+set}" = set; then :
+ withval=$with_openssl;
+fi
+
+
+if test "$with_openssl" != "no"; then :
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libcrypto" >&5
+$as_echo_n "checking for libcrypto... " >&6; }
+
+if test -n "$libcrypto_CFLAGS"; then
+ pkg_cv_libcrypto_CFLAGS="$libcrypto_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcrypto\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcrypto") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_libcrypto_CFLAGS=`$PKG_CONFIG --cflags "libcrypto" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$libcrypto_LIBS"; then
+ pkg_cv_libcrypto_LIBS="$libcrypto_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcrypto\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcrypto") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_libcrypto_LIBS=`$PKG_CONFIG --libs "libcrypto" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ libcrypto_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libcrypto" 2>&1`
+ else
+ libcrypto_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libcrypto" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$libcrypto_PKG_ERRORS" >&5
+
+
+
+ for try_openssl in "$with_openssl" "" "/usr/local"; do
+ save_LIBS="$LIBS"
+ save_CPPFLAGS="$CPPFLAGS"
+
+ if test -d "$try_openssl"; then :
+
+ libcrypto_CFLAGS="-I$try_openssl/include"
+ libcrypto_LIBS="-L$try_openssl/lib"
+
+else
+
+ libcrypto_CFLAGS=""
+ libcrypto_LIBS=""
+
+fi
+
+ CPPFLAGS="$CPPFLAGS $libcrypto_CFLAGS"
+ LIBS="$LIBS $libcrypto_LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing OpenSSL_add_all_digests" >&5
+$as_echo_n "checking for library containing OpenSSL_add_all_digests... " >&6; }
+if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
@@ -13899,16 +13689,16 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char dlopen ();
+char OpenSSL_add_all_digests ();
int
main ()
{
-return dlopen ();
+return OpenSSL_add_all_digests ();
;
return 0;
}
_ACEOF
-for ac_lib in '' dl; do
+for ac_lib in '' crypto; do
if test -z "$ac_lib"; then
ac_res="none required"
else
@@ -13916,33 +13706,77 @@ for ac_lib in '' dl; do
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_dlopen=$ac_res
+ ac_cv_search_OpenSSL_add_all_digests=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
- if ${ac_cv_search_dlopen+:} false; then :
+ if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
break
fi
done
-if ${ac_cv_search_dlopen+:} false; then :
+if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
else
- ac_cv_search_dlopen=no
+ ac_cv_search_OpenSSL_add_all_digests=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
-$as_echo "$ac_cv_search_dlopen" >&6; }
-ac_res=$ac_cv_search_dlopen
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_OpenSSL_add_all_digests" >&5
+$as_echo "$ac_cv_search_OpenSSL_add_all_digests" >&6; }
+ac_res=$ac_cv_search_OpenSSL_add_all_digests
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ with_openssl=yes
+ break
+
+else
+
+ with_openssl=no
+ # do not cache result of AC_SEARCH_LIBS test
+ unset ac_cv_search_OpenSSL_add_all_digests
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
-$as_echo_n "checking for library containing clock_gettime... " >&6; }
-if ${ac_cv_search_clock_gettime+:} false; then :
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LIBS="$save_LIBS"
+ done
+
+ if test "$with_openssl" = "no"; then :
+
+ as_fn_error $? "libcrypto (part of OpenSSL) is required" "$LINENO" 5
+
+fi
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+ for try_openssl in "$with_openssl" "" "/usr/local"; do
+ save_LIBS="$LIBS"
+ save_CPPFLAGS="$CPPFLAGS"
+
+ if test -d "$try_openssl"; then :
+
+ libcrypto_CFLAGS="-I$try_openssl/include"
+ libcrypto_LIBS="-L$try_openssl/lib"
+
+else
+
+ libcrypto_CFLAGS=""
+ libcrypto_LIBS=""
+
+fi
+
+ CPPFLAGS="$CPPFLAGS $libcrypto_CFLAGS"
+ LIBS="$LIBS $libcrypto_LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing OpenSSL_add_all_digests" >&5
+$as_echo_n "checking for library containing OpenSSL_add_all_digests... " >&6; }
+if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
@@ -13955,16 +13789,16 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char clock_gettime ();
+char OpenSSL_add_all_digests ();
int
main ()
{
-return clock_gettime ();
+return OpenSSL_add_all_digests ();
;
return 0;
}
_ACEOF
-for ac_lib in '' rt; do
+for ac_lib in '' crypto; do
if test -z "$ac_lib"; then
ac_res="none required"
else
@@ -13972,33 +13806,67 @@ for ac_lib in '' rt; do
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_clock_gettime=$ac_res
+ ac_cv_search_OpenSSL_add_all_digests=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
- if ${ac_cv_search_clock_gettime+:} false; then :
+ if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
break
fi
done
-if ${ac_cv_search_clock_gettime+:} false; then :
+if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
else
- ac_cv_search_clock_gettime=no
+ ac_cv_search_OpenSSL_add_all_digests=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
-$as_echo "$ac_cv_search_clock_gettime" >&6; }
-ac_res=$ac_cv_search_clock_gettime
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_OpenSSL_add_all_digests" >&5
+$as_echo "$ac_cv_search_OpenSSL_add_all_digests" >&6; }
+ac_res=$ac_cv_search_OpenSSL_add_all_digests
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+ with_openssl=yes
+ break
+
+else
+
+ with_openssl=no
+ # do not cache result of AC_SEARCH_LIBS test
+ unset ac_cv_search_OpenSSL_add_all_digests
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing OpenSSL_add_all_digests" >&5
-$as_echo_n "checking for library containing OpenSSL_add_all_digests... " >&6; }
-if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LIBS="$save_LIBS"
+ done
+
+ if test "$with_openssl" = "no"; then :
+
+ as_fn_error $? "libcrypto (part of OpenSSL) is required" "$LINENO" 5
+
+fi
+
+else
+ libcrypto_CFLAGS=$pkg_cv_libcrypto_CFLAGS
+ libcrypto_LIBS=$pkg_cv_libcrypto_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ CPPFLAGS="$CPPFLAGS $libcrypto_CFLAGS"
+ LIBS="$LIBS $libcrypto_LIBS"
+ with_openssl=yes
+
+fi
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pow" >&5
+$as_echo_n "checking for library containing pow... " >&6; }
+if ${ac_cv_search_pow+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
@@ -14011,16 +13879,16 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char OpenSSL_add_all_digests ();
+char pow ();
int
main ()
{
-return OpenSSL_add_all_digests ();
+return pow ();
;
return 0;
}
_ACEOF
-for ac_lib in '' crypto; do
+for ac_lib in '' m; do
if test -z "$ac_lib"; then
ac_res="none required"
else
@@ -14028,30 +13896,198 @@ for ac_lib in '' crypto; do
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_OpenSSL_add_all_digests=$ac_res
+ ac_cv_search_pow=$ac_res
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext
- if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
+ if ${ac_cv_search_pow+:} false; then :
break
fi
done
-if ${ac_cv_search_OpenSSL_add_all_digests+:} false; then :
+if ${ac_cv_search_pow+:} false; then :
else
- ac_cv_search_OpenSSL_add_all_digests=no
+ ac_cv_search_pow=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_OpenSSL_add_all_digests" >&5
-$as_echo "$ac_cv_search_OpenSSL_add_all_digests" >&6; }
-ac_res=$ac_cv_search_OpenSSL_add_all_digests
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pow" >&5
+$as_echo "$ac_cv_search_pow" >&6; }
+ac_res=$ac_cv_search_pow
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
+$as_echo_n "checking for library containing pthread_create... " >&6; }
+if ${ac_cv_search_pthread_create+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_pthread_create=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_pthread_create+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_pthread_create+:} false; then :
+
+else
+ ac_cv_search_pthread_create=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_create" >&5
+$as_echo "$ac_cv_search_pthread_create" >&6; }
+ac_res=$ac_cv_search_pthread_create
if test "$ac_res" != no; then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
else
- as_fn_error $? "libcrypto not found" "$LINENO" 5
+ as_fn_error $? "pthreads not found" "$LINENO" 5
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5
+$as_echo_n "checking for library containing dlopen... " >&6; }
+if ${ac_cv_search_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' dl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_dlopen=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_dlopen+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_dlopen+:} false; then :
+
+else
+ ac_cv_search_dlopen=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5
+$as_echo "$ac_cv_search_dlopen" >&6; }
+ac_res=$ac_cv_search_dlopen
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
+$as_echo_n "checking for library containing clock_gettime... " >&6; }
+if ${ac_cv_search_clock_gettime+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' rt; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_clock_gettime=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_clock_gettime+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_clock_gettime+:} false; then :
+
+else
+ ac_cv_search_clock_gettime=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5
+$as_echo "$ac_cv_search_clock_gettime" >&6; }
+ac_res=$ac_cv_search_clock_gettime
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing capng_apply" >&5
@@ -14166,7 +14202,6 @@ if test "$ac_res" != no; then :
fi
-#AC_SEARCH_LIBS([ldns_rr_list_pop_rrset], [ldns], [], [AC_MSG_ERROR([libldns not found])])
# Checks for header files.
for ac_header in sys/types.h netinet/in.h arpa/nameser.h netdb.h resolv.h
@@ -14195,10 +14230,14 @@ fi
done
-for ac_header in arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in_systm.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h sys/select.h sys/wait.h sys/stat.h cap-ng.h syslog.h unistd.h urcu.h ev.h pthread_np.h signal.h
+
+
+
+ for ac_header in $ac_header_list
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
@@ -14209,100 +14248,24 @@ fi
done
-# Checks for typedefs, structures, and compiler characteristics.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
-$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
-if ${ac_cv_header_stdbool_h+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
- #include <stdbool.h>
- #ifndef bool
- "error: bool is not defined"
- #endif
- #ifndef false
- "error: false is not defined"
- #endif
- #if false
- "error: false is not 0"
- #endif
- #ifndef true
- "error: true is not defined"
- #endif
- #if true != 1
- "error: true is not 1"
- #endif
- #ifndef __bool_true_false_are_defined
- "error: __bool_true_false_are_defined is not defined"
- #endif
-
- struct s { _Bool s: 1; _Bool t; } s;
-
- char a[true == 1 ? 1 : -1];
- char b[false == 0 ? 1 : -1];
- char c[__bool_true_false_are_defined == 1 ? 1 : -1];
- char d[(bool) 0.5 == true ? 1 : -1];
- /* See body of main program for 'e'. */
- char f[(_Bool) 0.0 == false ? 1 : -1];
- char g[true];
- char h[sizeof (_Bool)];
- char i[sizeof s.t];
- enum { j = false, k = true, l = false * true, m = true * 256 };
- /* The following fails for
- HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
- _Bool n[m];
- char o[sizeof n == m * sizeof n[0] ? 1 : -1];
- char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
- /* Catch a bug in an HP-UX C compiler. See
- http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
- http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
- */
- _Bool q = true;
- _Bool *pq = &q;
-int
-main ()
-{
- bool e = &s;
- *pq |= q;
- *pq |= ! q;
- /* Refer to every declared value, to avoid compiler optimizations. */
- return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
- + !m + !n + !o + !p + !q + !pq);
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdbool_h=yes
-else
- ac_cv_header_stdbool_h=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
-$as_echo "$ac_cv_header_stdbool_h" >&6; }
- ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
-if test "x$ac_cv_type__Bool" = xyes; then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE__BOOL 1
-_ACEOF
-fi
-if test $ac_cv_header_stdbool_h = yes; then
-$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
-fi
+
+
+
+
+
+# Checks for typedefs, structures, and compiler characteristics.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
$as_echo_n "checking for inline... " >&6; }
if ${ac_cv_c_inline+:} false; then :
@@ -14345,17 +14308,6 @@ _ACEOF
;;
esac
-ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t"
-case $ac_cv_c_int64_t in #(
- no|yes) ;; #(
- *)
-
-cat >>confdefs.h <<_ACEOF
-#define int64_t $ac_cv_c_int64_t
-_ACEOF
-;;
-esac
-
ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
if test "x$ac_cv_type_pid_t" = xyes; then :
@@ -14389,60 +14341,6 @@ _ACEOF
fi
-ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
-case $ac_cv_c_uint16_t in #(
- no|yes) ;; #(
- *)
-
-
-cat >>confdefs.h <<_ACEOF
-#define uint16_t $ac_cv_c_uint16_t
-_ACEOF
-;;
- esac
-
-ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
-case $ac_cv_c_uint32_t in #(
- no|yes) ;; #(
- *)
-
-$as_echo "#define _UINT32_T 1" >>confdefs.h
-
-
-cat >>confdefs.h <<_ACEOF
-#define uint32_t $ac_cv_c_uint32_t
-_ACEOF
-;;
- esac
-
-ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t"
-case $ac_cv_c_uint64_t in #(
- no|yes) ;; #(
- *)
-
-$as_echo "#define _UINT64_T 1" >>confdefs.h
-
-
-cat >>confdefs.h <<_ACEOF
-#define uint64_t $ac_cv_c_uint64_t
-_ACEOF
-;;
- esac
-
-ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t"
-case $ac_cv_c_uint8_t in #(
- no|yes) ;; #(
- *)
-
-$as_echo "#define _UINT8_T 1" >>confdefs.h
-
-
-cat >>confdefs.h <<_ACEOF
-#define uint8_t $ac_cv_c_uint8_t
-_ACEOF
-;;
- esac
-
# Set PRNG parameters
@@ -14450,421 +14348,7 @@ $as_echo "#define DSFMT_MEXP 521" >>confdefs.h
# Checks for library functions.
-for ac_header in vfork.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
-if test "x$ac_cv_header_vfork_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_VFORK_H 1
-_ACEOF
-
-fi
-
-done
-
-for ac_func in fork vfork
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-done
-
-if test "x$ac_cv_func_fork" = xyes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
-$as_echo_n "checking for working fork... " >&6; }
-if ${ac_cv_func_fork_works+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
- ac_cv_func_fork_works=cross
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$ac_includes_default
-int
-main ()
-{
-
- /* By Ruediger Kuhlmann. */
- return fork () < 0;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- ac_cv_func_fork_works=yes
-else
- ac_cv_func_fork_works=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
-$as_echo "$ac_cv_func_fork_works" >&6; }
-
-else
- ac_cv_func_fork_works=$ac_cv_func_fork
-fi
-if test "x$ac_cv_func_fork_works" = xcross; then
- case $host in
- *-*-amigaos* | *-*-msdosdjgpp*)
- # Override, as these systems have only a dummy fork() stub
- ac_cv_func_fork_works=no
- ;;
- *)
- ac_cv_func_fork_works=yes
- ;;
- esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
-fi
-ac_cv_func_vfork_works=$ac_cv_func_vfork
-if test "x$ac_cv_func_vfork" = xyes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
-$as_echo_n "checking for working vfork... " >&6; }
-if ${ac_cv_func_vfork_works+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
- ac_cv_func_vfork_works=cross
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-/* Thanks to Paul Eggert for this test. */
-$ac_includes_default
-#include <sys/wait.h>
-#ifdef HAVE_VFORK_H
-# include <vfork.h>
-#endif
-/* On some sparc systems, changes by the child to local and incoming
- argument registers are propagated back to the parent. The compiler
- is told about this with #include <vfork.h>, but some compilers
- (e.g. gcc -O) don't grok <vfork.h>. Test for this by using a
- static variable whose address is put into a register that is
- clobbered by the vfork. */
-static void
-#ifdef __cplusplus
-sparc_address_test (int arg)
-# else
-sparc_address_test (arg) int arg;
-#endif
-{
- static pid_t child;
- if (!child) {
- child = vfork ();
- if (child < 0) {
- perror ("vfork");
- _exit(2);
- }
- if (!child) {
- arg = getpid();
- write(-1, "", 0);
- _exit (arg);
- }
- }
-}
-
-int
-main ()
-{
- pid_t parent = getpid ();
- pid_t child;
-
- sparc_address_test (0);
-
- child = vfork ();
-
- if (child == 0) {
- /* Here is another test for sparc vfork register problems. This
- test uses lots of local variables, at least as many local
- variables as main has allocated so far including compiler
- temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris
- 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should
- reuse the register of parent for one of the local variables,
- since it will think that parent can't possibly be used any more
- in this routine. Assigning to the local variable will thus
- munge parent in the parent process. */
- pid_t
- p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
- p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
- /* Convince the compiler that p..p7 are live; otherwise, it might
- use the same hardware register for all 8 local variables. */
- if (p != p1 || p != p2 || p != p3 || p != p4
- || p != p5 || p != p6 || p != p7)
- _exit(1);
-
- /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
- from child file descriptors. If the child closes a descriptor
- before it execs or exits, this munges the parent's descriptor
- as well. Test for this by closing stdout in the child. */
- _exit(close(fileno(stdout)) != 0);
- } else {
- int status;
- struct stat st;
-
- while (wait(&status) != child)
- ;
- return (
- /* Was there some problem with vforking? */
- child < 0
-
- /* Did the child fail? (This shouldn't happen.) */
- || status
-
- /* Did the vfork/compiler bug occur? */
- || parent != getpid()
-
- /* Did the file descriptor bug occur? */
- || fstat(fileno(stdout), &st) != 0
- );
- }
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- ac_cv_func_vfork_works=yes
-else
- ac_cv_func_vfork_works=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
-$as_echo "$ac_cv_func_vfork_works" >&6; }
-
-fi;
-if test "x$ac_cv_func_fork_works" = xcross; then
- ac_cv_func_vfork_works=$ac_cv_func_vfork
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
-$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
-fi
-
-if test "x$ac_cv_func_vfork_works" = xyes; then
-
-$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
-
-else
-
-$as_echo "#define vfork fork" >>confdefs.h
-
-fi
-if test "x$ac_cv_func_fork_works" = xyes; then
-
-$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
-
-fi
-
-
-
-
- for ac_header in $ac_header_list
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
-"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
-
-
-
-
-
-
-
-for ac_func in getpagesize
-do :
- ac_fn_c_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize"
-if test "x$ac_cv_func_getpagesize" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_GETPAGESIZE 1
-_ACEOF
-
-fi
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5
-$as_echo_n "checking for working mmap... " >&6; }
-if ${ac_cv_func_mmap_fixed_mapped+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test "$cross_compiling" = yes; then :
- ac_cv_func_mmap_fixed_mapped=no
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$ac_includes_default
-/* malloc might have been renamed as rpl_malloc. */
-#undef malloc
-
-/* Thanks to Mike Haertel and Jim Avera for this test.
- Here is a matrix of mmap possibilities:
- mmap private not fixed
- mmap private fixed at somewhere currently unmapped
- mmap private fixed at somewhere already mapped
- mmap shared not fixed
- mmap shared fixed at somewhere currently unmapped
- mmap shared fixed at somewhere already mapped
- For private mappings, we should verify that changes cannot be read()
- back from the file, nor mmap's back from the file at a different
- address. (There have been systems where private was not correctly
- implemented like the infamous i386 svr4.0, and systems where the
- VM page cache was not coherent with the file system buffer cache
- like early versions of FreeBSD and possibly contemporary NetBSD.)
- For shared mappings, we should conversely verify that changes get
- propagated back to all the places they're supposed to be.
-
- Grep wants private fixed already mapped.
- The main things grep needs to know about mmap are:
- * does it exist and is it safe to write into the mmap'd area
- * how to use it (BSD variants) */
-
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H
-char *malloc ();
-#endif
-
-/* This mess was copied from the GNU getpagesize.h. */
-#ifndef HAVE_GETPAGESIZE
-# ifdef _SC_PAGESIZE
-# define getpagesize() sysconf(_SC_PAGESIZE)
-# else /* no _SC_PAGESIZE */
-# ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# ifdef EXEC_PAGESIZE
-# define getpagesize() EXEC_PAGESIZE
-# else /* no EXEC_PAGESIZE */
-# ifdef NBPG
-# define getpagesize() NBPG * CLSIZE
-# ifndef CLSIZE
-# define CLSIZE 1
-# endif /* no CLSIZE */
-# else /* no NBPG */
-# ifdef NBPC
-# define getpagesize() NBPC
-# else /* no NBPC */
-# ifdef PAGESIZE
-# define getpagesize() PAGESIZE
-# endif /* PAGESIZE */
-# endif /* no NBPC */
-# endif /* no NBPG */
-# endif /* no EXEC_PAGESIZE */
-# else /* no HAVE_SYS_PARAM_H */
-# define getpagesize() 8192 /* punt totally */
-# endif /* no HAVE_SYS_PARAM_H */
-# endif /* no _SC_PAGESIZE */
-
-#endif /* no HAVE_GETPAGESIZE */
-
-int
-main ()
-{
- char *data, *data2, *data3;
- const char *cdata2;
- int i, pagesize;
- int fd, fd2;
-
- pagesize = getpagesize ();
-
- /* First, make a file with some known garbage in it. */
- data = (char *) malloc (pagesize);
- if (!data)
- return 1;
- for (i = 0; i < pagesize; ++i)
- *(data + i) = rand ();
- umask (0);
- fd = creat ("conftest.mmap", 0600);
- if (fd < 0)
- return 2;
- if (write (fd, data, pagesize) != pagesize)
- return 3;
- close (fd);
-
- /* Next, check that the tail of a page is zero-filled. File must have
- non-zero length, otherwise we risk SIGBUS for entire page. */
- fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600);
- if (fd2 < 0)
- return 4;
- cdata2 = "";
- if (write (fd2, cdata2, 1) != 1)
- return 5;
- data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L);
- if (data2 == MAP_FAILED)
- return 6;
- for (i = 0; i < pagesize; ++i)
- if (*(data2 + i))
- return 7;
- close (fd2);
- if (munmap (data2, pagesize))
- return 8;
-
- /* Next, try to mmap the file at a fixed address which already has
- something else allocated at it. If we can, also make sure that
- we see the same garbage. */
- fd = open ("conftest.mmap", O_RDWR);
- if (fd < 0)
- return 9;
- if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_FIXED, fd, 0L))
- return 10;
- for (i = 0; i < pagesize; ++i)
- if (*(data + i) != *(data2 + i))
- return 11;
-
- /* Finally, make sure that changes to the mapped area do not
- percolate back to the file as seen by read(). (This is a bug on
- some variants of i386 svr4.0.) */
- for (i = 0; i < pagesize; ++i)
- *(data2 + i) = *(data2 + i) + 1;
- data3 = (char *) malloc (pagesize);
- if (!data3)
- return 12;
- if (read (fd, data3, pagesize) != pagesize)
- return 13;
- for (i = 0; i < pagesize; ++i)
- if (*(data + i) != *(data3 + i))
- return 14;
- close (fd);
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
- ac_cv_func_mmap_fixed_mapped=yes
-else
- ac_cv_func_mmap_fixed_mapped=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5
-$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; }
-if test $ac_cv_func_mmap_fixed_mapped = yes; then
-
-$as_echo "#define HAVE_MMAP 1" >>confdefs.h
-
-fi
-rm -f conftest.mmap conftest.txt
-
-for ac_func in gethostbyname gettimeofday clock_gettime memalign memmove memset munmap regcomp pselect select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue setgroups sendmmsg madvise pthread_setaffinity_np
+for ac_func in clock_gettime gettimeofday epoll_wait fgetln getline kqueue madvise poll posix_memalign pselect pthread_setaffinity_np regcomp select sendmmsg setgroups
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -14933,7 +14417,60 @@ fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
-ac_config_files="$ac_config_files Makefile samples/Makefile src/Makefile doc/Makefile"
+
+
+ CFLAG_VISIBILITY=
+ HAVE_VISIBILITY=0
+ if test -n "$GCC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for simple visibility declarations" >&5
+$as_echo_n "checking for simple visibility declarations... " >&6; }
+ if ${gl_cv_cc_visibility+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ gl_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+extern __attribute__((__visibility__("hidden"))) int hiddenvar;
+ extern __attribute__((__visibility__("default"))) int exportedvar;
+ extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
+ extern __attribute__((__visibility__("default"))) int exportedfunc (void);
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gl_cv_cc_visibility=yes
+else
+ gl_cv_cc_visibility=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$gl_save_CFLAGS"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gl_cv_cc_visibility" >&5
+$as_echo "$gl_cv_cc_visibility" >&6; }
+ if test $gl_cv_cc_visibility = yes; then
+ CFLAG_VISIBILITY="-fvisibility=hidden"
+ HAVE_VISIBILITY=1
+ fi
+ fi
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_VISIBILITY $HAVE_VISIBILITY
+_ACEOF
+
+
+CFLAGS="$CFLAGS $CFLAG_VISIBILITY"
+
+ac_config_files="$ac_config_files Makefile samples/Makefile src/Makefile src/tests/Makefile doc/Makefile man/Makefile src/zscanner/test/run_tests.sh src/zscanner/test/cases/06-3_INCLUDE.in:src/zscanner/test/cases/06-3_INCLUDE.inin src/zscanner/test/cases/06-4_INCLUDE.in:src/zscanner/test/cases/06-4_INCLUDE.inin src/zscanner/test/cases/06-0_INCLUDE.in:src/zscanner/test/cases/06-0_INCLUDE.inin man/khost.1 man/knotc.8 man/knotd.8 man/kdig.1 man/knsupdate.1 man/knot.conf.5"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -15044,14 +14581,6 @@ LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
-$as_echo_n "checking that generated files are newer than configure... " >&6; }
- if test -n "$am_sleep_pid"; then
- # Hide warnings about reused PIDs.
- wait $am_sleep_pid 2>/dev/null
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
-$as_echo "done" >&6; }
if test -n "$EXEEXT"; then
am__EXEEXT_TRUE=
am__EXEEXT_FALSE='#'
@@ -15068,8 +14597,8 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
-if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
- as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+if test -z "${HAVE_RAGEL_TRUE}" && test -z "${HAVE_RAGEL_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_RAGEL\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
@@ -15469,7 +14998,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by knot $as_me 1.2.0, which was
+This file was extended by knot $as_me 1.3.0-rc3, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15535,7 +15064,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-knot config.status 1.2.0
+knot config.status 1.3.0-rc3
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -15664,10 +15193,10 @@ AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
sed_quote_subst='$sed_quote_subst'
double_quote_subst='$double_quote_subst'
delay_variable_subst='$delay_variable_subst'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
-enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
@@ -15947,7 +15476,19 @@ do
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"samples/Makefile") CONFIG_FILES="$CONFIG_FILES samples/Makefile" ;;
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+ "src/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/tests/Makefile" ;;
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+ "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile" ;;
+ "src/zscanner/test/run_tests.sh") CONFIG_FILES="$CONFIG_FILES src/zscanner/test/run_tests.sh" ;;
+ "src/zscanner/test/cases/06-3_INCLUDE.in") CONFIG_FILES="$CONFIG_FILES src/zscanner/test/cases/06-3_INCLUDE.in:src/zscanner/test/cases/06-3_INCLUDE.inin" ;;
+ "src/zscanner/test/cases/06-4_INCLUDE.in") CONFIG_FILES="$CONFIG_FILES src/zscanner/test/cases/06-4_INCLUDE.in:src/zscanner/test/cases/06-4_INCLUDE.inin" ;;
+ "src/zscanner/test/cases/06-0_INCLUDE.in") CONFIG_FILES="$CONFIG_FILES src/zscanner/test/cases/06-0_INCLUDE.in:src/zscanner/test/cases/06-0_INCLUDE.inin" ;;
+ "man/khost.1") CONFIG_FILES="$CONFIG_FILES man/khost.1" ;;
+ "man/knotc.8") CONFIG_FILES="$CONFIG_FILES man/knotc.8" ;;
+ "man/knotd.8") CONFIG_FILES="$CONFIG_FILES man/knotd.8" ;;
+ "man/kdig.1") CONFIG_FILES="$CONFIG_FILES man/kdig.1" ;;
+ "man/knsupdate.1") CONFIG_FILES="$CONFIG_FILES man/knsupdate.1" ;;
+ "man/knot.conf.5") CONFIG_FILES="$CONFIG_FILES man/knot.conf.5" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
@@ -16557,7 +16098,7 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
- # We used to match only the files named 'Makefile.in', but
+ # We used to match only the files named `Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
@@ -16591,19 +16132,21 @@ $as_echo X"$mf" |
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
- # from the Makefile without running 'make'.
+ # from the Makefile without running `make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+ # When using ansi2knr, U may be empty or an underscore; expand it
+ U=`sed -n 's/^U = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`$as_dirname -- "$file" ||
@@ -16690,6 +16233,9 @@ available_tags=""
# ### BEGIN LIBTOOL CONFIG
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
# Which release of libtool.m4 was used?
macro_version=$macro_version
macro_revision=$macro_revision
@@ -16697,9 +16243,6 @@ macro_revision=$macro_revision
# Whether or not to build shared libraries.
build_libtool_libs=$enable_shared
-# Whether or not to build static libraries.
-build_old_libs=$enable_static
-
# What type of objects to build.
pic_mode=$pic_mode
diff --git a/configure.ac b/configure.ac
index ee1d73c..2bc79f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,23 +1,34 @@
# -*- Autoconf -*-
AC_PREREQ([2.60])
-AC_INIT([knot], [1.2.0], [knot-dns@labs.nic.cz])
-AM_INIT_AUTOMAKE([gnu -Wall -Werror])
+AC_INIT([knot], [1.3.0-rc3], [knot-dns@labs.nic.cz])
+AM_INIT_AUTOMAKE([gnits subdir-objects dist-bzip2 dist-xz -Wall -Werror])
+AM_SILENT_RULES([yes])
AC_CONFIG_SRCDIR([src/knot/main.c])
AC_CONFIG_HEADERS([src/config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_USE_SYSTEM_EXTENSIONS([_GNU_SOURCE])
+
+# Check SSE, SSE2 and SSE3 support
AX_EXT
+CFLAGS="$CFLAGS $SIMD_FLAGS"
+
+# Set compiler compatibility flags
+AC_PROG_CC_C99
+AM_PROG_CC_C_O
+AC_PROG_CPP_WERROR
# Checks for programs.
-AC_PROG_CC
-m4_pattern_allow([AM_PROG_AR]) # for automake 1.12
-AM_PROG_AR
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) # call AM_PROG_AR only if available
# Initialize libtool
+AC_DISABLE_STATIC
AC_PROG_LIBTOOL
LT_INIT
+# Use pkg-config
+PKG_PROG_PKG_CONFIG
+
AC_CACHE_CHECK([for reentrant lex], [ac_cv_path_LEX],
[AC_PATH_PROGS_FEATURE_CHECK([LEX], [$LEX flex gflex],
[cat >conftest.l <<_ACEOF
@@ -46,23 +57,21 @@ AM_PROG_LEX
AC_PROG_YACC
YACC_BISON=`bison --version | awk '{print $1;exit}'`
-AS_IF([test "x$YACC_BISON" != "xbison"],
+AS_IF([test "x$YACC_BISON" != "xbison"],
[AC_MSG_ERROR([GNU bison needed for reentrant parsers, set the \$YACC variable before running configure])])
AC_PROG_INSTALL
-# Set compiler compatibility flags
-AC_PROG_CPP_WERROR
-AC_PROG_CC_C99
+# Check for Ragel
+AC_PATH_PROG([RAGEL], [ragel], [true])
+AM_CONDITIONAL([HAVE_RAGEL], test "$RAGEL" != "true")
+
+# Set FSM type for Ragel
+AC_SUBST([FSM_TYPE], [-T0])
+AC_ARG_ENABLE([fastparser],
+ AS_HELP_STRING([--enable-fastparser], [Generate fast zone parser (requires Ragel!)]),
+ [touch src/zscanner/scanner.rl; AC_SUBST([FSM_TYPE], [-G2])],
+ [])
-AC_ARG_ENABLE([ldns],
- AS_HELP_STRING([--enable-ldns=yes|no], [Enable tests with ldns [default=no]]),
- [case "${enableval}" in
- yes) AC_SEARCH_LIBS([ldns_rr_list_pop_rrset], [ldns], [AC_DEFINE([HAVE_LDNS], [1], [ldns present])],
- AC_MSG_ERROR([ldns not found])) ;;
- no) ldns=false ;;
- *) AC_MSG_ERROR([bad value ${enableval} for --enable-ldns]) ;;
- esac],[ldns=false])
-
# Debug modules
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--enable-debug=server,zones,xfr,packet,dname,rr,ns,hash,compiler,stash],
@@ -93,16 +102,16 @@ AC_ARG_ENABLE([debuglevel],
AC_DEFINE([DEBUG_ENABLE_DETAILS], [1], [Enable details debugging messages.])
AC_DEFINE([DEBUG_ENABLE_VERBOSE], [1], [Enable verbose debugging messages.])
AC_DEFINE([DEBUG_ENABLE_BRIEF], [1], [Enable brief debugging messages.])
- ;;
+ ;;
xverbose)
AC_DEFINE([DEBUG_ENABLE_VERBOSE], [1], [Enable verbose debugging messages.])
AC_DEFINE([DEBUG_ENABLE_BRIEF], [1], [Enable brief debugging messages.])
- ;;
+ ;;
xbrief)
AC_DEFINE([DEBUG_ENABLE_BRIEF], [1], [Enable brief debugging messages.])
;;
esac], [])
-
+
AX_MSG_WAITFORONE
# recvmmsg() (valgrind doesn't support it, so disable for debugging)
AC_ARG_ENABLE([recvmmsg],
@@ -119,7 +128,7 @@ AC_ARG_ENABLE([recvmmsg],
no)
recvmmsg=false
;;
- *)
+ *)
AC_MSG_ERROR([bad value ${enableval} for --enable-recvmmsg])
;;
esac], [
@@ -135,52 +144,150 @@ AC_ARG_ENABLE([recvmmsg],
AC_ARG_ENABLE([lto],
AS_HELP_STRING([--enable-lto=yes|no], [enable link-time optimizations, enable if not broken for some extra speed [default=no]]),
[case "${enableval}" in
- yes) AX_CHECK_COMPILER_FLAGS("-flto", [CFLAGS="$CFLAGS -flto"], []) ;;
+ yes) AX_CHECK_COMPILE_FLAG("-flto", [CFLAGS="$CFLAGS -flto"], []) ;;
no) ;;
*) AC_MSG_ERROR([bad value ${enableval} for --enable-lto]) ;;
esac])
-AX_CHECK_COMPILER_FLAGS("-fpredictive-commoning", [CFLAGS="$CFLAGS -fpredictive-commoning"], [])
+# Check for enable microseconds in log messages
+AC_ARG_ENABLE([microseconds-log],
+ AS_HELP_STRING([--enable-microseconds-log], [enable microseconds in log messages [default=no]]),
+ AC_DEFINE([ENABLE_MICROSECONDS_LOG], [1], [microseconds in log messages]))
+
+AX_CHECK_COMPILE_FLAG("-fpredictive-commoning", [CFLAGS="$CFLAGS -fpredictive-commoning"], [], "-Werror")
+
+# Disable strict aliasing
+# FIXME: we break strict aliasing on many occurenes, disable it until resolved or kept
+AX_CHECK_COMPILE_FLAG("-fno-strict-aliasing", [CFLAGS="$CFLAGS -fno-strict-aliasing"], [])
+
+# Default directories
+run_dir="${localstatedir}/run/knot"
+AC_ARG_WITH([rundir],
+ AC_HELP_STRING([--with-rundir=path], [Path to run-time variable data (pid, sockets...). [default=`eval echo ${localstatedir}`/run/knot]]),
+ [run_dir=$withval])
+AC_SUBST(run_dir)
+
+storage_dir="${sharedstatedir}/knot"
+AC_ARG_WITH([storage],
+ AC_HELP_STRING([--with-storage=path], [Default storage directory (slave zones, persistent data). [default=$(sharedstatedir)/knot]]),
+ [storage_dir=$withval])
+AC_SUBST(storage_dir)
# Checks for libraries.
# FIXME: Replace `main' with a function in `-lm':
-# TODO: check if paths exist before appending
-CFLAGS="$CFLAGS -I/usr/local/include $SIMD_FLAGS"
-LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+dnl Check for userspace-rcu library
+AC_ARG_WITH(urcu,
+[ --with-urcu=DIR where to find userspace-rcu library])
+
+AS_IF([test "$with_urcu" != "no"], [
+ PKG_CHECK_MODULES([liburcu], liburcu, [
+ CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS"
+ LIBS="$LIBS $liburcu_LIBS"
+ with_urcu=yes
+ ],[
+ for try_urcu in "$with_urcu" "" "/usr/local"; do
+ save_LIBS="$LIBS"
+ save_CPPFLAGS="$CPPFLAGS"
+
+ AS_IF([test -d "$try_urcu"], [
+ liburcu_CFLAGS="-I$try_urcu/include"
+ liburcu_LIBS="-L$try_urcu/lib"
+ ],[
+ liburcu_CFLAGS=""
+ liburcu_LIBS=""
+ ])
+
+ CPPFLAGS="$CPPFLAGS $liburcu_CFLAGS"
+ LIBS="$LIBS $liburcu_LIBS"
+
+ AC_SEARCH_LIBS([rcu_set_pointer_sym], [urcu], [
+ with_urcu=yes
+ break
+ ],[
+ CPPFLAGS="$save_CPPFLAGS"
+ LIBS="$save_LIBS"
+ with_urcu=no
+ # do not cache result of AC_SEARCH_LIBS test
+ unset ac_cv_search_rcu_set_pointer_sym
+ ])
+ done
+
+ AS_IF([test "$with_urcu" = "no"],[
+ AC_MSG_ERROR([liburcu is required])
+ ])
+ ])
+])
+
+AC_SEARCH_LIBS([urcu_init], [urcu], [AC_MSG_ERROR([liburcu is too old (< 0.4.0), urcu_init symbol found])], [])
+
+dnl Check for OpenSSL
+AC_ARG_WITH(openssl,
+[ --with-openssl=DIR where to find openssl library])
+
+AS_IF([test "$with_openssl" != "no"],[
+ PKG_CHECK_MODULES([libcrypto], libcrypto, [
+ CPPFLAGS="$CPPFLAGS $libcrypto_CFLAGS"
+ LIBS="$LIBS $libcrypto_LIBS"
+ with_openssl=yes
+ ],[
+
+ for try_openssl in "$with_openssl" "" "/usr/local"; do
+ save_LIBS="$LIBS"
+ save_CPPFLAGS="$CPPFLAGS"
+
+ AS_IF([test -d "$try_openssl"], [
+ libcrypto_CFLAGS="-I$try_openssl/include"
+ libcrypto_LIBS="-L$try_openssl/lib"
+ ],[
+ libcrypto_CFLAGS=""
+ libcrypto_LIBS=""
+ ])
+
+ CPPFLAGS="$CPPFLAGS $libcrypto_CFLAGS"
+ LIBS="$LIBS $libcrypto_LIBS"
+
+ AC_SEARCH_LIBS([OpenSSL_add_all_digests], [crypto], [
+ with_openssl=yes
+ break
+ ],[
+ with_openssl=no
+ # do not cache result of AC_SEARCH_LIBS test
+ unset ac_cv_search_OpenSSL_add_all_digests
+ ])
+
+ CPPFLAGS="$save_CPPFLAGS"
+ LIBS="$save_LIBS"
+ done
+
+ AS_IF([test "$with_openssl" = "no"],[
+ AC_MSG_ERROR([libcrypto (part of OpenSSL) is required])
+ ])
+ ])
+])
+
AC_SEARCH_LIBS([pow], [m])
AC_SEARCH_LIBS([pthread_create], [pthread], [], [AC_MSG_ERROR([pthreads not found])])
-AC_SEARCH_LIBS([rcu_set_pointer_sym], [urcu], [], [AC_MSG_ERROR([liburcu not found])])
-AC_SEARCH_LIBS([urcu_init], [urcu], [AC_MSG_ERROR([liburcu is too old (< 0.4.0), urcu_init symbol found])], [])
AC_SEARCH_LIBS([dlopen], [dl])
AC_SEARCH_LIBS([clock_gettime], [rt])
-AC_SEARCH_LIBS([OpenSSL_add_all_digests], [crypto],[], [AC_MSG_ERROR([libcrypto not found])])
AC_SEARCH_LIBS([capng_apply], [cap-ng])
AC_SEARCH_LIBS([adler32], [z])
-#AC_SEARCH_LIBS([ldns_rr_list_pop_rrset], [ldns], [], [AC_MSG_ERROR([libldns not found])])
# Checks for header files.
AC_HEADER_RESOLV
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in_systm.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h sys/select.h sys/wait.h sys/stat.h cap-ng.h syslog.h unistd.h urcu.h ev.h pthread_np.h signal.h])
+AC_CHECK_HEADERS_ONCE([cap-ng.h netinet/in_systm.h pthread_np.h signal.h sys/select.h sys/time.h sys/wait.h sys/uio.h])
# Checks for typedefs, structures, and compiler characteristics.
-AC_HEADER_STDBOOL
AC_C_INLINE
-AC_TYPE_INT64_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
-AC_TYPE_UINT16_T
-AC_TYPE_UINT32_T
-AC_TYPE_UINT64_T
-AC_TYPE_UINT8_T
# Set PRNG parameters
-AC_DEFINE([DSFMT_MEXP], [521], [DSFMT parameters.])
+AC_DEFINE([DSFMT_MEXP], [521], [DSFMT parameters])
# Checks for library functions.
-AC_FUNC_FORK
-AC_FUNC_MMAP
-AC_CHECK_FUNCS([gethostbyname gettimeofday clock_gettime memalign memmove memset munmap regcomp pselect select socket sqrt strcasecmp strchr strdup strerror strncasecmp strtol strtoul poll epoll_wait kqueue setgroups sendmmsg madvise pthread_setaffinity_np])
+AC_CHECK_FUNCS([clock_gettime gettimeofday epoll_wait fgetln getline kqueue madvise poll posix_memalign pselect pthread_setaffinity_np regcomp select sendmmsg setgroups])
# Check for cpu_set_t/cpuset_t compatibility
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], [[cpu_set_t set; CPU_ZERO(&set);]])],
@@ -190,8 +297,24 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread_np.h>]], [[cpuset_t set; CPU
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <sched.h>]], [[cpuset_t* set = cpuset_create(); cpuset_destroy(set);]])],
[AC_DEFINE(HAVE_CPUSET_NETBSD, 1, [Define if cpuset_t and cpuset(3) exists.])])
+gl_VISIBILITY()
+CFLAGS="$CFLAGS $CFLAG_VISIBILITY"
+
AC_CONFIG_FILES([Makefile
samples/Makefile
- src/Makefile
- doc/Makefile])
+ src/Makefile
+ src/tests/Makefile
+ doc/Makefile
+ man/Makefile
+ src/zscanner/test/run_tests.sh
+ src/zscanner/test/cases/06-3_INCLUDE.in:src/zscanner/test/cases/06-3_INCLUDE.inin
+ src/zscanner/test/cases/06-4_INCLUDE.in:src/zscanner/test/cases/06-4_INCLUDE.inin
+ src/zscanner/test/cases/06-0_INCLUDE.in:src/zscanner/test/cases/06-0_INCLUDE.inin
+ man/khost.1
+ man/knotc.8
+ man/knotd.8
+ man/kdig.1
+ man/knsupdate.1
+ man/knot.conf.5
+ ])
AC_OUTPUT
diff --git a/depcomp b/depcomp
index e1f51f4..25a39e6 100755
--- a/depcomp
+++ b/depcomp
@@ -1,9 +1,10 @@
#! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
-scriptversion=2012-07-12.20; # UTC
+scriptversion=2012-03-27.16; # UTC
-# Copyright (C) 1999-2012 Free Software Foundation, Inc.
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
+# 2011, 2012 Free Software Foundation, Inc.
# 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
@@ -74,9 +75,6 @@ tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
-# Avoid interferences from the environment.
-gccflag= dashmflag=
-
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
@@ -111,7 +109,7 @@ if test "$depmode" = msvc7msys; then
fi
if test "$depmode" = xlc; then
- # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+ # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
@@ -145,17 +143,13 @@ gcc3)
;;
gcc)
-## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
-## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
-## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
-## -MM, not -M (despite what the docs say). Also, it might not be
-## supported by the other compilers which use the 'gcc' depmode.
+## -MM, not -M (despite what the docs say).
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
@@ -341,79 +335,6 @@ icc)
rm -f "$tmpdepfile"
;;
-## The order of this option in the case statement is important, since the
-## shell code in configure will try each of these formats in the order
-## listed in this file. A plain '-MD' option would be understood by many
-## compilers, so we must ensure this comes after the gcc and icc options.
-pgcc)
- # Portland's C compiler understands '-MD'.
- # Will always output deps to 'file.d' where file is the root name of the
- # source file under compilation, even if file resides in a subdirectory.
- # The object file name does not affect the name of the '.d' file.
- # pgcc 10.2 will output
- # foo.o: sub/foo.c sub/foo.h
- # and will wrap long lines using '\' :
- # foo.o: sub/foo.c ... \
- # sub/foo.h ... \
- # ...
- dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
- test "x$dir" = "x$object" && dir=
- # Use the source, not the object, to determine the base name, since
- # that's sadly what pgcc will do too.
- base=`echo "$source" | sed -e 's|^.*/||' -e 's/\.[-_a-zA-Z0-9]*$//'`
- tmpdepfile="$base.d"
-
- # For projects that build the same source file twice into different object
- # files, the pgcc approach of using the *source* file root name can cause
- # problems in parallel builds. Use a locking strategy to avoid stomping on
- # the same $tmpdepfile.
- lockdir="$base.d-lock"
- trap "echo '$0: caught signal, cleaning up...' >&2; rm -rf $lockdir" 1 2 13 15
- numtries=100
- i=$numtries
- while test $i -gt 0 ; do
- # mkdir is a portable test-and-set.
- if mkdir $lockdir 2>/dev/null; then
- # This process acquired the lock.
- "$@" -MD
- stat=$?
- # Release the lock.
- rm -rf $lockdir
- break
- else
- ## the lock is being held by a different process,
- ## wait until the winning process is done or we timeout
- while test -d $lockdir && test $i -gt 0; do
- sleep 1
- i=`expr $i - 1`
- done
- fi
- i=`expr $i - 1`
- done
- trap - 1 2 13 15
- if test $i -le 0; then
- echo "$0: failed to acquire lock after $numtries attempts" >&2
- echo "$0: check lockdir '$lockdir'" >&2
- exit 1
- fi
-
- if test $stat -ne 0; then
- rm -f "$tmpdepfile"
- exit $stat
- fi
- rm -f "$depfile"
- # Each line is of the form `foo.o: dependent.h',
- # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
- # Do two passes, one to just change these to
- # `$object: dependent.h' and one to simply `dependent.h:'.
- sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
- # Some versions of the HPUX 10.20 sed can't process this invocation
- # correctly. Breaking it into two sed invocations is a workaround.
- sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
- sed -e 's/$/ :/' >> "$depfile"
- rm -f "$tmpdepfile"
- ;;
-
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
diff --git a/doc/.gitignore b/doc/.gitignore
deleted file mode 100644
index b9dc5b2..0000000
--- a/doc/.gitignore
+++ /dev/null
@@ -1,17 +0,0 @@
-*.info
-*.pdf
-*.html
-*.dvi
-*.aux
-*.cp
-*.fn
-*.ky
-*.log
-*.pg
-*.toc
-*.tp
-*.vr
-texinfo.tex
-version.texi
-mdate-sh
-stamp-vti
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 9cec847..77b3d0a 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,10 +1,14 @@
info_TEXINFOS = knot.texi
-knot_TEXINFOS = \
- introduction.texi \
- requirements.texi \
- installation.texi \
- configuration.texi \
- reference.texi \
- security.texi \
- troubleshooting.texi \
- migration.texi
+knot_TEXINFOS = \
+ configuration.texi \
+ indices.texi \
+ installation.texi \
+ introduction.texi \
+ knot.texi \
+ migration.texi \
+ reference.texi \
+ requirements.texi \
+ running.texi \
+ security.texi \
+ troubleshooting.texi \
+ version.texi
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 3d391d2..5e6bfe5 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.12.6 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
-
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -54,19 +55,25 @@ DIST_COMMON = $(knot_TEXINFOS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/stamp-vti \
$(srcdir)/version.texi mdate-sh texinfo.tex
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compiler_flags.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_ext.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_recvmmsg.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/src/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
SOURCES =
DIST_SOURCES =
INFO_DEPS = $(srcdir)/knot.info
@@ -117,6 +124,7 @@ am__uninstall_files_from_dir = { \
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -125,6 +133,7 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -139,7 +148,9 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+FSM_TYPE = @FSM_TYPE@
GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -173,6 +184,10 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RAGEL = @RAGEL@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -215,8 +230,12 @@ htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
+libcrypto_CFLAGS = @libcrypto_CFLAGS@
+libcrypto_LIBS = @libcrypto_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+liburcu_CFLAGS = @liburcu_CFLAGS@
+liburcu_LIBS = @liburcu_LIBS@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
@@ -226,9 +245,11 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+run_dir = @run_dir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
+storage_dir = @storage_dir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
@@ -236,14 +257,18 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
info_TEXINFOS = knot.texi
knot_TEXINFOS = \
- introduction.texi \
- requirements.texi \
- installation.texi \
- configuration.texi \
- reference.texi \
- security.texi \
- troubleshooting.texi \
- migration.texi
+ configuration.texi \
+ indices.texi \
+ installation.texi \
+ introduction.texi \
+ knot.texi \
+ migration.texi \
+ reference.texi \
+ requirements.texi \
+ running.texi \
+ security.texi \
+ troubleshooting.texi \
+ version.texi
all: all-am
@@ -258,9 +283,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits doc/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu doc/Makefile
+ $(AUTOMAKE) --gnits doc/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -311,12 +336,12 @@ clean-libtool:
.texi.dvi:
TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
- $(TEXI2DVI) --clean $<
+ $(TEXI2DVI) $<
.texi.pdf:
TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \
- $(TEXI2PDF) --clean $<
+ $(TEXI2PDF) $<
.texi.html:
rm -rf $(@:.html=.htp)
@@ -356,7 +381,7 @@ maintainer-clean-vti:
-rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi
.dvi.ps:
TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
- $(DVIPS) -o $@ $<
+ $(DVIPS) -o $@ $<
uninstall-dvi-am:
@$(NORMAL_UNINSTALL)
@@ -455,8 +480,6 @@ TAGS:
ctags: CTAGS
CTAGS:
-cscope cscopelist:
-
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
diff --git a/doc/configuration.texi b/doc/configuration.texi
index b979c38..1f1a5ca 100644
--- a/doc/configuration.texi
+++ b/doc/configuration.texi
@@ -4,12 +4,12 @@
In this chapter we provide suggested configurations and explain the meaning of individual configuration options.
@menu
-* Minimal configuration::
-* Slave configuration::
-* Master configuration::
-* Configuring multiple interfaces::
+* Minimal configuration::
+* Slave configuration::
+* Master configuration::
+* Configuring multiple interfaces::
* Using DNS UPDATE::
-* Remote control interface::
+* Remote control interface::
* Enabling zone semantic checks::
* Creating IXFR differences from zone file changes::
* Using Response Rate Limiting::
@@ -43,21 +43,21 @@ log @{
@}
zones @{
- example.com @{
+ example.com @{
file "/etc/knot/example.com";
@}
@}
-
+
@end example
@page
Now let's go step by step through this minimal configuration file:
-@enumerate
+@enumerate
@item
In @code{system} statement we have configured @code{storage}
-directory where Knot DNS will store compiled zone files,
+directory where Knot DNS will store compiled zone files,
PID file and for slave zone also their journal files. (See @ref{system} and @ref{storage})
@item
@@ -103,11 +103,12 @@ remotes @{
subnet1 @{ address 192.168.1.0/24; @}
@}
zones @{
- example.com @{
+ example.com @{
file "example.com"; # relative to 'storage'
xfr-in master; # define 'master' for this zone
notify-in master; # also allow NOTIFY from 'master'
- update-in subnet1; # accept UPDATE msgs from subnet1 and forward to master
+ update-in subnet1; # accept UPDATE msgs from subnet1 and forward
+ # to master
@}
@}
@end example
@@ -127,7 +128,7 @@ remotes @{
master @{ address 127.0.0.1@@53; key key0; @}
@}
zones @{
- example.com @{
+ example.com @{
file "example.com"; # relative to 'storage'
xfr-in master; # define 'master' for this zone
notify-in master; # also allow NOTIFY from 'master'
@@ -151,7 +152,7 @@ remotes @{
subnet2 @{ address 192.168.2.0/8; @}
@}
zones @{
- example.com @{
+ example.com @{
file "/var/zones/example.com";
xfr-out subnet1, subnet2; # allow outgoing transfers
notify-out slave;
@@ -170,7 +171,7 @@ remotes @{
any @{ address 0.0.0.0/0; key key0; @}
@}
zones @{
- example.com @{
+ example.com @{
file "/var/zones/example.com";
xfr-out any; # uses 'any' remote secured with TSIG key 'key0'
@}
@@ -195,7 +196,7 @@ interfaces @{
As noted in examples for master and slave, it is possible to accept DNS UPDATE messages.
When the zone is configured as a slave and DNS UPDATE messages is accepted, server forwards the
-message to its primary master specified by @code{xfr-in} directive. When it receives
+message to its primary master specified by @code{xfr-in} directive. When it receives
the response from primary master, it forwards it back to the originator. This finishes the transaction.
However, if the zone is configured as master (i.e. not having any @code{xfr-in} directive), it accepts
@@ -221,29 +222,29 @@ Deleting a last RR also removes its RRSIG.
@node Remote control interface
@section Remote control interface
-It is possible to control Knot DNS remotely. In order to enable remote control,
-you have to define control interface and an appropriate key. Use of key for
-authentication is strongly recommended. The control protocol is not encrypted,
-and susceptible to replay attack in a short timeframe until message digest expires,
-for that reason, it is recommended to enable remote control only on private networks
-or loopback.
+As of v1.3.0, it is possible to control running daemon using UNIX sockets,
+which is also preferred over internet sockets. You don't need any specific configuration,
+since it is enabled by default and the UNIX socket is placed in the rundir.
+To disable remote control completely, add an empty @code{control} section to the
+configuration like:
@example
-keys @{
- knotc-key hmac-md5 "Wg==";
-@}
-remotes @{
- ctl @{ address 127.0.0.1; key knotc-key; @}
-@}
-control @{
- listen-on @{ address 127.0.0.1; @}
- allow ctl;
-@}
+control @{ @}
@end example
-The @code{allow} keyword accepts an ACL list, similar to @code{xfr-in} or @code{xfr-out},
+However you can still use IPv4/IPv6 address, although with several shortcomings.
+You then can use @code{allow} for an ACL list similar to @code{xfr-in} or @code{xfr-out},
see that for syntax reference. The @code{listen-on} has syntax equal to an interface specification,
-but the default port for remote control protocol is @code{5553}.
+but the default port for remote control protocol is @code{5533}.
+However keep in mind, that the transferred data isn't encrypted and could be
+susceptible to replay attack in a short timeframe.
+
+Example configuration:
+@example
+control @{
+ listen-on @{ address 127.0.0.1@@5533; @}
+@}
+@end example
@node Enabling zone semantic checks
@section Enabling zone semantic checks
@@ -253,7 +254,7 @@ which checks are enabled by default and which are optional.
@node Creating IXFR differences from zone file changes
@section Creating IXFR differences from zone file changes
-If Knot is being run as a master server, experimental feature @code{ixfr-from-differences}
+If Knot is being run as a master server, experimental feature @code{ixfr-from-differences}
can be enabled to create IXFR differences from changes made to the master zone file.
See @ref{Controlling running daemon} for more information. For more about @code{zones} statement see @ref{zones}.
@@ -280,8 +281,6 @@ Example configuration:
@example
system @{
rate-limit 200; # Each flow is allowed to 200 resp. per second
- rate-limit-slip 2; # Every other response is slipped (default)
+ rate-limit-slip 2; # Every other response is slipped (default)
@}
@end example
-
-
diff --git a/doc/installation.texi b/doc/installation.texi
index 0d88f06..e8abc5a 100644
--- a/doc/installation.texi
+++ b/doc/installation.texi
@@ -2,10 +2,10 @@
@chapter Knot DNS Installation
@menu
-* Required build environment::
-* Required libraries::
-* Installation from the sources::
-* Installation from packages::
+* Required build environment::
+* Required libraries::
+* Installation from the sources::
+* Installation from packages::
@end menu
@node Required build environment
@@ -27,6 +27,8 @@ autoconf >= 2.65
flex >= 2.5.31
@item
bison >= 2.3
+@item
+ragel >= 6.7 (only required for fast zone parsing)
@end itemize
@node Required libraries
@@ -34,7 +36,7 @@ bison >= 2.3
Knot DNS requires few libraries to be compiled:
-@itemize
+@itemize
@item
OpenSSL, at least 0.9.8
@@ -46,7 +48,7 @@ Userspace RCU, at least 0.5.4
libcap-ng, at least 0.6.4 (optional library)
@end itemize
-If libcap-ng library is available, Knot DNS will take advantage of
+If libcap-ng library is available, Knot DNS will take advantage of
the POSIX 1003.1e capabilites(7) by sandboxing the exposed threads.
Most rights are stripped from the exposed threads for security reasons.
@@ -56,7 +58,7 @@ your system or distribution. If not, zlib resides at
@url{http://www.openssl.org}.
@menu
-* Userspace RCU::
+* Userspace RCU::
@end menu
@node Userspace RCU
@@ -89,9 +91,9 @@ After unpacking the sources, the compilation and installation is
a quite straightforward process using autotools.
@menu
-* Configuring and generating Makefiles::
-* Compilation::
-* Installation::
+* Configuring and generating Makefiles::
+* Compilation::
+* Installation::
@end menu
@node Configuring and generating Makefiles
@@ -113,6 +115,10 @@ $ ./configure --help
If you have trouble with unknown syscalls under valgrind, disable recvmmsg by
adding a parameter @command{--enable-recvmmsg=no} to configure.
+If you want to load huge zone files quickly, enable fast zone parser by
+adding a parameter @command{--enable-fastparser} to configure. In this case
+Ragel compiler is required.
+
Knot DNS has also support for link time optimizations.
You can enable it by the configure parameter @command{./configure --enable-lto=yes}.
It is however disabled by default as it is known to be broken in some compiler
@@ -184,10 +190,10 @@ the Knot DNS might already be available in your favourite
distribution, or in a ports tree.
@menu
-* Installing Knot DNS packages on Debian::
-* Installing Knot DNS packages on Ubuntu::
-* Installing Knot DNS RPMs on Fedora::
-* Installing Knot DNS from ports on FreeBSD::
+* Installing Knot DNS packages on Debian::
+* Installing Knot DNS packages on Ubuntu::
+* Installing Knot DNS packages on Fedora::
+* Installing Knot DNS from ports on FreeBSD::
@end menu
@node Installing Knot DNS packages on Debian
@@ -218,7 +224,7 @@ deb-src http://deb.knot-dns.cz/debian/ <codename> main
EOF
$ apt-get update
$ apt-get install knot
-
+
@end example
@node Installing Knot DNS packages on Ubuntu
@@ -238,7 +244,7 @@ the time of writing this manual this includes Ubuntu 10.04 LTS, 11.04,
11.10 and 12.04 LTS.
@menu
-* Adding official PPA repository for Knot DNS::
+* Adding official PPA repository for Knot DNS::
@end menu
@node Adding official PPA repository for Knot DNS
@@ -253,7 +259,7 @@ the PPA.
$ sudo add-apt-repository ppa:cz.nic-labs/knot-dns
$ sudo apt-get update
$ sudo apt-get install knot
-
+
@end example
@noindent
@@ -262,36 +268,57 @@ install Knot DNS on your system and keep it up-to-date
in the future, when new versions are released.
@page
-@node Installing Knot DNS RPMs on Fedora
-@subsection Installing Knot DNS RPMs on Fedora
+@node Installing Knot DNS packages on Fedora
+@subsection Installing Knot DNS packages on Fedora
+
+The RPM packages for @code{Knot DNS} are available in official Fedora
+repositories since Fedora@tie{}18 (Spherical Cow). Look for @code{knot}
+package in your package manager. To install the package using Yum, run
+a following command as the root user:
+
+@example
+
+# yum install knot
-There are RPM packages for @code{Knot DNS} available for i386 and amd64 targets.
-If you want use the Fedora repository, add a file with the
-following lines into @file{/etc/yum.repos.d/}
+@end example
+
+Using official distribution repository is highly recommended, however you may
+want to run @code{Knot DNS} on older releases of Fedora. In this case you can
+set up an unofficial repository by creating @file{/etc/yum.repos.d/knot.conf}
+file with the following content:
@example
+
[knot]
name=Network.CZ Repository
baseurl=ftp://repo.network.cz/pub/redhat/
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-network.cz
+
@end example
-When you have added a new repository, you can install Knot DNS as a
-regular package.
+After performing this action, you can install @code{knot} package the same way
+as described above. Please note that the unofficial repository contains only
+builds for i686 and x86_64 architecture.
+
+When upgrading to Fedora@tie{}18 or higher, backup the configuration and
+switch to the latest package provided in the official repository by running the
+following command as the root user:
@example
-$ yum install knot
+
+# yum distro-sync knot
+
@end example
+
@node Installing Knot DNS from ports on FreeBSD
@subsection Installing Knot DNS from ports on FreeBSD
Knot DNS is in ports tree under @code{dns/knot}.
@example
-$ cd /usr/ports/dns/knot
+$ cd /usr/ports/dns/knot
$ sudo make install
@end example
-
diff --git a/doc/introduction.texi b/doc/introduction.texi
index 3644636..738cdf7 100644
--- a/doc/introduction.texi
+++ b/doc/introduction.texi
@@ -5,16 +5,16 @@ The reader of this document is assumed to know the principles of
Domain Name System.
@menu
-* What is Knot DNS::
+* What is Knot DNS::
* Knot DNS features::
-* Scope of this document::
+* Scope of this document::
@end menu
@node What is Knot DNS
@section What is Knot DNS
-Knot DNS is a high-performance open source DNS server. It
-implements only authoritative domain name service. Knot DNS
+Knot DNS is a high-performance open source DNS server. It
+implements only authoritative domain name service. Knot DNS
is best suited for use on TLD domains but can reliably serve
any other zones as well.
@@ -47,15 +47,17 @@ Server features:
@item Semantic checks of zones
@end itemize
-For more info and downloads see
+For more info and downloads see
@url{http://www.knot-dns.cz, www.knot-dns.cz}.
-Git repository:
+Git repository:
@url{git://git.nic.cz/knot-dns.git, git://git.nic.cz/knot-dns.git}
-Knot DNS issue tracker:
-@url{https://git.nic.cz/redmine/projects/knot-dns,
-git.nic.cz/redmine/projects/knot-dns}
+Git repository browser:
+@url{https://gitlab.labs.nic.cz/knot/tree/master, gitlab.labs.nic.cz/knot/tree/master}
+
+Knot DNS issue tracker:
+@url{https://gitlab.labs.nic.cz/knot/issues, gitlab.labs.nic.cz/knot/issues}
Knot DNS users mailing list:
@url{mailto:knot-dns-users@@lists.nic.cz, knot-dns-users@@lists.nic.cz}
@@ -65,4 +67,3 @@ Knot DNS users mailing list:
This document covers the basic information on installing,
configuring and troubleshooting the Knot DNS server.
-
diff --git a/doc/knot.info b/doc/knot.info
new file mode 100644
index 0000000..bed79fe
--- /dev/null
+++ b/doc/knot.info
@@ -0,0 +1,2709 @@
+This is ../../doc/knot.info, produced by makeinfo version 4.13 from
+../../doc/knot.texi.
+
+This manual is for Knot DNS (version 1.3.0-rc3, 26 June 2013), which is
+a high-performance authoritative-only DNS server.
+
+Copyright (C) 2012 CZ.NIC, z.s.p.o.
+
+ 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/>.
+
+INFO-DIR-SECTION Internet-application/server
+START-INFO-DIR-ENTRY
+* Knot DNS: (Knot DNS) An authoritative-only DNS server
+END-INFO-DIR-ENTRY
+
+
+File: knot.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir)
+
+Knot DNS
+********
+
+This manual is for Knot DNS (version 1.3.0-rc3, 26 June 2013).
+
+* Menu:
+
+* Introduction::
+* Knot DNS Resource Requirements::
+* Knot DNS Installation::
+* Knot DNS Configuration::
+* Running Knot DNS::
+* Troubleshooting::
+* Statement Index::
+* Knot DNS Configuration Reference::
+
+ --- The Detailed Node Listing ---
+
+Introduction
+
+* What is Knot DNS::
+* Knot DNS features::
+* Scope of this document::
+
+Knot DNS Resource Requirements
+
+* Hardware requirements::
+* CPU requirements::
+* Memory requirements::
+* Supported operating system::
+
+Knot DNS Installation
+
+* Required build environment::
+* Required libraries::
+* Installation from the sources::
+* Installation from packages::
+
+Required libraries
+
+* Userspace RCU::
+
+Installation from the sources
+
+* Configuring and generating Makefiles::
+* Compilation::
+* Installation::
+
+Installation from packages
+
+* Installing Knot DNS packages on Debian::
+* Installing Knot DNS packages on Ubuntu::
+* Installing Knot DNS packages on Fedora::
+* Installing Knot DNS from ports on FreeBSD::
+
+Installing Knot DNS packages on Ubuntu
+
+* Adding official PPA repository for Knot DNS::
+
+Knot DNS Configuration
+
+* Minimal configuration::
+* Slave configuration::
+* Master configuration::
+* Configuring multiple interfaces::
+
+Sample Configurations
+
+* Minimal configuration::
+* Slave configuration::
+* Master configuration::
+* Configuring multiple interfaces::
+* Enabling zone semantic checks::
+* Creating IXFR differences from zone file changes::
+
+Running Knot DNS
+
+* Running a slave server::
+* Running a master server::
+* Controlling running daemon::
+
+Troubleshooting
+
+* Submitting a bugreport::
+* Generating backtrace::
+* Debug messages::
+
+Debug messages
+
+* Enabling debug messages in server::
+
+Enabling debug messages in server
+
+* Example::
+
+Knot DNS Configuration Reference
+
+* system::
+* keys::
+* interfaces::
+* remotes::
+* groups::
+* zones::
+* log::
+* include::
+
+`system' Statement
+
+* system Syntax::
+* system Statement Definition and Usage::
+* system Example::
+
+Statement Definition and Usage
+
+* identity::
+* version::
+* nsid::
+* storage::
+* rundir::
+* workers::
+* user::
+* max-conn-idle::
+* max-conn-hs::
+* max-conn-reply::
+* rate-limit::
+* rate-limit-size::
+* rate-limit-slip::
+
+`keys' Statement
+
+* keys Syntax::
+* keys Statement Definition and Usage::
+* Example::
+
+Statement Definition and Usage
+
+* key_id::
+
+interfaces
+
+* interfaces Syntax::
+* interfaces Statement Definition and Usage::
+* interfaces Examples::
+
+Statement Definition and Usage
+
+* interface_id::
+
+`remotes' Statement
+
+* remotes Syntax::
+* remotes Statement Definition and Grammar::
+
+`groups' Statement
+
+* groups Syntax::
+* groups Statement Definition and Grammar::
+
+`zones' Statement
+
+* zones Syntax::
+* zones Statement Definition and Grammar::
+* zones List of zone semantic checks::
+
+`log' Statement
+
+* log Syntax::
+* log Statement Definition and Grammar::
+
+`include' Statement
+
+* include Syntax::
+
+
+File: knot.info, Node: Introduction, Next: Knot DNS Resource Requirements, Prev: Top, Up: Top
+
+1 Introduction
+**************
+
+The reader of this document is assumed to know the principles of Domain
+Name System.
+
+* Menu:
+
+* What is Knot DNS::
+* Knot DNS features::
+* Scope of this document::
+
+
+File: knot.info, Node: What is Knot DNS, Next: Knot DNS features, Up: Introduction
+
+1.1 What is Knot DNS
+====================
+
+Knot DNS is a high-performance open source DNS server. It implements
+only authoritative domain name service. Knot DNS is best suited for use
+on TLD domains but can reliably serve any other zones as well.
+
+Knot DNS benefits from its multi-threaded and mostly lock-free
+implementation which allows it to scale well on SMP systems and operate
+non-stop even when adding or removing zones.
+
+
+File: knot.info, Node: Knot DNS features, Next: Scope of this document, Prev: What is Knot DNS, Up: Introduction
+
+1.2 Knot DNS features
+=====================
+
+Knot DNS supports the following DNS features:
+
+ * TCP/UDP protocols
+
+ * AXFR - master, slave
+
+ * IXFR - master (primary master experimental), slave
+
+ * TSIG
+
+ * ENDS0
+
+ * DNSSEC, including NSEC3
+
+ * NSID
+
+ * Unknown RR types
+
+Server features:
+
+ * Adding/removing zones on-the-fly
+
+ * Reconfiguring server instance on-the-fly
+
+ * IPv4 / IPv6 support
+
+ * Semantic checks of zones
+
+For more info and downloads see www.knot-dns.cz
+(http://www.knot-dns.cz).
+
+Git repository: git://git.nic.cz/knot-dns.git
+(git://git.nic.cz/knot-dns.git)
+
+Git repository browser: gitlab.labs.nic.cz/knot/tree/master
+(https://gitlab.labs.nic.cz/knot/tree/master)
+
+Knot DNS issue tracker: gitlab.labs.nic.cz/knot/issues
+(https://gitlab.labs.nic.cz/knot/issues)
+
+Knot DNS users mailing list: knot-dns-users@lists.nic.cz
+(mailto:knot-dns-users@lists.nic.cz)
+
+
+File: knot.info, Node: Scope of this document, Prev: Knot DNS features, Up: Introduction
+
+1.3 Scope of this document
+==========================
+
+This document covers the basic information on installing, configuring
+and troubleshooting the Knot DNS server.
+
+
+File: knot.info, Node: Knot DNS Resource Requirements, Next: Knot DNS Installation, Prev: Introduction, Up: Top
+
+2 Knot DNS Resource Requirements
+********************************
+
+* Menu:
+
+* Hardware requirements::
+* CPU requirements::
+* Memory requirements::
+* Supported operating system::
+
+
+File: knot.info, Node: Hardware requirements, Next: CPU requirements, Up: Knot DNS Resource Requirements
+
+2.1 Hardware requirements
+=========================
+
+Knot DNS requirements are not very demanding for typical installations,
+and a commodity server or a virtual solution will be sufficient in most
+cases.
+
+However please note that there are some scenarios that will require
+administrator attention and testing of exact requirements before
+deploying Knot DNS in production. These cases include deployment for a
+large number of zones (DNS hosting), a large number of records in one
+or more zones (TLD) or large number of requests.
+
+
+File: knot.info, Node: CPU requirements, Next: Memory requirements, Prev: Hardware requirements, Up: Knot DNS Resource Requirements
+
+2.2 CPU requirements
+====================
+
+Knot DNS scales with processing power and also with the number of
+available cores/CPUs.
+
+There is no lower bound on the CPU requirements, but it should support
+memory barriers and CAS (i586 and newer).
+
+
+File: knot.info, Node: Memory requirements, Next: Supported operating system, Prev: CPU requirements, Up: Knot DNS Resource Requirements
+
+2.3 Memory requirements
+=======================
+
+Knot DNS implementation focuses on performance and thus can be quite
+demanding for memory. The rough estimate for memory requirements is
+5-7 times of the size of the zone in text format. Again this is only
+an estimate and you are advised to do your own measurements before
+deploying Knot DNS into production.
+
+Also note that to ensure uninterrupted serving of the zone, Knot DNS
+employs a Read-Copy-Update mechanism instead of locking and thus
+requires twice the amount of memory for the duration of incoming
+transfers.
+
+
+File: knot.info, Node: Supported operating system, Prev: Memory requirements, Up: Knot DNS Resource Requirements
+
+2.4 Supported operating system
+==============================
+
+Knot DNS itself is written in a portable way, but it depends on several
+libraries. Namely userspace-rcu, which could be a constraint when it
+comes to the operating system support. As far as we know the Knot DNS
+can be compiled and run on Linux, FreeBSD, OpenBSD, NetBSD and Mac OS X.
+
+
+File: knot.info, Node: Knot DNS Installation, Next: Knot DNS Configuration, Prev: Knot DNS Resource Requirements, Up: Top
+
+3 Knot DNS Installation
+***********************
+
+* Menu:
+
+* Required build environment::
+* Required libraries::
+* Installation from the sources::
+* Installation from packages::
+
+
+File: knot.info, Node: Required build environment, Next: Required libraries, Up: Knot DNS Installation
+
+3.1 Required build environment
+==============================
+
+GCC at least 4.1 is strictly required for atomic built-ins, but 4.2 or
+newer is recommended. Another requirement is `_GNU_SOURCE' support,
+otherwise it adapts to the compiler available features. Clang should
+work, but it is not officially supported.
+
+Knot DNS build system relies on these standard tools:
+ * make
+
+ * libtool
+
+ * autoconf >= 2.65
+
+ * flex >= 2.5.31
+
+ * bison >= 2.3
+
+ * ragel >= 6.7 (only required for fast zone parsing)
+
+
+File: knot.info, Node: Required libraries, Next: Installation from the sources, Prev: Required build environment, Up: Knot DNS Installation
+
+3.2 Required libraries
+======================
+
+Knot DNS requires few libraries to be compiled:
+
+ * OpenSSL, at least 0.9.8
+
+ * zlib
+
+ * Userspace RCU, at least 0.5.4
+
+ * libcap-ng, at least 0.6.4 (optional library)
+
+If libcap-ng library is available, Knot DNS will take advantage of the
+POSIX 1003.1e capabilites(7) by sandboxing the exposed threads. Most
+rights are stripped from the exposed threads for security reasons.
+
+You can probably find OpenSSL and zlib libraries already included in
+your system or distribution. If not, zlib resides at
+`http://zlib.net', and OpenSSL can be found at `http://www.openssl.org'.
+
+* Menu:
+
+* Userspace RCU::
+
+
+File: knot.info, Node: Userspace RCU, Up: Required libraries
+
+3.2.1 Userspace RCU
+-------------------
+
+liburcu is a LGPLv2.1 userspace RCU (read-copy-update) library. This
+data synchronization library provides read-side access which scales
+linearly with the number of cores. It does so by allowing multiple
+copies of a given data structure to live at the same time, and by
+monitoring the data structure accesses to detect grace periods after
+which memory reclamation is possible. (Userspace RCU
+(http://lttng.org/urcu))
+
+Binary packages for Debian can be found under `liburcu1' for the
+library and `liburcu-dev' for development files.
+
+Minimum supported version of Userspace RCU library is 0.5.4, but we
+recommend using latest available version. It is crucial especially on
+non-Linux systems, as we got some compatibility patches accepted to
+later releases of Userspace RCU. OpenBSD, NetBSD and OS X platforms
+are supported from version 0.7.0.
+
+
+File: knot.info, Node: Installation from the sources, Next: Installation from packages, Prev: Required libraries, Up: Knot DNS Installation
+
+3.3 Installation from the sources
+=================================
+
+You can find the source files for the latest release on
+`www.knot-dns.cz'. Alternatively, you can fetch the sources from git
+repository `git://git.nic.cz/knot-dns.git'
+
+After unpacking the sources, the compilation and installation is a
+quite straightforward process using autotools.
+
+* Menu:
+
+* Configuring and generating Makefiles::
+* Compilation::
+* Installation::
+
+
+File: knot.info, Node: Configuring and generating Makefiles, Next: Compilation, Up: Installation from the sources
+
+3.3.1 Configuring and generating Makefiles
+------------------------------------------
+
+If you want to compile from Git sources, you need to bootstrap the
+`./configure' file first.
+
+ $ autoreconf -i -f
+
+For all available configure options run:
+
+ $ ./configure --help
+
+If you have trouble with unknown syscalls under valgrind, disable
+recvmmsg by adding a parameter `--enable-recvmmsg=no' to configure.
+
+If you want to load huge zone files quickly, enable fast zone parser by
+adding a parameter `--enable-fastparser' to configure. In this case
+Ragel compiler is required.
+
+Knot DNS has also support for link time optimizations. You can enable
+it by the configure parameter `./configure --enable-lto=yes'. It is
+however disabled by default as it is known to be broken in some compiler
+versions and may result in an unexpected behaviour.
+
+If you want to add debug messages, there are two steps to do that.
+First you have to enable modules you are interested in. Available are:
+`server, zones, xfr, packet, dname, rr, ns, hash, compiler'. You can
+combine multiple modules as a comma-separated list. Then you can
+narrow the verbosity of the debugging message by specifying the
+verbosity as `brief, verbose, details'.
+
+For example:
+ $ ./configure --enable-debug=server,packet --enable-debuglevel=brief
+ $ ./configure --enable-debug=server,packet --enable-debuglevel=verbose
+
+For more detailed information, see *note Debug messages::.
+
+In most simple case you can just run configure without any options.
+
+ $ ./configure
+
+
+File: knot.info, Node: Compilation, Next: Installation, Prev: Configuring and generating Makefiles, Up: Installation from the sources
+
+3.3.2 Compilation
+-----------------
+
+After running `./configure' you can compile Knot DNS by running `make'
+command, which will produce binaries and other related files.
+
+ $ make
+
+Knot DNS build process is safe to parallelize using `make -j N', where
+N is number of concurrent processes. Using this option can increase
+speed of the compilation.
+
+For example to use maximum 8 concurrent processes you would use:
+
+ $ make -j 8
+
+
+File: knot.info, Node: Installation, Prev: Compilation, Up: Installation from the sources
+
+3.3.3 Installation
+------------------
+
+When you have finished building the Knot DNS, it's time to install the
+binaries and configuration files into the operation system hierarchy.
+You can do so by executing `make install' command. When installing as a
+non-root user you might have to gain elevated privileges by switching
+to root user, e.g. `sudo make install' or `su -c 'make install''.
+
+ $ make install
+
+
+File: knot.info, Node: Installation from packages, Prev: Installation from the sources, Up: Knot DNS Installation
+
+3.4 Installation from packages
+==============================
+
+In addition to providing the packages in .DEB and .RPM format, the Knot
+DNS might already be available in your favourite distribution, or in a
+ports tree.
+
+* Menu:
+
+* Installing Knot DNS packages on Debian::
+* Installing Knot DNS packages on Ubuntu::
+* Installing Knot DNS packages on Fedora::
+* Installing Knot DNS from ports on FreeBSD::
+
+
+File: knot.info, Node: Installing Knot DNS packages on Debian, Next: Installing Knot DNS packages on Ubuntu, Up: Installation from packages
+
+3.4.1 Installing Knot DNS packages on Debian
+--------------------------------------------
+
+Knot DNS is already available from Debian wheezy upwards. In addition
+to the official packages we also provide custom repository, which can
+be used by adding:
+
+ deb `http://deb.knot-dns.cz/debian/' <codename> main
+ deb-src `http://deb.knot-dns.cz/debian/' <codename> main
+
+to your `/etc/apt/sources.list' or into separate file in
+`/etc/apt/sources.list.d/'.
+
+As an example, for Debian squeeze (current stable) the Knot DNS
+packages can be added by executing following command as the root user.
+
+
+ $ cat >/etc/apt/sources.list.d/knot.list <<EOF
+ deb http://deb.knot-dns.cz/debian/ <codename> main
+ deb-src http://deb.knot-dns.cz/debian/ <codename> main
+ EOF
+ $ apt-get update
+ $ apt-get install knot
+
+
+File: knot.info, Node: Installing Knot DNS packages on Ubuntu, Next: Installing Knot DNS packages on Fedora, Prev: Installing Knot DNS packages on Debian, Up: Installation from packages
+
+3.4.2 Installing Knot DNS packages on Ubuntu
+--------------------------------------------
+
+Prepackaged version of the Knot DNS can be found in Ubuntu from version
+12.10 (Quantal Quetzal). In addition to the package included in the
+main archive, we provide Personal Package Archive (PPA) as an option to
+upgrade to last stable version of the Knot DNS or to install it on
+older versions of Ubuntu Linux.
+
+We typically provide packages for all supported versions of Ubuntu
+Linux including 5 year support for LTS (https://wiki.ubuntu.com/LTS)
+versions of Ubuntu Linux. At the time of writing this manual this
+includes Ubuntu 10.04 LTS, 11.04, 11.10 and 12.04 LTS.
+
+* Menu:
+
+* Adding official PPA repository for Knot DNS::
+
+
+File: knot.info, Node: Adding official PPA repository for Knot DNS, Up: Installing Knot DNS packages on Ubuntu
+
+3.4.2.1 Adding official PPA repository for Knot DNS
+...................................................
+
+To start installing and using software from a Personal Package Archive,
+you first need to tell Ubuntu where to find the PPA.
+
+
+ $ sudo add-apt-repository ppa:cz.nic-labs/knot-dns
+ $ sudo apt-get update
+ $ sudo apt-get install knot
+
+Running this sequence of commands will ensure that you will install
+Knot DNS on your system and keep it up-to-date in the future, when new
+versions are released.
+
+
+File: knot.info, Node: Installing Knot DNS packages on Fedora, Next: Installing Knot DNS from ports on FreeBSD, Prev: Installing Knot DNS packages on Ubuntu, Up: Installation from packages
+
+3.4.3 Installing Knot DNS packages on Fedora
+--------------------------------------------
+
+The RPM packages for `Knot DNS' are available in official Fedora
+repositories since Fedora 18 (Spherical Cow). Look for `knot' package
+in your package manager. To install the package using Yum, run a
+following command as the root user:
+
+
+ # yum install knot
+
+Using official distribution repository is highly recommended, however
+you may want to run `Knot DNS' on older releases of Fedora. In this
+case you can set up an unofficial repository by creating
+`/etc/yum.repos.d/knot.conf' file with the following content:
+
+
+ [knot]
+ name=Network.CZ Repository
+ baseurl=ftp://repo.network.cz/pub/redhat/
+ enabled=1
+ gpgcheck=0
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-network.cz
+
+After performing this action, you can install `knot' package the same
+way as described above. Please note that the unofficial repository
+contains only builds for i686 and x86_64 architecture.
+
+When upgrading to Fedora 18 or higher, backup the configuration and
+switch to the latest package provided in the official repository by
+running the following command as the root user:
+
+
+ # yum distro-sync knot
+
+
+File: knot.info, Node: Installing Knot DNS from ports on FreeBSD, Prev: Installing Knot DNS packages on Fedora, Up: Installation from packages
+
+3.4.4 Installing Knot DNS from ports on FreeBSD
+-----------------------------------------------
+
+Knot DNS is in ports tree under `dns/knot'.
+
+ $ cd /usr/ports/dns/knot
+ $ sudo make install
+
+
+File: knot.info, Node: Knot DNS Configuration, Next: Running Knot DNS, Prev: Knot DNS Installation, Up: Top
+
+4 Knot DNS Configuration
+************************
+
+In this chapter we provide suggested configurations and explain the
+meaning of individual configuration options.
+
+* Menu:
+
+* Minimal configuration::
+* Slave configuration::
+* Master configuration::
+* Configuring multiple interfaces::
+* Using DNS UPDATE::
+* Remote control interface::
+* Enabling zone semantic checks::
+* Creating IXFR differences from zone file changes::
+* Using Response Rate Limiting::
+
+
+File: knot.info, Node: Minimal configuration, Next: Slave configuration, Up: Knot DNS Configuration
+
+4.1 Minimal configuration
+=========================
+
+The following configuration presents a minimal configuration file which
+can be used as a base for your Knot DNS setup.
+
+
+ # This is a sample of a minimal configuration file for Knot DNS.
+ #
+ # For exhaustive list of all options see samples/knot.full.conf
+ # in the source directory.
+ #
+
+ system {
+ storage "/var/lib/knot";
+ }
+
+ interfaces {
+ my_interface { address 127.0.0.1@53; }
+ second_int { address ::1; }
+ }
+
+ log {
+ syslog { any notice, warning, error; }
+ }
+
+ zones {
+ example.com {
+ file "/etc/knot/example.com";
+ }
+ }
+
+Now let's go step by step through this minimal configuration file:
+
+ 1. In `system' statement we have configured `storage' directory where
+ Knot DNS will store compiled zone files, PID file and for slave
+ zone also their journal files. (See *note system:: and *note
+ storage::)
+
+ 2. The `interfaces' statement defines interfaces where Knot DNS will
+ listen for incoming connections. We have defined two interfaces:
+ one IPv4 called `my_interface' explicitly listening on port 53 and
+ second IPv6 called `second_int' also listening on port 53, which
+ is the default port for the DNS. See *note interfaces::.
+
+ 3. The `log' statement defines the log facilities for Knot DNS. In
+ this example we told Knot DNS to send its log messages with the
+ severities `debug', `warning' and `notice' into the syslog. If
+ you omit this sections, all severities will printed to either
+ `stdout' or `stderr', and the severities from the `warning' and
+ more serious to syslog. You can find all possible combinations in
+ the *note log::.
+
+ 4. The `zones' statement is probably the most important one, because
+ it defines the zones that Knot DNS will serve. In its most simple
+ form you can define a zone by its name and zone file.
+
+
+File: knot.info, Node: Slave configuration, Next: Master configuration, Prev: Minimal configuration, Up: Knot DNS Configuration
+
+4.2 Slave configuration
+=======================
+
+Knot DNS doesn't strictly differ between master and slave zones. The
+only requirement is to have `xfr-in' `zones' statement set for given
+zone, thus allowing both incoming XFR from that remote and using it as
+the zone master. If `update-in' is set and zone has a master, any
+accepted DNS UPDATE will be forwarded to master. Also note that you
+need to explicitly allow incoming NOTIFY, otherwise the daemon would
+reject them. Also, you can specify paths, relative to the storage
+directory. See *note zones:: and *note storage::. If the zone file
+doesn't exist and `xfr-in' is set, it will be bootstrapped over AXFR.
+
+ remotes {
+ master { address 127.0.0.1@53; }
+ subnet1 { address 192.168.1.0/24; }
+ }
+ zones {
+ example.com {
+ file "example.com"; # relative to 'storage'
+ xfr-in master; # define 'master' for this zone
+ notify-in master; # also allow NOTIFY from 'master'
+ update-in subnet1; # accept UPDATE msgs from subnet1 and forward
+ # to master
+ }
+ }
+
+You can also use TSIG for access control. For this, you need to
+configure a TSIG key and assign it to a remote. Supported algorithms
+for TSIG key are:
+`hmac-md5, hmac-sha1, hmac-sha224, hmac-sha256, hmac-sha384,
+hmac-sha512'
+Key secret is written in a base64 encoded format. See *note keys::.
+
+ keys {
+ key0 hmac-md5 "Wg=="; # keyname algorithm secret
+ }
+ remotes {
+ master { address 127.0.0.1@53; key key0; }
+ }
+ zones {
+ example.com {
+ file "example.com"; # relative to 'storage'
+ xfr-in master; # define 'master' for this zone
+ notify-in master; # also allow NOTIFY from 'master'
+ }
+ }
+
+As of now it is not possible to associate multiple keys with a remote.
+
+
+File: knot.info, Node: Master configuration, Next: Configuring multiple interfaces, Prev: Slave configuration, Up: Knot DNS Configuration
+
+4.3 Master configuration
+========================
+
+You can specify which remotes to allow for outgoing XFR and NOTIFY
+`zones'.
+
+ remotes {
+ slave { address 127.0.0.1@53; }
+ any { address 0.0.0.0/0; }
+ subnet1 { address 192.168.1.0/8; }
+ subnet2 { address 192.168.2.0/8; }
+ }
+ zones {
+ example.com {
+ file "/var/zones/example.com";
+ xfr-out subnet1, subnet2; # allow outgoing transfers
+ notify-out slave;
+ update-in subnet1; # only allow DNS UPDATE from subnet1
+ }
+ }
+
+You can also secure outgoing XFRs with TSIG.
+
+ keys {
+ key0 hmac-md5 "Wg=="; # keyname algorithm secret
+ }
+ remotes {
+ any { address 0.0.0.0/0; key key0; }
+ }
+ zones {
+ example.com {
+ file "/var/zones/example.com";
+ xfr-out any; # uses 'any' remote secured with TSIG key 'key0'
+ }
+ }
+
+
+File: knot.info, Node: Configuring multiple interfaces, Next: Using DNS UPDATE, Prev: Master configuration, Up: Knot DNS Configuration
+
+4.4 Configuring multiple interfaces
+===================================
+
+Knot DNS support binding to multiple available interfaces in the
+`interfaces' section.
+You can also use the special addresses for "any address" like `0.0.0.0'
+or `[::]'.
+
+ interfaces {
+ if1 { address 192.168.1.2@53; }
+ anyv6 { address [::]@53; }
+ }
+
+
+File: knot.info, Node: Using DNS UPDATE, Next: Remote control interface, Prev: Configuring multiple interfaces, Up: Knot DNS Configuration
+
+4.5 Using DNS UPDATE
+====================
+
+As noted in examples for master and slave, it is possible to accept DNS
+UPDATE messages. When the zone is configured as a slave and DNS UPDATE
+messages is accepted, server forwards the message to its primary master
+specified by `xfr-in' directive. When it receives the response from
+primary master, it forwards it back to the originator. This finishes
+the transaction.
+
+However, if the zone is configured as master (i.e. not having any
+`xfr-in' directive), it accepts such an UPDATE and processes it. As of
+1.2, there are a few limitations with DNSSEC signed zones described
+below. Other than that, UPDATE of unsigned zones works as expected
+without any limitations.
+
+ * Knot DNS doesn't automatically sign incoming RR if the zone is
+ signed. As a workaround, it accepts DNSSEC-related records.
+ However, it may prove challenging to create such an UPDATE that it
+ correctly adds/replaces signed RRs, so this feature should be
+ treated as experimental until correct signing is implemented.
+
+ * As for the reason in a previous point, removing RRSIG with no
+ specified rdata makes it impossible to determine whether the user
+ meant a RRSIG for an NSEC3 record or other one. Since they are
+ stored separately, it is advisable to always specify RRSIG along
+ with at least the types it covers.
+
+ * Deleting a last RR also removes its RRSIG.
+
+
+
+File: knot.info, Node: Remote control interface, Next: Enabling zone semantic checks, Prev: Using DNS UPDATE, Up: Knot DNS Configuration
+
+4.6 Remote control interface
+============================
+
+As of v1.3.0, it is possible to control running daemon using UNIX
+sockets, which is also preferred over internet sockets. You don't need
+any specific configuration, since it is enabled by default and the UNIX
+socket is placed in the rundir. To disable remote control completely,
+add an empty `control' section to the configuration like:
+
+ control { }
+
+However you can still use IPv4/IPv6 address, although with several
+shortcomings. You then can use `allow' for an ACL list similar to
+`xfr-in' or `xfr-out', see that for syntax reference. The `listen-on'
+has syntax equal to an interface specification, but the default port
+for remote control protocol is `5533'. However keep in mind, that the
+transferred data isn't encrypted and could be susceptible to replay
+attack in a short timeframe.
+
+Example configuration:
+ control {
+ listen-on { address 127.0.0.1@5533; }
+ }
+
+
+File: knot.info, Node: Enabling zone semantic checks, Next: Creating IXFR differences from zone file changes, Prev: Remote control interface, Up: Knot DNS Configuration
+
+4.7 Enabling zone semantic checks
+=================================
+
+You can turn on more detailed semantic checks of zone file in this
+`zones' statement (*note zones::). Refer to *note zones List of zone
+semantic checks:: to see which checks are enabled by default and which
+are optional.
+
+
+File: knot.info, Node: Creating IXFR differences from zone file changes, Next: Using Response Rate Limiting, Prev: Enabling zone semantic checks, Up: Knot DNS Configuration
+
+4.8 Creating IXFR differences from zone file changes
+====================================================
+
+If Knot is being run as a master server, experimental feature
+`ixfr-from-differences' can be enabled to create IXFR differences from
+changes made to the master zone file. See *note Controlling running
+daemon:: for more information. For more about `zones' statement see
+*note zones::.
+
+
+File: knot.info, Node: Using Response Rate Limiting, Prev: Creating IXFR differences from zone file changes, Up: Knot DNS Configuration
+
+4.9 Using Response Rate Limiting
+================================
+
+Response rate limiting (RRL) is a method to combat recent DNS
+reflection amplification attacks. These attacked rely on the fact that
+source address of a UDP query could be forged, and without a worldwide
+deployment of BCP38, such a forgery could not be detected. Attacker
+could then exploit DNS server responding to every query, potentially
+flooding the victim with a large unsolicited DNS responses.
+
+As of Knot DNS version 1.2.0, RRL is compiled in, but disabled by
+default. You can enable it with the *note rate-limit:: option in the
+*note system:: section. Setting to a value greater than `0' means that
+every flow is allowed N responses per second, (i.e. `rate-limit 50;'
+means `50' responses per second). It is also possible to configure
+SLIP interval, which causes every Nth blocked response to be slipped as
+a truncated response. Not that some error responses cannot be truncated
+and are slipped as-is. For more information, refer to *note
+rate-limit-slip::. It is advisable to not set slip interval to a value
+larger than 2, to allow legitimate clients get at least some level of
+service.
+
+Example configuration:
+ system {
+ rate-limit 200; # Each flow is allowed to 200 resp. per second
+ rate-limit-slip 2; # Every other response is slipped (default)
+ }
+
+
+File: knot.info, Node: Running Knot DNS, Next: Troubleshooting, Prev: Knot DNS Configuration, Up: Top
+
+5 Running Knot DNS
+******************
+
+* Menu:
+
+* Running a slave server::
+* Running a master server::
+* Controlling running daemon::
+
+Knot DNS can run either in the foreground or in a background, with the
+`-d' option. When run in foreground, it doesn't create a PID file.
+Other than that, there are no differences and you can control it just
+the same way.
+ Usage: knotd [parameters]
+
+ Parameters:
+ -c, --config [file] Select configuration file.
+ -d, --daemonize Run server as a daemon.
+ -v, --verbose Verbose mode - additional runtime information.
+ -V, --version Print version of the server.
+ -h, --help Print help and usage.
+
+Use knotc tool for convenience when working with the server daemon. As
+of Knot DNS 1.3.0, the zones are not compiled anymore. That makes
+working with the server much more user friendly.
+ $ knotc -c knot.conf reload|restart
+
+The tool `knotc' is designed as a front-end for user, making it easier
+to do everything from server startup to state checking of a running
+server daemon. If you want to control the daemon directly, use
+`SIGINT' to quit the process or `SIGHUP' to reload configuration.
+
+ Usage: knotc [parameters] <action> [action_args]
+
+ Parameters:
+ -c [file], --config=[file] Select configuration file.
+ -s [server] Remote UNIX socket/IP address (default ${rundir}/knot.sock).
+ -p [port] Remote server port (only for IP).
+ -y [[hmac:]name:key] Use key_id specified on the command line.
+ -k [file] Use key file (as in config section 'keys').
+ Example:
+ echo "knotc-key hmac-md5 Wg==" > knotc.key
+ -f, --force Force operation - override some checks.
+ -v, --verbose Verbose mode - additional runtime
+ information.
+ -V, --version Print knot server version.
+ -w, --wait Wait for the server to finish start/stop
+ operations.
+ -i, --interactive Interactive mode (do not daemonize).
+ -h, --help Print help and usage.
+
+ Actions:
+ start Start server (if not running).
+ stop Stop server.
+ restart Restart server.
+ reload Reload configuration and changed zones.
+ refresh [zone] Refresh slave zone (all if not specified).
+ flush Flush journal and update zone files.
+ status Check if server is running.
+ zonestatus Show status of configured zones.
+ checkconf Check current server configuration.
+ checkzone [zone] Check zone (all if not specified).
+ memstats [zone] Estimate memory consumption for zone (all if not specified).
+
+Also, the server needs to create several files in order to run properly.
+Zones and related data are stored in the directory described by
+`storage' (*note storage::).
+ * _Journal files_ - each zone has a journal file to store
+ differences for IXFR and dynamic updates. Journal for zone
+ `example.com' will be placed in `STORAGE/example.com.diff.db'.
+
+ * _PID file_ - is created automatically in `rundir' (*note rundir::)
+ when the server is run in background.
+
+ * _Control sockets_ - as a default, UNIX sockets are created in
+ `rundir' (*note rundir::), but can be overriden.
+
+
+File: knot.info, Node: Running a slave server, Next: Running a master server, Up: Running Knot DNS
+
+5.1 Running a slave server
+==========================
+
+Running the server as a slave is very straightforward as you usually
+bootstrap zones over AXFR and thus avoid any manual zone compilation.
+In contrast to AXFR, when the incremental transfer finishes, it stores
+the differences in a journal file and doesn't update the zone file
+immediately. There is a timer that checks periodically for new
+differences and updates the zone file. You can configure this timer
+with the `zonefile-sync' statement in `zones' (*note zones::).
+
+There are two ways to start the server - in foreground or background.
+First, let's start in foreground. If you do not pass any configuration,
+it will try to search configuration in default path that is
+`SYSCONFDIR/knot.conf'. The `SYSCONFDIR' depends on what you passed to
+the `./configure', usually `/etc'.
+
+ $ knotd -c slave.conf
+
+To start it as a daemon, just add a `-d' parameter. Unlike the
+foreground mode, PID file will be created in `rundir' directory.
+
+ $ knotd -d -c slave.conf # start the daemon
+ $ knotc -c slave.conf stop # stop the daemon
+
+When the server is running, you can control the daemon, see *note
+Controlling running daemon::.
+
+
+File: knot.info, Node: Running a master server, Next: Controlling running daemon, Prev: Running a slave server, Up: Running Knot DNS
+
+5.2 Running a master server
+===========================
+
+If you want to just check the zone files first before starting, you can
+use `knotc checkzone' action.
+ $ knotc -c master.conf checkzone example.com
+
+For an approximate estimate of server's memory consumption, you can use
+the `knotc memstats' action. This action prints count of resource
+records, percentage of signed records and finally estimation of memory
+consumption for each zone, unless specified otherwise. Please note that
+estimated values might differ from the actual consumption. Also, for
+slave servers with incoming transfers enabled, be aware that the actual
+memory consumption might be double or more during transfers.
+
+ $ knotc -c master.conf memstats example.com
+
+Starting and stopping the daemon is the same as with the slave server
+in the previous section.
+
+
+File: knot.info, Node: Controlling running daemon, Prev: Running a master server, Up: Running Knot DNS
+
+5.3 Controlling running daemon
+==============================
+
+Knot DNS was designed to allow server reconfiguration on-the-fly
+without interrupting its operation. Thus it is possible to change both
+configuration and zone files and also add or remove zones without
+restarting the server. This can be done with the `knotc reload' action.
+
+ $ knotc -c master.conf reload # reconfigure and load updated zones
+
+If you want _IXFR-out_ differences created from changes you make to a
+zone file, enable *note ixfr-from-differences:: in `zones' statement,
+then reload your server as seen above. If _SOA_'s _serial_ is not
+changed no differences will be created. Please note that this feature
+is in _experimental_ stage and should be used with care. If you
+encounter a bug using this feature, please send it to Knot developers
+(*note Submitting a bugreport::).
+
+You can also choose to tear-down the server fully and restart with the
+`knotc restart' action. Note that some actions like start, stop and
+restart cannot be done remotely.
+ $ knotc -c master.conf status # check if running
+ $ knotc -c master.conf restart # fully restart
+
+If you want to force refresh the slave zones, you can do this with the
+`knotc refresh' action.
+ $ knotc -c slave.conf refresh
+
+For a complete list of actions refer to `knotc --help' command output.
+
+
+File: knot.info, Node: Troubleshooting, Next: Statement Index, Prev: Running Knot DNS, Up: Top
+
+6 Troubleshooting
+*****************
+
+* Menu:
+
+* Submitting a bugreport::
+* Generating backtrace::
+* Debug messages::
+
+First of all, check the logs (*note log::). By default, Knot DNS logs
+all error messages to syslog. Enabling at least the `warning' message
+severity may help you identify some problems.
+
+
+File: knot.info, Node: Submitting a bugreport, Next: Generating backtrace, Up: Troubleshooting
+
+6.1 Submitting a bugreport
+==========================
+
+If you are unable to solve the problem by yourselves, you can submit a
+bugreport to the Knot DNS team. For security issues (e.g. crash) do not
+use the public mailinglist. Instead, write to knot-dns@labs.nic.cz
+(mailto:knot-dns@labs.nic.cz). All other bugs and questions may be
+directed to the Knot DNS users mailinglist (knot-dns-users@lists.nic.cz
+(mailto:knot-dns-users@lists.nic.cz)).
+
+The bugreport should contain at least:
+ * Knot DNS version and type of installation (source, package, etc.),
+
+ * type and version of your operating system,
+
+ * basic hardware information,
+
+ * description of the bug,
+
+ * log output of all messages (category `any') with severity Info and
+ higher (severities `info, notice, warning, error', or `any' if
+ debug messages are not turned on (see below)),
+
+ * steps to reproduce the bug (if known),
+
+ * backtrace (if the bug caused a crash; see next section).
+
+If it is possible, the actual configuration file and/or zone file(s)
+will be very useful as well.
+
+
+File: knot.info, Node: Generating backtrace, Next: Debug messages, Prev: Submitting a bugreport, Up: Troubleshooting
+
+6.2 Generating backtrace
+========================
+
+There are several ways to achieve that, the most common way is to leave
+core dumps and then extract a backtrace from it. This doesn't affect
+any server operation, you just need to make sure the OS is configured
+to generate them.
+
+ $ ulimit -c unlimited # enable unlimited core dump size
+ ...
+ $ gdb $(which knotd) core.<KNOT_PID> # start gdb on a core dump
+ (gdb) thread apply all bt # extract backtrace from all threads
+ (gdb) q
+
+If the error is repeatable, you can run the binary in a `gdb' debugger
+or attach the debugger to the running process. The backtrace from a
+running process is generally useful when debugging problems like stuck
+process and similar.
+ $ knotc -c knot.conf start
+ $ sudo gdb --pid <KNOT_PID>
+ (gdb) continue
+ ...
+ (gdb) thread apply all bt
+ (gdb) q
+
+
+File: knot.info, Node: Debug messages, Prev: Generating backtrace, Up: Troubleshooting
+
+6.3 Debug messages
+==================
+
+* Menu:
+
+* Enabling debug messages in server::
+
+In some cases the aforementioned information may not be enough to find
+and fix the bug. In these cases it may be useful to turn on debug
+messages.
+
+Two steps are required in order to log debug messages. First you need to
+allow the debug messages in the server. Then the logging must be
+configured to log debug messages (*note log::). It is recommended to
+log these messages to a file. Firstly, the debug output may be rather
+large and secondly, it is easier to use the data for debugging.
+
+
+File: knot.info, Node: Enabling debug messages in server, Up: Debug messages
+
+6.3.1 Enabling debug messages in server
+---------------------------------------
+
+* Menu:
+
+* Debug messages Example::
+
+Allowing debug messages in the server is possible only when configuring
+the sources. Two `configure' options are required to do this:
+
+ * The `--enable-debug' option specifies the server modules for which
+ you want to enable debug messages. One or more of the following
+ modules may be listed, separated by commas:
+
+ * `server' - Messages related to networking, threads and
+ low-level journal handling.
+
+ * `zones' - All operations with zones - loading, updating,
+ saving, timers, high-level journal management.
+
+ * `xfr' - AXFR, IXFR and NOTIFY handling.
+
+ * `packet' - Packet parsing and response creation.
+
+ * `dname' - Parsing, comparing and other operations on domain
+ names.
+
+ * `rr' - Details of processed resource records.
+
+ * `ns' - Query processing, high-level handling of all requests
+ (transfers, NOTIFY, normal queries).
+
+ * `hash' - Details of hash table (the main data structure)
+ operation.
+
+ * `compiler' - Zone file compilation.
+
+ * The `--enable-debuglevel' option is used to specify the verbosity
+ of the debug output. Be careful with this, as the `details'
+ verbosity may produce really large logs (in order of GBs). There
+ are three levels of verbosity: `brief', `verbose' and `details'.
+
+
+
+File: knot.info, Node: Debug messages Example, Up: Enabling debug messages in server
+
+6.3.1.1 Example
+...............
+
+ $ ./configure --enable-debug=server,zones --enable-debuglevel=verbose
+
+
+File: knot.info, Node: Statement Index, Next: Knot DNS Configuration Reference, Prev: Troubleshooting, Up: Top
+
+Statement Index
+***************
+
+
+* Menu:
+
+* address: address. (line 6)
+* category: category. (line 6)
+* disable-any: disable-any. (line 6)
+* file: file. (line 6)
+* group_id: group_id. (line 6)
+* groups: groups. (line 6)
+* groups_remote_id: groups_remote_id. (line 6)
+* hostname: hostname. (line 6)
+* identity: identity. (line 6)
+* include: include. (line 6)
+* interface_id: interface_id. (line 6)
+* interfaces: interfaces. (line 6)
+* ixfr-from-differences: ixfr-from-differences. (line 6)
+* ixfr-fslimit: ixfr-fslimit. (line 6)
+* key: key. (line 6)
+* key_id: key_id. (line 6)
+* keys: keys. (line 6)
+* log: log. (line 6)
+* log_file: log_file. (line 6)
+* log_name: log_name. (line 6)
+* max-conn-hs: max-conn-hs. (line 6)
+* max-conn-idle: max-conn-idle. (line 6)
+* max-conn-reply: max-conn-reply. (line 6)
+* notify-in: notify-in. (line 6)
+* notify-out: notify-out. (line 6)
+* notify-retries: notify-retries. (line 6)
+* notify-timeout: notify-timeout. (line 6)
+* nsid: nsid. (line 6)
+* port: port. (line 6)
+* rate-limit: rate-limit. (line 6)
+* rate-limit-size: rate-limit-size. (line 6)
+* rate-limit-slip: rate-limit-slip. (line 6)
+* remote_id: remote_id. (line 6)
+* remotes: remotes. (line 6)
+* rundir: rundir. (line 6)
+* semantic-checks: semantic-checks. (line 6)
+* severity: severity. (line 6)
+* storage: storage. (line 6)
+* system: system. (line 6)
+* transfers: transfers. (line 6)
+* update-in: update-in. (line 6)
+* user: user. (line 6)
+* version: version. (line 6)
+* via: via. (line 6)
+* workers: workers. (line 6)
+* xfr-in: xfr-in. (line 6)
+* xfr-out: xfr-out. (line 6)
+* zone_id: zone_id. (line 6)
+* zonefile-sync: zonefile-sync. (line 6)
+
+
+File: knot.info, Node: Knot DNS Configuration Reference, Prev: Statement Index, Up: Top
+
+Appendix A Knot DNS Configuration Reference
+*******************************************
+
+This reference describes every configuration option in Knot DNS server.
+
+* Menu:
+
+* system::
+* keys::
+* interfaces::
+* remotes::
+* groups::
+* control::
+* zones::
+* log::
+* include::
+
+
+File: knot.info, Node: system, Next: keys, Up: Knot DNS Configuration Reference
+
+A.1 `system' Statement
+======================
+
+The `system' statement contains general options related to the
+operating system and other general options which do not fit anywhere
+else.
+
+* Menu:
+
+* system Syntax::
+* system Statement Definition and Usage::
+* system Example::
+
+
+File: knot.info, Node: system Syntax, Next: system Statement Definition and Usage, Up: system
+
+A.1.1 `system' Syntax
+---------------------
+
+ `system' `{'
+ [ `identity' `"'string`";' ]
+ [ `version' `"'string`";' ]
+ [ `hostname' `"'string`";' ]
+ [ `nsid' ( `"'string`"' | hex_string )`;' ]
+ [ `storage' `"'string`";' ]
+ [ `rundir' `"'string`";' ]
+ [ `workers' integer`;' ]
+ [ `user' string[`.'string]`;' ]
+ [ `max-conn-idle' ( integer | integer(`s' | `m' | `h' | `d')`;' ) ]
+ [ `max-conn-hs' ( integer | integer(`s' | `m' | `h' | `d')`;' ) ]
+ [ `max-conn-reply' ( integer | integer(`s' | `m' | `h' | `d')`;' ) ]
+ [ `transfers' integer`;' ]
+ [ `rate-limit' integer`;' ]
+ [ `rate-limit-size' integer`;' ]
+ [ `rate-limit-slip' integer`;' ]
+ `}'
+
+
+File: knot.info, Node: system Statement Definition and Usage, Next: system Example, Prev: system Syntax, Up: system
+
+A.1.2 Statement Definition and Usage
+------------------------------------
+
+* Menu:
+
+* identity::
+* version::
+* hostname::
+* nsid::
+* storage::
+* rundir::
+* workers::
+* user::
+* max-conn-idle::
+* max-conn-hs::
+* max-conn-reply::
+* transfers::
+* rate-limit::
+* rate-limit-size::
+* rate-limit-slip::
+
+
+File: knot.info, Node: identity, Next: version, Up: system Statement Definition and Usage
+
+A.1.2.1 identity
+................
+
+Identity of the server returned in a response for the query for TXT
+record `id.server.' in the CHAOS class (see RFC 4892
+(http://tools.ietf.org/html/rfc4892)).
+
+If not specified or empty, the server returns REFUSED status code.
+
+ system {
+ identity "Knot DNS";
+ }
+
+
+File: knot.info, Node: version, Next: hostname, Prev: identity, Up: system Statement Definition and Usage
+
+A.1.2.2 version
+...............
+
+Version of the server software returned in a response for the query for
+TXT record `version.server.' in the CHAOS class (see RFC 4892
+(http://tools.ietf.org/html/rfc4892)).
+
+If not specified or empty, the server returns REFUSED status code.
+
+ system {
+ version "1.3.0";
+ }
+
+
+File: knot.info, Node: hostname, Next: nsid, Prev: version, Up: system Statement Definition and Usage
+
+A.1.2.3 hostname
+................
+
+Host name of the server returned in a response for the query for TXT
+record `hostname.server.' in the CHAOS class (see RFC 4892
+(http://tools.ietf.org/html/rfc4892)).
+
+If not specified or empty, the server returns REFUSED status code.
+
+ system {
+ hostname "a.ns.example.com";
+ }
+
+
+File: knot.info, Node: nsid, Next: storage, Prev: hostname, Up: system Statement Definition and Usage
+
+A.1.2.4 nsid
+............
+
+DNS Name Server Identifier (see RFC 5001
+(http://tools.ietf.org/html/rfc5001)).
+
+Use a string format "text" or a hexstring (e.g. 0x01ab00)
+
+ system {
+ nsid 0x00cafe;
+ }
+
+
+File: knot.info, Node: storage, Next: rundir, Prev: nsid, Up: system Statement Definition and Usage
+
+A.1.2.5 storage
+...............
+
+The working directory of Knot DNS, it is used to store compiled zone
+files and other persistent data. Default: `${sharedstatedir}/knot',
+configured with `--with-storage=path'
+
+ system {
+ storage "/var/lib/knot";
+ }
+
+
+File: knot.info, Node: rundir, Next: workers, Prev: storage, Up: system Statement Definition and Usage
+
+A.1.2.6 rundir
+..............
+
+Path for storing run-time data, for example PID file and unix sockets.
+Default: `${localstatedir}/run/knot', configured with
+`--with-rundir=path'
+
+ system {
+ rundir "/var/run/knot";
+ }
+
+
+File: knot.info, Node: workers, Next: user, Prev: rundir, Up: system Statement Definition and Usage
+
+A.1.2.7 workers
+...............
+
+Number of workers (threads) per server interface. This option is used
+to force number of threads used per interface.
+
+Default value: unset (auto-estimates optimal value from the number of
+online CPUs)
+
+ system {
+ workers 16;
+ }
+
+
+File: knot.info, Node: user, Next: max-conn-idle, Prev: workers, Up: system Statement Definition and Usage
+
+A.1.2.8 user
+............
+
+System `user' or `user'.`group' under which the Knot DNS is run after
+starting and binding to interfaces. Linux capabilities (*note Required
+libraries::) are employed if supported and this configuration option is
+set.
+
+Default value: `root.root'
+
+ system {
+ user knot.knot;
+ }
+
+
+File: knot.info, Node: max-conn-idle, Next: max-conn-hs, Prev: user, Up: system Statement Definition and Usage
+
+A.1.2.9 max-conn-idle
+.....................
+
+Maximum idle time between requests on a TCP connection. This also
+limits receiving of a single query, each query must be received in this
+time limit.
+
+
+File: knot.info, Node: max-conn-hs, Next: max-conn-reply, Prev: max-conn-idle, Up: system Statement Definition and Usage
+
+A.1.2.10 max-conn-hs
+....................
+
+Maximum time between newly accepted TCP connection and first query.
+This is useful to disconnect inactive connections faster, than
+connection that already made at least 1 meaningful query.
+
+
+File: knot.info, Node: max-conn-reply, Next: transfers, Prev: max-conn-hs, Up: system Statement Definition and Usage
+
+A.1.2.11 max-conn-reply
+.......................
+
+Maximum time to wait for a reply to an issued SOA query.
+
+
+File: knot.info, Node: transfers, Next: rate-limit, Prev: max-conn-reply, Up: system Statement Definition and Usage
+
+A.1.2.12 transfers
+..................
+
+Maximum parallel transfers, including pending SOA queries. Lowest
+possible number is the number of CPUs. Default is 10.
+
+
+File: knot.info, Node: rate-limit, Next: rate-limit-size, Prev: transfers, Up: system Statement Definition and Usage
+
+A.1.2.13 rate-limit
+...................
+
+Rate limiting is based on a token bucket scheme, rate basically
+represents number of tokens available each second. Each response is
+processed and classified (based on a several discriminators, f.e.
+source netblock, qtype, name, rcode, etc.). Classified responses are
+then hashed and assigned to a bucket containing number of available
+tokens, timestamp and metadata. When available tokens are exhausted,
+response is rejected or enters SLIP (server responds with a truncated
+response). Number of available tokens is recalculated each second.
+
+Default value: `0 (disabled)'
+
+
+File: knot.info, Node: rate-limit-size, Next: rate-limit-slip, Prev: rate-limit, Up: system Statement Definition and Usage
+
+A.1.2.14 rate-limit-size
+........................
+
+Option controls the size of a hashtable of buckets. The larger the
+hashtable, the lesser probability of a hash collision, but at the
+expense of additional memory costs. Each bucket is estimated roughly to
+32B. Size should be selected as a reasonably large prime due to the
+better hash function distribution properties. Hash table is internally
+chained and works well up to a fill rate of 90%, general rule of thumb
+is to select a prime near `1.2 * maximum_qps'.
+
+Default value: `393241'
+
+
+File: knot.info, Node: rate-limit-slip, Prev: rate-limit-size, Up: system Statement Definition and Usage
+
+A.1.2.15 rate-limit-slip
+........................
+
+As attacks using DNS/UDP are usually based on a forged source address,
+an attacker could deny services to the victim netblock if all responses
+would be completely blocked. The idea behind SLIP mechanism is to send
+each Nth response as truncated, thus allowing client to reconnect via
+TCP for at least some degree of service. It is worth noting, that some
+responses can't be truncated (f.e. SERVFAIL).
+
+Default value: `2'
+
+
+File: knot.info, Node: system Example, Prev: system Statement Definition and Usage, Up: system
+
+A.1.3 system Example
+--------------------
+
+ system {
+ identity "Knot DNS 1.3.0-rc3";
+ version "1.3.0-rc3";
+ nsid "amaterasu";
+ storage "/var/lib/knot";
+ rundir "/var/run/knot";
+ workers 16;
+ user knot.knot;
+ }
+
+
+File: knot.info, Node: keys, Next: interfaces, Prev: system, Up: Knot DNS Configuration Reference
+
+A.2 `keys' Statement
+====================
+
+The `keys' statement sets up the TSIG keys used to authenticate zone
+transfers.
+
+* Menu:
+
+* keys Syntax::
+* keys Statement Definition and Usage::
+* Example::
+
+
+File: knot.info, Node: keys Syntax, Next: keys Statement Definition and Usage, Up: keys
+
+A.2.1 keys Syntax
+-----------------
+
+ keys {
+ key_id algorithm "string"; ]
+ [ key_id algorithm "string"; ... ]
+ }
+
+
+File: knot.info, Node: keys Statement Definition and Usage, Next: Example, Prev: keys Syntax, Up: keys
+
+A.2.2 Statement Definition and Usage
+------------------------------------
+
+* Menu:
+
+* key_id::
+
+
+File: knot.info, Node: key_id, Up: keys Statement Definition and Usage
+
+A.2.2.1 `key_id' Statement
+..........................
+
+The `key_id' statement defines a secret shared key for use with TSIG.
+It consists of its `name', `algorithm' and `key' contents.
+
+Supported algoritms:
+
+ * hmac-md5
+
+ * hmac-sha1
+
+ * hmac-sha224
+
+ * hmac-sha256
+
+ * hmac-sha384
+
+ * hmac-sha512
+
+You need to use bind or ldns utils to generate TSIG keys.
+Unfortunately, Knot DNS does not have any own generation utilities yet.
+
+
+ $ dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST foobar.example.com
+ Kfoobar.example.com.+163+21239
+ $ cat Kfoobar.example.com.+163+21239.key
+ foobar.example.com. ( IN KEY 512 3 163
+ rqv2WRyDgIUaHcJi03Zssor9jtG1kOpb3dPywxZfTeo= )
+
+Key generated in previous paragraph would be written as:
+
+
+ keys {
+ foobar.example.com. hmac-sha256
+ "rqv2WRyDgIUaHcJi03Zssor9jtG1kOpb3dPywxZfTeo=";
+ }
+
+
+File: knot.info, Node: Example, Prev: keys Statement Definition and Usage, Up: keys
+
+A.2.3 keys Example
+------------------
+
+
+ keys {
+ key0.server0 hmac-md5 "Wg==";
+ foobar.example.com. hmac-sha256 "RQ==";
+ }
+
+
+File: knot.info, Node: interfaces, Next: remotes, Prev: keys, Up: Knot DNS Configuration Reference
+
+A.3 interfaces
+==============
+
+The `interfaces' statement contains IP interfaces where Knot DNS
+listens for incoming queries.
+
+* Menu:
+
+* interfaces Syntax::
+* interfaces Statement Definition and Usage::
+* interfaces Examples::
+
+
+File: knot.info, Node: interfaces Syntax, Next: interfaces Statement Definition and Usage, Up: interfaces
+
+A.3.1 Syntax
+------------
+
+ `interfaces' `{'
+ interface_id
+ ( ip_address[@port_number] |
+ `{' `address' ip_address`;' [ `port' port_number`;' ] `}' )
+ [ interface_id ...`;' ...`;' ]
+ `}'
+
+
+File: knot.info, Node: interfaces Statement Definition and Usage, Next: interfaces Examples, Prev: interfaces Syntax, Up: interfaces
+
+A.3.2 Statement Definition and Usage
+------------------------------------
+
+* Menu:
+
+* interface_id::
+
+
+File: knot.info, Node: interface_id, Up: interfaces Statement Definition and Usage
+
+A.3.2.1 `interface_id'
+......................
+
+The `interface_id' is a textual identifier of an IP interface, which
+consists of an IP address and a port.
+
+The definition of an interface can be written in long or a short form
+and it always contains IP (IPv4 or IPv6) address.
+
+
+File: knot.info, Node: interfaces Examples, Prev: interfaces Statement Definition and Usage, Up: interfaces
+
+A.3.3 interfaces Examples
+-------------------------
+
+Long form:
+
+
+ interfaces {
+ my_ip {
+ address 192.0.2.1;
+ port 53;
+ }
+ }
+
+Short form:
+
+
+ interfaces {
+ my_second_ip { address 198.51.100.1@53; }
+ }
+
+Short form without port (defaults to 53):
+
+
+ interfaces {
+ my_third_ip { address 203.0.113.1; }
+ }
+
+
+File: knot.info, Node: remotes, Next: groups, Prev: interfaces, Up: Knot DNS Configuration Reference
+
+A.4 `remotes' Statement
+=======================
+
+The `remotes' statement sets up all remote servers for zone transfers.
+Knot DNS does not distinguish between client or server in this section.
+Role of the server is determined at the time of its usage in the
+`zones' section. One server may act as a client for one zone (e.g.
+downloading the updates) and as a master server for a different zone.
+
+* Menu:
+
+* remotes Syntax::
+* remotes Statement Definition and Grammar::
+* remotes Examples::
+
+
+File: knot.info, Node: remotes Syntax, Next: remotes Statement Definition and Grammar, Up: remotes
+
+A.4.1 Syntax
+------------
+
+ `remotes' `{'
+ remote_id
+ ( ip_address[`@'port_number] |
+ `{' `address' ip_address;
+ [ `port' port_number; ]
+ [ `key' key_id; ]
+ [ `via' [ interface_id | ip_address ]; ]
+ `}'
+ )
+ [ remote_id ...; ...; ]
+ `}'
+
+
+File: knot.info, Node: remotes Statement Definition and Grammar, Next: remotes Examples, Prev: remotes Syntax, Up: remotes
+
+A.4.2 Statement Definition and Grammar
+--------------------------------------
+
+* Menu:
+
+* remote_id::
+* address::
+* port::
+* key::
+* via::
+
+
+File: knot.info, Node: remote_id, Next: address, Up: remotes Statement Definition and Grammar
+
+A.4.2.1 `remote_id'
+...................
+
+`remote_id' contains a symbolic name for a remote server.
+
+
+File: knot.info, Node: address, Next: port, Prev: remote_id, Up: remotes Statement Definition and Grammar
+
+A.4.2.2 address
+...............
+
+`address' sets an IPv4 or an IPv6 address for this particular `remote'.
+
+
+File: knot.info, Node: port, Next: key, Prev: address, Up: remotes Statement Definition and Grammar
+
+A.4.2.3 port
+............
+
+`port' section contains a port number for the current `remote'. This
+section is optional with default port set to 53.
+
+
+File: knot.info, Node: key, Next: via, Prev: port, Up: remotes Statement Definition and Grammar
+
+A.4.2.4 key
+...........
+
+`key' section contains a key associated with this `remote'. This
+section is optional.
+
+
+File: knot.info, Node: via, Prev: key, Up: remotes Statement Definition and Grammar
+
+A.4.2.5 via
+...........
+
+`via' section specifies which interface will be used to communicate
+with this `remote'. This section is optional.
+
+
+File: knot.info, Node: remotes Examples, Prev: remotes Statement Definition and Grammar, Up: remotes
+
+A.4.3 remotes Examples
+----------------------
+
+
+ remotes {
+
+ # Format 1:
+ server0 {
+ address 127.0.0.1;
+ port 53531;
+ key key0.server0;
+ via ipv4; # reference to 'remotes'
+ # via 82.35.64.59; # direct IPv4
+ # via [::cafe]; # direct IPv6
+ }
+
+ # Format 2:
+ server1 {
+ address 127.0.0.1@53001;
+ }
+ }
+
+
+File: knot.info, Node: groups, Next: control, Prev: remotes, Up: Knot DNS Configuration Reference
+
+A.5 `groups' Statement
+======================
+
+The `groups' statement is used to create groups of remote machines
+defined in *note remotes:: statement. The group can substitute multiple
+machines specification anywhere in the configuration where the list of
+remotes is allowed to be used (namely `allow' in *note control::
+section and ACLs in *note zones:: section).
+
+The remotes definitions must exist prior to using them in group
+definitions. One remote can be a member of multiple groups.
+
+* Menu:
+
+* groups Syntax::
+* groups Statement Definition and Grammar::
+* groups Examples::
+
+
+File: knot.info, Node: groups Syntax, Next: groups Statement Definition and Grammar, Up: groups
+
+A.5.1 Syntax
+------------
+
+ `groups' `{'
+ group_id `{' remote_id [ `,' ... ] `}'
+ [ ... ]
+ `}'
+
+
+File: knot.info, Node: groups Statement Definition and Grammar, Next: groups Examples, Prev: groups Syntax, Up: groups
+
+A.5.2 Statement Definition and Grammar
+--------------------------------------
+
+* Menu:
+
+* group_id::
+* remote_id:groups_remote_id.
+
+
+File: knot.info, Node: group_id, Next: groups_remote_id, Up: groups Statement Definition and Grammar
+
+A.5.2.1 `group_id'
+..................
+
+`group_id' contains a symbolic name for a group of remotes.
+
+
+File: knot.info, Node: groups_remote_id, Prev: group_id, Up: groups Statement Definition and Grammar
+
+A.5.2.2 `remote_id'
+...................
+
+`remote_id' contains a symbolic name for a remote server as specified in
+*note remotes:: section.
+
+
+File: knot.info, Node: groups Examples, Prev: groups Statement Definition and Grammar, Up: groups
+
+A.5.3 Examples
+--------------
+
+ remotes {
+ ctl {
+ # ...
+ }
+ alice {
+ # ...
+ }
+ bob {
+ # ...
+ }
+ }
+
+ groups {
+ admins { alice, bob }
+ }
+
+ # example usage:
+ control {
+ # ...
+ allow ctl, admins;
+ }
+
+
+File: knot.info, Node: control, Next: zones, Prev: groups, Up: Knot DNS Configuration Reference
+
+A.6 `control' Statement
+=======================
+
+The `control' statement specifies on which interface to listen for
+remote control commands. Caution: The control protocol is not
+encrypted, and susceptible to replay attack in a short timeframe until
+message digest expires, for that reason, it is recommended to use
+default UNIX sockets.
+
+* Menu:
+
+* control Syntax::
+* control Statement Definition and Grammar::
+* control Examples::
+
+
+File: knot.info, Node: control Syntax, Next: control Statement Definition and Grammar, Up: control
+
+A.6.1 Syntax
+------------
+
+ `control' `{'
+ [ listen-on `{'
+ ( `address' ip_address[@port_number] |
+ `{' `address' ip_address`;' [ `port' port_number`;' ] `}' )
+ `}' ]
+ [ `allow' remote_id [, remote_id, ... ]`;' ]
+ `}'
+
+
+File: knot.info, Node: control Statement Definition and Grammar, Next: control Examples, Prev: control Syntax, Up: control
+
+A.6.2 Statement Definition and Grammar
+--------------------------------------
+
+Control interface `listen-on' either defines a UNIX socket or an
+IPv4/IPv6 `interface' definition as in *note interfaces::. Default
+port for IPv4/v6 control interface is `5533', however UNIX socket is
+preferred. UNIX socket address is relative to `rundir' if not
+specified as an absolute path. Without any configuration, the socket
+will be created in `rundir/knot.sock'.
+
+
+File: knot.info, Node: control Examples, Prev: control Statement Definition and Grammar, Up: control
+
+A.6.3 Examples
+--------------
+
+UNIX socket example:
+ control {
+ listen-on "/var/run/knot/knot.sock";
+ }
+
+IPv4 socket example:
+ keys {
+ knotc-key hmac-md5 "Wg==";
+ }
+ remotes {
+ ctl { address 127.0.0.1; key knotc-key; }
+ }
+ control {
+ listen-on { address 127.0.0.1; }
+ allow ctl;
+ }
+
+
+File: knot.info, Node: zones, Next: log, Prev: control, Up: Knot DNS Configuration Reference
+
+A.7 `zones' Statement
+=====================
+
+The `zones' statement contains definition of zones served by Knot DNS.
+
+* Menu:
+
+* zones Syntax::
+* zones Statement Definition and Grammar::
+* zones Example::
+* zones List of zone semantic checks::
+
+
+File: knot.info, Node: zones Syntax, Next: zones Statement Definition and Grammar, Up: zones
+
+A.7.1 Syntax
+------------
+
+ `zones' `{'
+ [ zone_options ]
+ zone_id `{'
+ `file' `"'string`";'
+ [ `xfr-in' remote_id [, remote_id, ... ]`;' ]
+ [ `xfr-out' remote_id [, remote_id, ... ]`;' ]
+ [ `notify-in' remote_id [, remote_id, ... ]`;' ]
+ [ `notify-out' remote_id [, remote_id, ... ]`;' ]
+ [ `update-in' remote_id [, remote_id, ... ]`;' ]
+ [ zone_options ]
+ `}'
+ `}'
+
+ zone_options :=
+ [ `semantic-checks' boolean`;' ]
+ [ `ixfr-from-differences' boolean`;' ]
+ [ `disable-any' boolean`;' ]
+ [ `notify-timeout' integer`;' ]
+ [ `notify-retries' integer`;' ]
+ [ `zonefile-sync' ( integer | integer(`s' | `m' | `h' | `d')`;' ) ]
+ [ `ixfr-fslimit' ( integer | integer(`k' | `M' | `G') )`;' ]
+ [ `ixfr-from-differences' boolean`;' ]
+
+
+File: knot.info, Node: zones Statement Definition and Grammar, Next: zones Example, Prev: zones Syntax, Up: zones
+
+A.7.2 Statement Definition and Grammar
+--------------------------------------
+
+* Menu:
+
+* zone_id::
+* file::
+* xfr-in::
+* xfr-out::
+* notify-in::
+* notify-out::
+* update-in::
+* semantic-checks::
+* ixfr-from-differences::
+* disable-any::
+* notify-timeout::
+* notify-retries::
+* zonefile-sync::
+* ixfr-fslimit::
+
+
+File: knot.info, Node: zone_id, Next: file, Up: zones Statement Definition and Grammar
+
+A.7.2.1 `zone_id'
+.................
+
+`zone_id' is a zone origin, and as such is a domain name that may or
+may not end with a ".". If no $ORIGIN directive is found inside actual
+zone file, this domain name will be used in place of "@". SOA record
+in the zone must have this name as its owner.
+
+
+File: knot.info, Node: file, Next: xfr-in, Prev: zone_id, Up: zones Statement Definition and Grammar
+
+A.7.2.2 file
+............
+
+The `file' statement defines a path to the zone file. You can either
+use an absolute path or a relative path. In that case, the zone file
+path will be relative to the `storage' directory (*note storage::).
+
+
+File: knot.info, Node: xfr-in, Next: xfr-out, Prev: file, Up: zones Statement Definition and Grammar
+
+A.7.2.3 xfr-in
+..............
+
+In `xfr-in' statement user specifies which remotes will be permitted to
+perform a zone transfer to update the zone. Remotes are defined in
+`remotes' section of configuration file (*note remotes::).
+
+
+File: knot.info, Node: xfr-out, Next: notify-in, Prev: xfr-in, Up: zones Statement Definition and Grammar
+
+A.7.2.4 xfr-out
+...............
+
+In `xfr-out' statement user specifies which remotes will be permitted
+to obtain zone's contents via zone transfer. Remotes are defined in
+`remotes' section of configuration file (*note remotes::).
+
+
+File: knot.info, Node: notify-in, Next: notify-out, Prev: xfr-out, Up: zones Statement Definition and Grammar
+
+A.7.2.5 notify-in
+.................
+
+`notify-in' defines which remotes will be permitted to send NOTIFY for
+this particular zone.
+
+
+File: knot.info, Node: notify-out, Next: update-in, Prev: notify-in, Up: zones Statement Definition and Grammar
+
+A.7.2.6 notify-out
+..................
+
+`notify-out' defines to which remotes will your server send NOTIFYs
+about this particular zone.
+
+
+File: knot.info, Node: update-in, Next: semantic-checks, Prev: notify-out, Up: zones Statement Definition and Grammar
+
+A.7.2.7 update-in
+.................
+
+In `update-in' statement user specifies which remotes will be permitted
+to perform a DNS UPDATE. Remotes are defined in `remotes' section of
+configuration file (*note remotes::).
+
+
+File: knot.info, Node: semantic-checks, Next: ixfr-from-differences, Prev: update-in, Up: zones Statement Definition and Grammar
+
+A.7.2.8 semantic-checks
+.......................
+
+`semantic-checks' statement turns on optional semantic checks for this
+particular zone. See *note zones List of zone semantic checks:: for
+more information.
+
+Possible values are `on' and `off'. Most checks are disabled by
+default.
+
+
+File: knot.info, Node: ixfr-from-differences, Next: disable-any, Prev: semantic-checks, Up: zones Statement Definition and Grammar
+
+A.7.2.9 ixfr-from-differences
+.............................
+
+EXPERIMENTAL: option `ixfr-from-differences' is only relevant if you
+are running Knot DNS as a master for this zone. By turning the feature
+on you tell Knot to create differences from changes you made to a zone
+file upon server reload. See *note Controlling running daemon:: for
+more information.
+
+Possible values are `on' and `off'. Disabled by default.
+
+
+File: knot.info, Node: disable-any, Next: notify-timeout, Prev: ixfr-from-differences, Up: zones Statement Definition and Grammar
+
+A.7.2.10 disable-any
+....................
+
+If you enable `disable-any', all authoritative ANY queries sent over
+UDP will be answered with an empty response and with the TC bit set.
+Use to minimize the risk of DNS replay attack. Disabled by default.
+
+
+File: knot.info, Node: notify-timeout, Next: notify-retries, Prev: disable-any, Up: zones Statement Definition and Grammar
+
+A.7.2.11 notify-timeout
+.......................
+
+`notify-timeout' in seconds specifies how long will server wait for
+NOTIFY response. Possible values are 1 to INT_MAX. By default, this
+value is set to 60 seconds.
+
+
+File: knot.info, Node: notify-retries, Next: zonefile-sync, Prev: notify-timeout, Up: zones Statement Definition and Grammar
+
+A.7.2.12 notify-retries
+.......................
+
+`notify-retries' tells the server how many times it can retry to send a
+NOTIFY. Possible values are 1 to INT_MAX and default value is 5.
+
+
+File: knot.info, Node: zonefile-sync, Next: ixfr-fslimit, Prev: notify-retries, Up: zones Statement Definition and Grammar
+
+A.7.2.13 zonefile-sync
+......................
+
+`zonefile-sync' is only relevant in a slave server scenario and only
+after receiving IXFR. It is a time in seconds after which current zone
+in memory will be synced to its file on a disk (as set in *note
+file::). Knot DNS will serve the latest zone even after restart, but
+zone file on a disk will only be synced after `zonefile-sync' time has
+expired. Possible values are 1 to INT_MAX, optionally suffixed by unit
+size (s/m/h/d) - _1s_ is one second, _1m_ one minute, _1h_ one hour and
+_1d_ one day with default value set to _1h_.
+
+
+File: knot.info, Node: ixfr-fslimit, Prev: zonefile-sync, Up: zones Statement Definition and Grammar
+
+A.7.2.14 ixfr-fslimit
+.....................
+
+`ixfr-fslimit' sets a maximum file size for zone's journal in bytes.
+Possible values are 1 to INT_MAX, with optional suffixes k, m and G.
+I.e. _1k_, _1m_ and _1G_ with default value not being set, meaning that
+journal file can grow without limitations.
+
+
+File: knot.info, Node: zones Example, Next: zones List of zone semantic checks, Prev: zones Statement Definition and Grammar, Up: zones
+
+A.7.3 zones Example
+-------------------
+
+ zones {
+
+ # Shared options for all listed zones
+ ixfr-from-differences off;
+ semantic-checks off;
+ disable-any off;
+ notify-timeout 60;
+ notify-retries 5;
+ zonefile-sync 1h;
+ ixfr-fslimit 1G;
+ example.com {
+ file "samples/example.com.zone";
+ ixfr-from-differences off; #experimental
+ disable-any off;
+ semantic-checks on;
+ notify-timeout 60;
+ notify-retries 5;
+ zonefile-sync 1h;
+ xfr-in server0;
+ xfr-out server0, server1;
+ notify-in server0;
+ notify-out server0, server1;
+ }
+ }
+
+
+File: knot.info, Node: zones List of zone semantic checks, Prev: zones Example, Up: zones
+
+A.7.4 List of zone semantic checks
+----------------------------------
+
+The `semantic-checks' statement turns on extra zone file semantic
+checks. Several checks are enabled by default and cannot be turned off.
+If an error is found using these mandatory checks, the zone file will
+not be loaded. Upon loading a zone file, occurred errors and counts of
+their occurrence will be logged to _stderr_. These checks are the
+following:
+
+ - An extra record together with CNAME record (except for RRSIG and DS)
+ - CNAME link chain length greater than 10 (including infinite cycles)
+ - DNAME and CNAME records under the same owner (RFC 2672)
+ - CNAME and DNAME wildcards pointing to themselves
+ - SOA record missing in the zone (RFC 1034)
+ - DNAME records having records under it (DNAME children) (RFC 2672)
+
+Following checks have to be turned on using `semantic-checks' and a
+zone containing following errors will be loaded even upon discovering
+an error:
+
+ - Missing NS record at the zone apex
+ - Missing glue A or AAAA records
+ - Broken or non-cyclic NSEC(3) chain
+ - Wrong NSEC(3) type bitmap
+ - Multiple NSEC records at the same node
+ - Missing NSEC records at authoritative nodes
+ - Extra record types under same name as NSEC3 record
+ (this is RFC-valid, but Knot will not serve such a zone correctly)
+ - NSEC3-unsecured delegation that is not part of Opt-out span
+ - Wrong original TTL value in NSEC3 records
+ - Wrong RDATA TTL value in RRSIG record
+ - Signer name in RRSIG RR not the same as in DNSKEY
+ - Signed RRSIG
+ - Not all RRs in node are signed
+ - Wrong key flags or wrong key in RRSIG record (not the same as ZSK)
+
+
+File: knot.info, Node: log, Next: include, Prev: zones, Up: Knot DNS Configuration Reference
+
+A.8 `log' Statement
+===================
+
+* Menu:
+
+* log Syntax::
+* log Statement Definition and Grammar::
+* log Example::
+
+
+File: knot.info, Node: log Syntax, Next: log Statement Definition and Grammar, Up: log
+
+A.8.1 Syntax
+------------
+
+ `log' `{'
+ [ log_name `{'
+ [ category severity [ severity ... ]`;' ]
+ `}' ]
+ [ `log_file' filename {
+ [ category severity [ severity ... ]`;' ]
+ } ]
+ `}'
+
+
+File: knot.info, Node: log Statement Definition and Grammar, Next: log Example, Prev: log Syntax, Up: log
+
+A.8.2 Statement Definition and Grammar
+--------------------------------------
+
+* Menu:
+
+* log_name::
+* category::
+* severity::
+* log_file::
+
+The `log' statement configures logging output of Knot DNS. You can
+configure Knot DNS to log into file or system log. There are several
+logging categories to choose from. Each log message has its severity
+and user can configure severities for each log destination.
+
+In case of missing log section, severities from `warning' and more
+serious will be logged to both `stderr' and `syslog'. The `info' and
+`notice' severities will be logged to the `stdout'.
+
+
+File: knot.info, Node: log_name, Next: category, Up: log Statement Definition and Grammar
+
+A.8.2.1 `log_name'
+..................
+
+`log_name' should be replaced with one of 3 symbolic log names :
+ * _stdout_ - logging to standard output
+
+ * _stderr_ - logging to standard error output
+
+ * _syslog_ - logging to syslog
+
+
+File: knot.info, Node: category, Next: severity, Prev: log_name, Up: log Statement Definition and Grammar
+
+A.8.2.2 `category'
+..................
+
+Knot DNS allows user to choose from these logging categories:
+
+ * _server_ - Messages related to general operation of the server.
+
+ * _zone_ - Messages related to zones, zone parsing and loading.
+
+ * _answering_ - Messages regarding query processing and response
+ creation.
+
+ * _any_ - All categories.
+
+
+File: knot.info, Node: severity, Next: log_file, Prev: category, Up: log Statement Definition and Grammar
+
+A.8.2.3 `severity'
+..................
+
+Knot DNS has the following logging severities:
+ * _debug_ - Debug messages, must be turned on at compile time (*note
+ Enabling debug messages in server::).
+
+ * _info_ - Informational message.
+
+ * _notice_ - Server notices and hints.
+
+ * _warning_ - Warnings that might require user action.
+
+ * _error_ - Recoverable error. Action should be taken.
+
+ * _all_ - All severities.
+
+More severities may be listed for each category, but all severities
+have to be listed explicitly, i.e. using _warning_ severity does not
+mean that _error_ severity messages will be logged as well.
+
+
+File: knot.info, Node: log_file, Prev: severity, Up: log Statement Definition and Grammar
+
+A.8.2.4 `log_file'
+..................
+
+`log_file' is either absolute or relative path to file user wants to
+log to. See following example for clarification.
+
+
+File: knot.info, Node: log Example, Prev: log Statement Definition and Grammar, Up: log
+
+A.8.3 log Example
+-----------------
+
+
+ log {
+
+ syslog {
+ any error;
+ zone warning, notice;
+ server info;
+ }
+
+ stderr {
+ any error, warning;
+ }
+
+ file "/tmp/knot-sample/knotd.debug" {
+ server debug;
+ }
+ }
+
+
+File: knot.info, Node: include, Prev: log, Up: Knot DNS Configuration Reference
+
+A.9 `include' Statement
+=======================
+
+The `include' statement is a special statement which can be used almost
+anywhere on any level in the configuration file. It makes inclusion of
+another file possible.
+
+The path of the included file can be either absolute or relative to a
+configuration file currently being processed.
+
+* Menu:
+
+* include Syntax::
+* include Examples::
+
+
+File: knot.info, Node: include Syntax, Next: include Examples, Up: include
+
+A.9.1 Syntax
+------------
+
+ `include' "filename"`;'
+
+
+File: knot.info, Node: include Examples, Prev: include Syntax, Up: include
+
+A.9.2 Examples
+--------------
+
+ include "keys.conf";
+
+ remotes {
+ ctl {
+ address 127.0.0.1;
+ key knotc-key;
+ }
+ include "remotes.conf";
+ }
+
+
+
+Tag Table:
+Node: Top1060
+Node: Introduction4057
+Node: What is Knot DNS4355
+Node: Knot DNS features4873
+Node: Scope of this document5894
+Node: Knot DNS Resource Requirements6156
+Node: Hardware requirements6454
+Node: CPU requirements7094
+Node: Memory requirements7479
+Node: Supported operating system8195
+Node: Knot DNS Installation8663
+Node: Required build environment8970
+Node: Required libraries9594
+Node: Userspace RCU10399
+Node: Installation from the sources11351
+Node: Configuring and generating Makefiles11936
+Node: Compilation13594
+Node: Installation14170
+Node: Installation from packages14677
+Node: Installing Knot DNS packages on Debian15201
+Node: Installing Knot DNS packages on Ubuntu16179
+Node: Adding official PPA repository for Knot DNS17093
+Node: Installing Knot DNS packages on Fedora17721
+Node: Installing Knot DNS from ports on FreeBSD19120
+Node: Knot DNS Configuration19467
+Node: Minimal configuration20038
+Node: Slave configuration22099
+Node: Master configuration24095
+Node: Configuring multiple interfaces25141
+Node: Using DNS UPDATE25626
+Node: Remote control interface27193
+Node: Enabling zone semantic checks28285
+Node: Creating IXFR differences from zone file changes28752
+Node: Using Response Rate Limiting29325
+Node: Running Knot DNS30826
+Node: Running a slave server34527
+Node: Running a master server35823
+Node: Controlling running daemon36804
+Node: Troubleshooting38255
+Node: Submitting a bugreport38663
+Node: Generating backtrace39833
+Node: Debug messages40835
+Node: Enabling debug messages in server41505
+Node: Debug messages Example43065
+Node: Statement Index43264
+Node: Knot DNS Configuration Reference47014
+Node: system47380
+Node: system Syntax47741
+Node: system Statement Definition and Usage48585
+Node: identity49006
+Node: version49416
+Node: hostname49850
+Node: nsid50288
+Node: storage50608
+Node: rundir50979
+Node: workers51320
+Node: user51704
+Node: max-conn-idle52138
+Node: max-conn-hs52453
+Node: max-conn-reply52814
+Node: transfers53045
+Node: rate-limit53330
+Node: rate-limit-size54072
+Node: rate-limit-slip54743
+Node: system Example55327
+Node: keys55692
+Node: keys Syntax55999
+Node: keys Statement Definition and Usage56228
+Node: key_id56434
+Node: Example57396
+Node: interfaces57630
+Node: interfaces Syntax57965
+Node: interfaces Statement Definition and Usage58303
+Node: interface_id58545
+Node: interfaces Examples58909
+Node: remotes59388
+Node: remotes Syntax59987
+Node: remotes Statement Definition and Grammar60426
+Node: remote_id60696
+Node: address60896
+Node: port61115
+Node: key61369
+Node: via61584
+Node: remotes Examples61814
+Node: groups62340
+Node: groups Syntax63030
+Node: groups Statement Definition and Grammar63248
+Node: group_id63506
+Node: groups_remote_id63713
+Node: groups Examples63960
+Node: control64366
+Node: control Syntax64903
+Node: control Statement Definition and Grammar65271
+Node: control Examples65854
+Node: zones66336
+Node: zones Syntax66680
+Node: zones Statement Definition and Grammar67640
+Node: zone_id68072
+Node: file68460
+Node: xfr-in68804
+Node: xfr-out69143
+Node: notify-in69488
+Node: notify-out69736
+Node: update-in69991
+Node: semantic-checks70334
+Node: ixfr-from-differences70753
+Node: disable-any71310
+Node: notify-timeout71697
+Node: notify-retries72042
+Node: zonefile-sync72361
+Node: ixfr-fslimit73071
+Node: zones Example73477
+Node: zones List of zone semantic checks74299
+Node: log76099
+Node: log Syntax76322
+Node: log Statement Definition and Grammar76646
+Node: log_name77356
+Node: category77685
+Node: severity78152
+Node: log_file78894
+Node: log Example79149
+Node: include79532
+Node: include Syntax80001
+Node: include Examples80139
+
+End Tag Table
+
+
+Local Variables:
+coding: utf-8
+End:
diff --git a/doc/knot.texi b/doc/knot.texi
index 04e81b5..f4eaa56 100644
--- a/doc/knot.texi
+++ b/doc/knot.texi
@@ -1,7 +1,7 @@
\input texinfo @c -*-texinfo-*-
@setfilename knot.info
@include version.texi
-@documentencoding utf-8
+@documentencoding UTF-8
@settitle Knot DNS @value{VERSION}
@paragraphindent 0
@@ -43,6 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
@author Lubos Slovak (@email{lubos.slovak@@nic.cz})
@author Ondrej Sury (@email{ondrej@@sury.org})
@author Marek Vavrusa (@email{marek.vavrusa@@nic.cz})
+@author Jan Vcelak (@email{jan.vcelak@@nic.cz})
@page
@vskip 0pt plus 1filll
@insertcopying
@@ -58,71 +59,71 @@ This manual is for Knot DNS (version @value{VERSION}, @value{UPDATED}).
@end ifnottex
@menu
-* Introduction::
-* Knot DNS Resource Requirements::
-* Knot DNS Installation::
-* Knot DNS Configuration::
-* Running Knot DNS::
-* Troubleshooting::
-* Statement Index::
-* Knot DNS Configuration Reference::
+* Introduction::
+* Knot DNS Resource Requirements::
+* Knot DNS Installation::
+* Knot DNS Configuration::
+* Running Knot DNS::
+* Troubleshooting::
+* Statement Index::
+* Knot DNS Configuration Reference::
@detailmenu
--- The Detailed Node Listing ---
Introduction
-* What is Knot DNS::
+* What is Knot DNS::
* Knot DNS features::
-* Scope of this document::
+* Scope of this document::
Knot DNS Resource Requirements
-* Hardware requirements::
-* CPU requirements::
-* Memory requirements::
-* Supported operating system::
+* Hardware requirements::
+* CPU requirements::
+* Memory requirements::
+* Supported operating system::
Knot DNS Installation
-* Required build environment::
-* Required libraries::
-* Installation from the sources::
-* Installation from packages::
+* Required build environment::
+* Required libraries::
+* Installation from the sources::
+* Installation from packages::
Required libraries
-* Userspace RCU::
+* Userspace RCU::
Installation from the sources
-* Configuring and generating Makefiles::
-* Compilation::
-* Installation::
+* Configuring and generating Makefiles::
+* Compilation::
+* Installation::
Installation from packages
-* Installing Knot DNS packages on Debian::
-* Installing Knot DNS packages on Ubuntu::
-* Installing Knot DNS RPMs on Fedora::
-* Installing Knot DNS from ports on FreeBSD::
+* Installing Knot DNS packages on Debian::
+* Installing Knot DNS packages on Ubuntu::
+* Installing Knot DNS packages on Fedora::
+* Installing Knot DNS from ports on FreeBSD::
Installing Knot DNS packages on Ubuntu
-* Adding official PPA repository for Knot DNS::
+* Adding official PPA repository for Knot DNS::
Knot DNS Configuration
-* Minimal configuration::
-* Slave configuration::
-* Master configuration::
-* Configuring multiple interfaces::
+* Minimal configuration::
+* Slave configuration::
+* Master configuration::
+* Configuring multiple interfaces::
Sample Configurations
-* Minimal configuration::
-* Slave configuration::
-* Master configuration::
+* Minimal configuration::
+* Slave configuration::
+* Master configuration::
* Configuring multiple interfaces::
* Enabling zone semantic checks::
* Creating IXFR differences from zone file changes::
@@ -136,8 +137,8 @@ Running Knot DNS
Troubleshooting
* Submitting a bugreport::
-* Generating backtrace::
-* Debug messages::
+* Generating backtrace::
+* Debug messages::
Debug messages
@@ -149,28 +150,30 @@ Enabling debug messages in server
Knot DNS Configuration Reference
-* system::
-* keys::
-* interfaces::
-* remotes::
-* zones::
-* log::
+* system::
+* keys::
+* interfaces::
+* remotes::
+* groups::
+* zones::
+* log::
+* include::
@code{system} Statement
-* system Syntax::
-* system Statement Definition and Usage::
-* system Example::
+* system Syntax::
+* system Statement Definition and Usage::
+* system Example::
Statement Definition and Usage
-* identity::
-* version::
-* nsid::
-* storage::
-* pidfile::
-* workers::
-* user::
+* identity::
+* version::
+* nsid::
+* storage::
+* rundir::
+* workers::
+* user::
* max-conn-idle::
* max-conn-hs::
* max-conn-reply::
@@ -180,39 +183,48 @@ Statement Definition and Usage
@code{keys} Statement
-* keys Syntax::
-* keys Statement Definition and Usage::
-* Example::
+* keys Syntax::
+* keys Statement Definition and Usage::
+* Example::
Statement Definition and Usage
-* key_id::
+* key_id::
interfaces
-* interfaces Syntax::
-* interfaces Statement Definition and Usage::
-* interfaces Examples::
+* interfaces Syntax::
+* interfaces Statement Definition and Usage::
+* interfaces Examples::
Statement Definition and Usage
-* interface_id::
+* interface_id::
@code{remotes} Statement
-* remotes Syntax::
-* remotes Statement Definition and Grammar::
+* remotes Syntax::
+* remotes Statement Definition and Grammar::
+
+@code{groups} Statement
+
+* groups Syntax::
+* groups Statement Definition and Grammar::
@code{zones} Statement
-* zones Syntax::
+* zones Syntax::
* zones Statement Definition and Grammar::
* zones List of zone semantic checks::
@code{log} Statement
-* log Syntax::
-* log Statement Definition and Grammar::
+* log Syntax::
+* log Statement Definition and Grammar::
+
+@code{include} Statement
+
+* include Syntax::
@end detailmenu
@end menu
diff --git a/doc/mdate-sh b/doc/mdate-sh
index 4614441..60dc485 100755
--- a/doc/mdate-sh
+++ b/doc/mdate-sh
@@ -3,7 +3,8 @@
scriptversion=2010-08-21.06; # UTC
-# Copyright (C) 1995-2012 Free Software Foundation, Inc.
+# Copyright (C) 1995, 1996, 1997, 2003, 2004, 2005, 2007, 2009, 2010
+# Free Software Foundation, Inc.
# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
#
# This program is free software; you can redistribute it and/or modify
@@ -39,7 +40,7 @@ fi
case $1 in
'')
- echo "$0: No file. Try '$0 --help' for more information." 1>&2
+ echo "$0: No file. Try \`$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
@@ -75,7 +76,7 @@ LC_TIME=C
export LC_TIME
# GNU ls changes its time format in response to the TIME_STYLE
-# variable. Since we cannot assume 'unset' works, revert this
+# variable. Since we cannot assume `unset' works, revert this
# variable to its documented default.
if test "${TIME_STYLE+set}" = set; then
TIME_STYLE=posix-long-iso
@@ -95,14 +96,14 @@ if ls -n /dev/null 1>/dev/null 2>&1; then
ls_command="$ls_command -n"
fi
-# A 'ls -l' line looks as follows on OS/2.
+# A `ls -l' line looks as follows on OS/2.
# drwxrwx--- 0 Aug 11 2001 foo
# This differs from Unix, which adds ownership information.
# drwxrwx--- 2 root root 4096 Aug 11 2001 foo
#
# To find the date, we split the line on spaces and iterate on words
# until we find a month. This cannot work with files whose owner is a
-# user named "Jan", or "Feb", etc. However, it's unlikely that '/'
+# user named `Jan', or `Feb', etc. However, it's unlikely that `/'
# will be owned by a user whose name is a month. So we first look at
# the extended ls output of the root directory to decide how many
# words should be skipped to get the date.
@@ -115,7 +116,7 @@ month=
command=
until test $month
do
- test $# -gt 0 || error "failed parsing '$ls_command /' output"
+ test $# -gt 0 || error "failed parsing \`$ls_command /' output"
shift
# Add another shift to the command.
command="$command shift;"
@@ -135,7 +136,7 @@ do
esac
done
-test -n "$month" || error "failed parsing '$ls_command /' output"
+test -n "$month" || error "failed parsing \`$ls_command /' output"
# Get the extended ls output of the file or directory.
set dummy x`eval "$ls_command \"\\\$save_arg1\""`
diff --git a/doc/migration.texi b/doc/migration.texi
index 9d4e0fa..f6a4933 100644
--- a/doc/migration.texi
+++ b/doc/migration.texi
@@ -2,10 +2,10 @@
@appendix Migration for other DNS servers
@menu
-* Knot DNS for BIND users::
-* Knot DNS for NSD users::
-* Knot DNS for PowerDNS users::
-* Knot DNS for djbdns users::
+* Knot DNS for BIND users::
+* Knot DNS for NSD users::
+* Knot DNS for PowerDNS users::
+* Knot DNS for djbdns users::
@end menu
@node Knot DNS for BIND users
diff --git a/doc/reference.texi b/doc/reference.texi
index bb2bf39..57324b7 100644
--- a/doc/reference.texi
+++ b/doc/reference.texi
@@ -4,13 +4,15 @@
This reference describes every configuration option in Knot DNS server.
@menu
-* system::
-* keys::
-* interfaces::
-* remotes::
+* system::
+* keys::
+* interfaces::
+* remotes::
+* groups::
* control::
-* zones::
-* log::
+* zones::
+* log::
+* include::
@end menu
@node system
@@ -22,9 +24,9 @@ operating system and other general options which do not fit anywhere
else.
@menu
-* system Syntax::
-* system Statement Definition and Usage::
-* system Example::
+* system Syntax::
+* system Statement Definition and Usage::
+* system Example::
@end menu
@node system Syntax
@@ -34,16 +36,18 @@ else.
@code{system} @code{@{}
[ @code{identity} @code{"}@kbd{string}@code{";} ]
[ @code{version} @code{"}@kbd{string}@code{";} ]
+ [ @code{hostname} @code{"}@kbd{string}@code{";} ]
[ @code{nsid} ( @code{"}@kbd{string}@code{"} | @kbd{hex_string} )@code{;} ]
[ @code{storage} @code{"}@kbd{string}@code{";} ]
- [ @code{pidfile} @code{"}@kbd{string}@code{";} ]
+ [ @code{rundir} @code{"}@kbd{string}@code{";} ]
[ @code{workers} @kbd{integer}@code{;} ]
[ @code{user} @kbd{string}[@code{.}@kbd{string}]@code{;} ]
[ @code{max-conn-idle} ( @kbd{integer} | @kbd{integer}(@code{s} | @code{m} | @code{h} | @code{d})@code{;} ) ]
[ @code{max-conn-hs} ( @kbd{integer} | @kbd{integer}(@code{s} | @code{m} | @code{h} | @code{d})@code{;} ) ]
[ @code{max-conn-reply} ( @kbd{integer} | @kbd{integer}(@code{s} | @code{m} | @code{h} | @code{d})@code{;} ) ]
+ [ @code{transfers} @kbd{integer}@code{;} ]
[ @code{rate-limit} @kbd{integer}@code{;} ]
- [ @code{rate-limit-size} ( @kbd{integer} | @kbd{integer}(@code{s} | @code{m} | @code{h} | @code{d})@code{;} ) ]
+ [ @code{rate-limit-size} @kbd{integer}@code{;} ]
[ @code{rate-limit-slip} @kbd{integer}@code{;} ]
@code{@}}
@end example
@@ -52,16 +56,18 @@ else.
@subsection Statement Definition and Usage
@menu
-* identity::
-* version::
-* nsid::
-* storage::
-* pidfile::
-* workers::
-* user::
-* max-conn-idle::
-* max-conn-hs::
-* max-conn-reply::
+* identity::
+* version::
+* hostname::
+* nsid::
+* storage::
+* rundir::
+* workers::
+* user::
+* max-conn-idle::
+* max-conn-hs::
+* max-conn-reply::
+* transfers::
* rate-limit::
* rate-limit-size::
* rate-limit-slip::
@@ -71,7 +77,11 @@ else.
@subsubsection identity
@vindex identity
-Identity of the server (see @url{http://tools.ietf.org/html/rfc4892,RFC 4892}). Not used yet.
+Identity of the server returned in a response for the query for TXT record
+@code{id.server.} in the CHAOS class
+(see @url{http://tools.ietf.org/html/rfc4892,RFC 4892}).
+
+If not specified or empty, the server returns REFUSED status code.
@example
system @{
@@ -83,11 +93,31 @@ system @{
@subsubsection version
@vindex version
-Version of the server (see @url{http://tools.ietf.org/html/rfc4892,RFC 4892}). Not used yet.
+Version of the server software returned in a response for the query for TXT
+record @code{version.server.} in the CHAOS class
+(see @url{http://tools.ietf.org/html/rfc4892,RFC 4892}).
+
+If not specified or empty, the server returns REFUSED status code.
@example
system @{
- version "1.1.0";
+ version "1.3.0";
+@}
+@end example
+
+@node hostname
+@subsubsection hostname
+@vindex hostname
+
+Host name of the server returned in a response for the query for TXT record
+@code{hostname.server.} in the CHAOS class
+(see @url{http://tools.ietf.org/html/rfc4892,RFC 4892}).
+
+If not specified or empty, the server returns REFUSED status code.
+
+@example
+system @{
+ hostname "a.ns.example.com";
@}
@end example
@@ -109,7 +139,9 @@ system @{
@subsubsection storage
@vindex storage
-The working directory of Knot DNS, it is used to store compiled zone files and it is also a default location of the PID file.
+The working directory of Knot DNS, it is used to store compiled zone files and
+other persistent data.
+Default: @file{$@{sharedstatedir@}/knot}, configured with @code{--with-storage=path}
@example
system @{
@@ -117,17 +149,16 @@ system @{
@}
@end example
-@node pidfile
-@subsubsection pidfile
-@vindex pidfile
-
-Specifies a custom PID file location.
+@node rundir
+@subsubsection rundir
+@vindex rundir
-Default value: @file{knot.pid} in @code{storage} directory.
+Path for storing run-time data, for example PID file and unix sockets.
+Default: @file{$@{localstatedir@}/run/knot}, configured with @code{--with-rundir=path}
@example
system @{
- pidfile "/var/run/knot.pid";
+ rundir "/var/run/knot";
@}
@end example
@@ -184,6 +215,14 @@ that already made at least 1 meaningful query.
Maximum time to wait for a reply to an issued SOA query.
+@node transfers
+@subsubsection transfers
+@vindex transfers
+
+Maximum parallel transfers, including pending SOA queries.
+Lowest possible number is the number of CPUs.
+Default is 10.
+
@node rate-limit
@subsubsection rate-limit
@vindex rate-limit
@@ -227,7 +266,7 @@ system @{
version "@value{VERSION}";
nsid "amaterasu";
storage "/var/lib/knot";
- pidfile "/var/run/knot.pid";
+ rundir "/var/run/knot";
workers 16;
user knot.knot;
@}
@@ -241,9 +280,9 @@ The @code{keys} statement sets up the TSIG keys used to authenticate
zone transfers.
@menu
-* keys Syntax::
-* keys Statement Definition and Usage::
-* Example::
+* keys Syntax::
+* keys Statement Definition and Usage::
+* Example::
@end menu
@node keys Syntax
@@ -260,7 +299,7 @@ keys @{
@subsection Statement Definition and Usage
@menu
-* key_id::
+* key_id::
@end menu
@node key_id
@@ -293,10 +332,10 @@ You need to use bind or ldns utils to generate TSIG keys. Unfortunately, Knot DN
$ dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST foobar.example.com
Kfoobar.example.com.+163+21239
-$ cat Kfoobar.example.com.+163+21239.key
+$ cat Kfoobar.example.com.+163+21239.key
foobar.example.com. ( IN KEY 512 3 163
rqv2WRyDgIUaHcJi03Zssor9jtG1kOpb3dPywxZfTeo= )
-
+
@end example
Key generated in previous paragraph would be written as:
@@ -307,7 +346,7 @@ keys @{
foobar.example.com. hmac-sha256
"rqv2WRyDgIUaHcJi03Zssor9jtG1kOpb3dPywxZfTeo=";
@}
-
+
@end example
@node Example
@@ -320,7 +359,7 @@ keys @{
key0.server0 hmac-md5 "Wg==";
foobar.example.com. hmac-sha256 "RQ==";
@}
-
+
@end example
@node interfaces
@@ -330,9 +369,9 @@ keys @{
The @code{interfaces} statement contains IP interfaces where Knot DNS listens for incoming queries.
@menu
-* interfaces Syntax::
-* interfaces Statement Definition and Usage::
-* interfaces Examples::
+* interfaces Syntax::
+* interfaces Statement Definition and Usage::
+* interfaces Examples::
@end menu
@node interfaces Syntax
@@ -351,7 +390,7 @@ The @code{interfaces} statement contains IP interfaces where Knot DNS listens fo
@subsection Statement Definition and Usage
@menu
-* interface_id::
+* interface_id::
@end menu
@node interface_id
@@ -377,7 +416,7 @@ interfaces @{
port 53;
@}
@}
-
+
@end example
Short form:
@@ -387,7 +426,7 @@ Short form:
interfaces @{
my_second_ip @{ address 198.51.100.1@@53; @}
@}
-
+
@end example
Short form without port (defaults to 53):
@@ -397,7 +436,7 @@ Short form without port (defaults to 53):
interfaces @{
my_third_ip @{ address 203.0.113.1; @}
@}
-
+
@end example
@node remotes
@@ -412,8 +451,8 @@ client for one zone (e.g. downloading the updates) and as a master
server for a different zone.
@menu
-* remotes Syntax::
-* remotes Statement Definition and Grammar::
+* remotes Syntax::
+* remotes Statement Definition and Grammar::
* remotes Examples::
@end menu
@@ -484,9 +523,9 @@ server for a different zone.
remotes @{
# Format 1:
- server0 @{
- address 127.0.0.1;
- port 53531;
+ server0 @{
+ address 127.0.0.1;
+ port 53531;
key key0.server0;
via ipv4; # reference to 'remotes'
# via 82.35.64.59; # direct IPv4
@@ -501,18 +540,94 @@ remotes @{
@end example
-@node control
+@node groups
+@section @code{groups} Statement
+@stindex groups
+
+The @code{groups} statement is used to create groups of remote machines defined
+in @ref{remotes} statement. The group can substitute multiple machines
+specification anywhere in the configuration where the list of remotes is
+allowed to be used (namely @code{allow} in @ref{control} section and ACLs in
+@ref{zones} section).
+
+The remotes definitions must exist prior to using them in group definitions.
+One remote can be a member of multiple groups.
+
+@menu
+* groups Syntax::
+* groups Statement Definition and Grammar::
+* groups Examples::
+@end menu
+
+@node groups Syntax
+@subsection Syntax
+
+@example
+@code{groups} @code{@{}
+ @kbd{group_id} @code{@{} @kbd{remote_id} [ @code{,} @kbd{...} ] @code{@}}
+ [ @kbd{...} ]
+@code{@}}
+@end example
+
+@node groups Statement Definition and Grammar
+@subsection Statement Definition and Grammar
+
+@menu
+* group_id::
+* remote_id:groups_remote_id.
+@end menu
+
+@node group_id
+@subsubsection @kbd{group_id}
+@vindex group_id
+
+@kbd{group_id} contains a symbolic name for a group of remotes.
+
+@node groups_remote_id
+@subsubsection @kbd{remote_id}
+@vindex groups_remote_id
+
+@kbd{remote_id} contains a symbolic name for a remote server as specified in
+@ref{remotes} section.
+
+@node groups Examples
+@subsection Examples
+
+@example
+remotes @{
+ ctl @{
+ # ...
+ @}
+ alice @{
+ # ...
+ @}
+ bob @{
+ # ...
+ @}
+@}
+
+groups @{
+ admins @{ alice, bob @}
+@}
+
+# example usage:
+control @{
+ # ...
+ allow ctl, admins;
+@}
+@end example
+
+@node control
@section @code{control} Statement
The @code{control} statement specifies on which interface to listen for remote control commands.
Caution: The control protocol is not encrypted,
and susceptible to replay attack in a short timeframe until message digest expires,
-for that reason, it is recommended to enable remote control only on private networks
-or loopback.
+for that reason, it is recommended to use default UNIX sockets.
@menu
-* control Syntax::
-* control Statement Definition and Grammar::
+* control Syntax::
+* control Statement Definition and Grammar::
* control Examples::
@end menu
@@ -532,12 +647,24 @@ or loopback.
@node control Statement Definition and Grammar
@subsection Statement Definition and Grammar
-Control interface @code{listen-on} definition is equal to @code{interface} definition in @ref{interfaces}.
-Default port for control interface is @code{5553}.
+Control interface @code{listen-on} either defines a UNIX socket or an
+IPv4/IPv6 @code{interface} definition as in @ref{interfaces}.
+Default port for IPv4/v6 control interface is @code{5533},
+however UNIX socket is preferred.
+UNIX socket address is relative to @code{rundir} if not specified as an absolute
+path. Without any configuration, the socket will be created in @code{rundir/knot.sock}.
@node control Examples
@subsection Examples
+UNIX socket example:
+@example
+control @{
+ listen-on "/var/run/knot/knot.sock";
+@}
+@end example
+
+IPv4 socket example:
@example
keys @{
knotc-key hmac-md5 "Wg==";
@@ -558,10 +685,10 @@ control @{
The @code{zones} statement contains definition of zones served by Knot DNS.
@menu
-* zones Syntax::
+* zones Syntax::
* zones Statement Definition and Grammar::
* zones Example::
-* zones List of zone semantic checks::
+* zones List of zone semantic checks::
@end menu
@node zones Syntax
@@ -598,18 +725,18 @@ The @code{zones} statement contains definition of zones served by Knot DNS.
@menu
* zone_id::
* file::
-* xfr-in::
-* xfr-out::
-* notify-in::
-* notify-out::
+* xfr-in::
+* xfr-out::
+* notify-in::
+* notify-out::
* update-in::
-* semantic-checks::
+* semantic-checks::
* ixfr-from-differences::
-* disable-any::
-* notify-timeout::
-* notify-retries::
-* zonefile-sync::
-* ixfr-fslimit::
+* disable-any::
+* notify-timeout::
+* notify-retries::
+* zonefile-sync::
+* ixfr-fslimit::
@end menu
@node zone_id
@@ -663,7 +790,7 @@ Remotes are defined in @code{remotes} section of configuration file (@pxref{remo
@node semantic-checks
@subsubsection semantic-checks
-@vindex semantic-checks
+@vindex semantic-checks
@code{semantic-checks} statement turns on optional semantic checks for this particular zone.
See @ref{zones List of zone semantic checks} for more information.
@@ -677,7 +804,7 @@ Most checks are disabled by default.
EXPERIMENTAL: option @code{ixfr-from-differences} is only relevant if you are running Knot DNS as a master for this zone.
By turning the feature on you tell Knot to create differences from changes you made to a zone file upon server reload.
-See @ref{Controlling running daemon} for more information.
+See @ref{Controlling running daemon} for more information.
Possible values are @code{on} and @code{off}. Disabled by default.
@@ -699,7 +826,7 @@ By default, this value is set to 60 seconds.
@subsubsection notify-retries
@vindex notify-retries
-@code{notify-retries} tells the server how many times it can retry to send a NOTIFY. Possible values
+@code{notify-retries} tells the server how many times it can retry to send a NOTIFY. Possible values
are 1 to INT_MAX and default value is 5.
@node zonefile-sync
@@ -747,7 +874,7 @@ zones @{
@end group
@end example
-@node zones List of zone semantic checks
+@node zones List of zone semantic checks
@subsection List of zone semantic checks
The @code{semantic-checks} statement turns on extra zone file semantic
@@ -767,7 +894,7 @@ These checks are the following:
@end example
Following checks have to be turned on using @code{semantic-checks} and
-a zone containing following errors will be
+a zone containing following errors will be
loaded even upon discovering an error:
@example
@@ -793,7 +920,7 @@ loaded even upon discovering an error:
@stindex log
@menu
-* log Syntax::
+* log Syntax::
* log Statement Definition and Grammar::
* log Example::
@end menu
@@ -807,7 +934,7 @@ loaded even upon discovering an error:
[ @kbd{category} @kbd{severity} [ @kbd{severity} @dots{} ]@code{;} ]
@code{@}} ]
[ @code{log_file} @kbd{filename} @{
- [ @kbd{category} @kbd{severity} [ @kbd{severity} @dots{} ]@code{;} ]
+ [ @kbd{category} @kbd{severity} [ @kbd{severity} @dots{} ]@code{;} ]
@} ]
@code{@}}
@@ -904,3 +1031,40 @@ log @{
@end example
+@node include
+@section @code{include} Statement
+@stindex include
+
+The @code{include} statement is a special statement which can be used almost
+anywhere on any level in the configuration file. It makes inclusion of another
+file possible.
+
+The path of the included file can be either absolute or relative to a
+configuration file currently being processed.
+
+@menu
+* include Syntax::
+* include Examples::
+@end menu
+
+@node include Syntax
+@subsection Syntax
+
+@example
+@code{include} "filename"@code{;}
+@end example
+
+@node include Examples
+@subsection Examples
+
+@example
+include "keys.conf";
+
+remotes @{
+ ctl @{
+ address 127.0.0.1;
+ key knotc-key;
+ @}
+ include "remotes.conf";
+@}
+@end example
diff --git a/doc/requirements.texi b/doc/requirements.texi
index 136f3c6..6bebf04 100644
--- a/doc/requirements.texi
+++ b/doc/requirements.texi
@@ -2,10 +2,10 @@
@chapter Knot DNS Resource Requirements
@menu
-* Hardware requirements::
-* CPU requirements::
-* Memory requirements::
-* Supported operating system::
+* Hardware requirements::
+* CPU requirements::
+* Memory requirements::
+* Supported operating system::
@end menu
@node Hardware requirements
diff --git a/doc/running.texi b/doc/running.texi
index bee48f3..aa5b93c 100644
--- a/doc/running.texi
+++ b/doc/running.texi
@@ -2,90 +2,85 @@
@chapter Running Knot DNS
@menu
-* Running a slave server::
-* Running a master server::
-* Controlling running daemon::
+* Running a slave server::
+* Running a master server::
+* Controlling running daemon::
@end menu
-Knot DNS is designed to compile zone files before loading them into server.
-The reason for this is to speed up server startup, but requires a bit of user
-effort, so each time the zone file changes you need to compile it.
+Knot DNS can run either in the foreground or in a background, with the @code{-d}
+option. When run in foreground, it doesn't create a PID file. Other than that,
+there are no differences and you can control it just the same way.
@example
-$ knotc -c knot.conf compile
+Usage: knotd [parameters]
+
+Parameters:
+ -c, --config [file] Select configuration file.
+ -d, --daemonize Run server as a daemon.
+ -v, --verbose Verbose mode - additional runtime information.
+ -V, --version Print version of the server.
+ -h, --help Print help and usage.
@end example
-Knot DNS automatically compiles zones on some actions (@code{start|restart}).
+
+Use knotc tool for convenience when working with the server daemon.
+As of Knot DNS 1.3.0, the zones are not compiled anymore. That makes working
+with the server much more user friendly.
@example
-$ knotc -c knot.conf start|reload|restart
+$ knotc -c knot.conf reload|restart
@end example
The tool @code{knotc} is designed as a front-end for user, making it easier
-to do everything from zone compilation to controlling the server daemon.
+to do everything from server startup to state checking of a running server daemon.
If you want to control the daemon directly, use @code{SIGINT} to quit the process or @code{SIGHUP} to reload configuration.
@example
Usage: knotc [parameters] <action> [action_args]
Parameters:
- -c [file], --config=[file] Select configuration file.
- -j [num], --jobs=[num] Number of parallel tasks to run when compiling.
- -s [server] Remote server address (default 127.0.0.1)
- -p [port] Remote server port (default 5553)
- -y [hmac:]name:key] Use key_id specified on the command line.
- -k [file] Use key file (as in config section 'keys').
- f.e. echo "knotc-key hmac-md5 Wg==" > knotc.key
- -f, --force Force operation - override some checks.
- -v, --verbose Verbose mode - additional runtime information.
- -V, --version Print knot server version.
- -w, --wait Wait for the server to finish start/stop operations.
- -i, --interactive Interactive mode (do not daemonize).
- -h, --help Print help and usage.
+ -c [file], --config=[file] Select configuration file.
+ -s [server] Remote UNIX socket/IP address (default $@{rundir@}/knot.sock).
+ -p [port] Remote server port (only for IP).
+ -y [[hmac:]name:key] Use key_id specified on the command line.
+ -k [file] Use key file (as in config section 'keys').
+ Example:
+ echo "knotc-key hmac-md5 Wg==" > knotc.key
+ -f, --force Force operation - override some checks.
+ -v, --verbose Verbose mode - additional runtime
+ information.
+ -V, --version Print knot server version.
+ -w, --wait Wait for the server to finish start/stop
+ operations.
+ -i, --interactive Interactive mode (do not daemonize).
+ -h, --help Print help and usage.
Actions:
- start Start server (no-op if running).
- stop Stop server (no-op if running).
- restart Restarts server (no-op if running).
- reload Reloads configuration and changed zones.
- refresh Refresh slave zones (all if not specified).
- flush Flush journal and update zone files.
- status Check if server is running.
- zonestatus Show status of configured zones.
- checkconf Check server configuration.
- checkzone Check specified zone files.
- compile Compile zone files (all if not specified).
-@end example
-
-If you want to run Knot DNS daemon directly, you can use @code{knotd} binary
-to do that. It accepts just configuration file and option to run in background.
-@example
-Usage: knotd [parameters]
-
-Parameters:
- -c, --config [file] Select configuration file.
- -d, --daemonize Run server as a daemon.
- -v, --verbose Verbose mode - additional runtime information.
- -V, --version Print version of the server.
- -h, --help Print help and usage.
+ start Start server (if not running).
+ stop Stop server.
+ restart Restart server.
+ reload Reload configuration and changed zones.
+ refresh [zone] Refresh slave zone (all if not specified).
+ flush Flush journal and update zone files.
+ status Check if server is running.
+ zonestatus Show status of configured zones.
+ checkconf Check current server configuration.
+ checkzone [zone] Check zone (all if not specified).
+ memstats [zone] Estimate memory consumption for zone (all if not specified).
@end example
Also, the server needs to create several files in order to run properly.
-All files are placed in the directory described by @code{storage} (@pxref{storage}).
-PID file can be placed elsewhere using the @code{pidfile} statement (@pxref{pidfile}).
-Slave zones with relative path specified will be placed in the @code{storage} as well.
+Zones and related data are stored in the directory described by @code{storage} (@pxref{storage}).
@itemize @bullet
@item
-@emph{Compiled zones} - preprocessed zones, for example zone @code{example.com} will be
-placed in @file{STORAGE/example.com.db}.
-@item
@emph{Journal files} - each zone has a journal file to store differences for IXFR and
dynamic updates. Journal for zone @code{example.com} will be
placed in @file{STORAGE/example.com.diff.db}.
+
@item
-@emph{PID file} - unless specified differently by the @code{pidfile}, it will be placed
-in the @file{STORAGE/knot.pid}.
+@emph{PID file} - is created automatically in @code{rundir} (@pxref{rundir}) when
+the server is run in background.
+
@item
-@emph{Checksum files} - in order to identify compiled zone corruption, it
-has a separate checksum file. For @code{example.com} will be
-placed in @file{STORAGE/example.com.db.crc}.
+@emph{Control sockets} - as a default, UNIX sockets are created in @code{rundir} (@pxref{rundir}),
+but can be overriden.
@end itemize
@node Running a slave server
@@ -93,29 +88,26 @@ placed in @file{STORAGE/example.com.db.crc}.
Running the server as a slave is very straightforward as you usually bootstrap
zones over AXFR and thus avoid any manual zone compilation.
-When a zone is transferred over AXFR, both the compiled zone and the zone file is
-updated, so no further compilation is needed.
-However when IXFR transfer finishes, it stores the differences in a journal file
-and doesn't update the zone file nor compiled zone immediately,
-but there is a timer that checks periodically for new differences and
-updates both zone file and the compiled zone. You can configure this timer
+In contrast to AXFR, when the incremental transfer finishes, it stores the differences in a journal file
+and doesn't update the zone file immediately.
+There is a timer that checks periodically for new differences and
+updates the zone file. You can configure this timer
with the @code{zonefile-sync} statement in @code{zones} (@pxref{zones}).
-There are two ways to start the server - directly or with the @code{knotc} controller tool.
-First, let us start it directly. If you do not pass any configuration, it will try to
+There are two ways to start the server - in foreground or background.
+First, let's start in foreground. If you do not pass any configuration, it will try to
search configuration in default path that is @code{SYSCONFDIR/knot.conf}. The @code{SYSCONFDIR}
depends on what you passed to the @code{./configure}, usually @code{/etc}.
@example
-$ knotc -c slave.conf checkconf # check configuration
$ knotd -c slave.conf
@end example
-However to start it as a daemon, @code{knotc} tool should be used.
-The @code{knotc} tool accepts parameter @code{-w} to wait until the requested operation finishes.
-When the action is "start" for example, it waits until the server starts to serve zones.
+To start it as a daemon, just add a @code{-d} parameter. Unlike the foreground mode,
+PID file will be created in @code{rundir} directory.
+
@example
-$ knotc -w -c slave.conf start # start the daemon
+$ knotd -d -c slave.conf # start the daemon
$ knotc -c slave.conf stop # stop the daemon
@end example
@@ -124,50 +116,46 @@ When the server is running, you can control the daemon, see @ref{Controlling run
@node Running a master server
@section Running a master server
-Knot DNS first needs to compile the zones before it can load them, therefore you need to
-compile them with the @code{knotc compile} action.
-Some actions like @code{start} or @code{restart} compile zones automatically.
-
If you want to just check the zone files first before starting,
you can use @code{knotc checkzone} action.
@example
$ knotc -c master.conf checkzone example.com
@end example
-Starting and stopping the daemon is the same as with the slave server in the previous section.
-@example
-$ knotc -c master.conf compile
-$ knotc -w -c master.conf start
-@end example
+For an approximate estimate of server's memory consumption, you can use the @code{knotc memstats} action.
+This action prints count of resource records, percentage of signed records and finally estimation
+of memory consumption for each zone, unless specified otherwise. Please note that estimated values might
+differ from the actual consumption. Also, for slave servers with incoming transfers enabled,
+be aware that the actual memory consumption might be double or more during transfers.
-Or you can compile it automatically:
@example
-$ knotc -c master.conf checkconf # check configuration
-$ knotc -w -c master.conf start
+$ knotc -c master.conf memstats example.com
@end example
+Starting and stopping the daemon is the same as with the slave server in the previous section.
+
@node Controlling running daemon
@section Controlling running daemon
Knot DNS was designed to allow server reconfiguration on-the-fly without interrupting
its operation. Thus it is possible to change both configuration and zone files and
also add or remove zones without restarting the server. This can be done with the
-@code{knotc reload} action.
+@code{knotc reload} action.
@example
-$ knotc -c master.conf compile # compile updated zones
$ knotc -c master.conf reload # reconfigure and load updated zones
@end example
If you want @emph{IXFR-out} differences created from changes you make to a zone file, enable @ref{ixfr-from-differences}
-in @code{zones} statement, then compile the zone and reload your server as seen above.
+in @code{zones} statement, then reload your server as seen above.
If @emph{SOA}'s @emph{serial} is not changed no differences will be created. Please note
that this feature is in @emph{experimental} stage and should be used with care.
If you encounter a bug using this feature, please send it to Knot developers (@pxref{Submitting a bugreport}).
You can also choose to tear-down the server fully and restart with the @code{knotc restart} action.
+Note that some actions like start, stop and restart cannot be done remotely.
@example
-$ knotc -c master.conf running # check if running
+$ knotc -c master.conf status # check if running
$ knotc -c master.conf restart # fully restart
@end example
diff --git a/doc/stamp-vti b/doc/stamp-vti
new file mode 100644
index 0000000..b53f702
--- /dev/null
+++ b/doc/stamp-vti
@@ -0,0 +1,4 @@
+@set UPDATED 26 June 2013
+@set UPDATED-MONTH June 2013
+@set EDITION 1.3.0-rc3
+@set VERSION 1.3.0-rc3
diff --git a/doc/texinfo.tex b/doc/texinfo.tex
index b5f3141..85b68e7 100644
--- a/doc/texinfo.tex
+++ b/doc/texinfo.tex
@@ -3,7 +3,7 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2012-11-08.11}
+\def\texinfoversion{2012-03-11.15}
%
% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
@@ -28,9 +28,9 @@
%
% Please try the latest version of texinfo.tex before submitting bug
% reports; you can get the latest version from:
-% http://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or
-% http://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or
-% http://www.gnu.org/software/texinfo/ (the Texinfo home page)
+% http://www.gnu.org/software/texinfo/ (the Texinfo home page), or
+% ftp://tug.org/tex/texinfo.tex
+% (and all CTAN mirrors, see http://www.ctan.org).
% The texinfo.tex in any given distribution could well be out
% of date, so if that's what you're using, please check.
%
@@ -594,7 +594,7 @@
\def\:{\spacefactor=1000 }
% @* forces a line break.
-\def\*{\unskip\hfil\break\hbox{}\ignorespaces}
+\def\*{\hfil\break\hbox{}\ignorespaces}
% @/ allows a line break.
\let\/=\allowbreak
@@ -1117,7 +1117,7 @@ where each line of input produces a line of output.}
% #1 is a control sequence in which to do the replacements,
% which we \xdef.
\def\txiescapepdf#1{%
- \ifx\pdfescapestring\thisisundefined
+ \ifx\pdfescapestring\relax
% No primitive available; should we give a warning or log?
% Many times it won't matter.
\else
@@ -1367,8 +1367,9 @@ output) for that.)}
\def\skipspaces#1{\def\PP{#1}\def\D{|}%
\ifx\PP\D\let\nextsp\relax
\else\let\nextsp\skipspaces
- \addtokens{\filename}{\PP}%
- \advance\filenamelength by 1
+ \ifx\p\space\else\addtokens{\filename}{\PP}%
+ \advance\filenamelength by 1
+ \fi
\fi
\nextsp}
\def\getfilename#1{%
@@ -1474,6 +1475,9 @@ output) for that.)}
\def\ttsl{\setfontstyle{ttsl}}
+% Default leading.
+\newdimen\textleading \textleading = 13.2pt
+
% Set the baselineskip to #1, and the lineskip and strut size
% correspondingly. There is no deep meaning behind these magic numbers
% used as factors; they just match (closely enough) what Knuth defined.
@@ -1485,7 +1489,6 @@ output) for that.)}
% can get a sort of poor man's double spacing by redefining this.
\def\baselinefactor{1}
%
-\newdimen\textleading
\def\setleading#1{%
\dimen0 = #1\relax
\normalbaselineskip = \baselinefactor\dimen0
@@ -1758,24 +1761,18 @@ end
\fi\fi
-% Set the font macro #1 to the font named \fontprefix#2.
+% Set the font macro #1 to the font named #2, adding on the
+% specified font prefix (normally `cm').
% #3 is the font's design size, #4 is a scale factor, #5 is the CMap
-% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit).
-% Example:
-% #1 = \textrm
-% #2 = \rmshape
-% #3 = 10
-% #4 = \mainmagstep
-% #5 = OT1
-%
+% encoding (currently only OT1, OT1IT and OT1TT are allowed, pass
+% empty to omit).
\def\setfont#1#2#3#4#5{%
\font#1=\fontprefix#2#3 scaled #4
\csname cmap#5\endcsname#1%
}
% This is what gets called when #5 of \setfont is empty.
\let\cmap\gobble
-%
-% (end of cmaps)
+% emacs-page end of cmaps
% Use cm as the default font prefix.
% To specify the font prefix, you must define \fontprefix
@@ -1785,7 +1782,7 @@ end
\fi
% Support font families that don't use the same naming scheme as CM.
\def\rmshape{r}
-\def\rmbshape{bx} % where the normal face is bold
+\def\rmbshape{bx} %where the normal face is bold
\def\bfshape{b}
\def\bxshape{bx}
\def\ttshape{tt}
@@ -1800,7 +1797,8 @@ end
\def\scshape{csc}
\def\scbshape{csc}
-% Definitions for a main text size of 11pt. (The default in Texinfo.)
+% Definitions for a main text size of 11pt. This is the default in
+% Texinfo.
%
\def\definetextfontsizexi{%
% Text fonts (11.2pt, magstep1).
@@ -1925,7 +1923,7 @@ end
\textleading = 13.2pt % line spacing for 11pt CM
\textfonts % reset the current fonts
\rm
-} % end of 11pt text font size definitions, \definetextfontsizexi
+} % end of 11pt text font size definitions
% Definitions to make the main text be 10pt Computer Modern, with
@@ -2057,7 +2055,7 @@ end
\textleading = 12pt % line spacing for 10pt CM
\textfonts % reset the current fonts
\rm
-} % end of 10pt text font size definitions, \definetextfontsizex
+} % end of 10pt text font size definitions
% We provide the user-level command
@@ -2272,6 +2270,8 @@ end
\gdef\markupsetcodequoteleft{\let`\codequoteleft}
\gdef\markupsetcodequoteright{\let'\codequoteright}
+
+\gdef\markupsetnoligaturesquoteleft{\let`\noligaturesquoteleft}
}
\let\markupsetuplqcode \markupsetcodequoteleft
@@ -2280,9 +2280,6 @@ end
\let\markupsetuplqexample \markupsetcodequoteleft
\let\markupsetuprqexample \markupsetcodequoteright
%
-\let\markupsetuplqkbd \markupsetcodequoteleft
-\let\markupsetuprqkbd \markupsetcodequoteright
-%
\let\markupsetuplqsamp \markupsetcodequoteleft
\let\markupsetuprqsamp \markupsetcodequoteright
%
@@ -2292,6 +2289,8 @@ end
\let\markupsetuplqverbatim \markupsetcodequoteleft
\let\markupsetuprqverbatim \markupsetcodequoteright
+\let\markupsetuplqkbd \markupsetnoligaturesquoteleft
+
% Allow an option to not use regular directed right quote/apostrophe
% (char 0x27), but instead the undirected quote from cmtt (char 0x0d).
% The undirected quote is ugly, so don't make it the default, but it
@@ -2381,7 +2380,8 @@ end
\aftersmartic
}
-% Unconditional use \ttsl, and no ic. @var is set to this for defuns.
+% like \smartslanted except unconditionally uses \ttsl, and no ic.
+% @var is set to this for defun arguments.
\def\ttslanted#1{{\ttsl #1}}
% @cite is like \smartslanted except unconditionally use \sl. We never want
@@ -2446,12 +2446,34 @@ end
% @samp.
\def\samp#1{{\setupmarkupstyle{samp}\lq\tclose{#1}\rq\null}}
-% @indicateurl is \samp, that is, with quotes.
-\let\indicateurl=\samp
+% definition of @key that produces a lozenge. Doesn't adjust to text size.
+%\setfont\keyrm\rmshape{8}{1000}{OT1}
+%\font\keysy=cmsy9
+%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
+% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
+% \vbox{\hrule\kern-0.4pt
+% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
+% \kern-0.4pt\hrule}%
+% \kern-.06em\raise0.4pt\hbox{\angleright}}}}
-% @code (and similar) prints in typewriter, but with spaces the same
-% size as normal in the surrounding text, without hyphenation, etc.
-% This is a subroutine for that.
+% definition of @key with no lozenge. If the current font is already
+% monospace, don't change it; that way, we respect @kbdinputstyle. But
+% if it isn't monospace, then use \tt.
+%
+\def\key#1{{\setupmarkupstyle{key}%
+ \nohyphenation
+ \ifmonospace\else\tt\fi
+ #1}\null}
+
+% ctrl is no longer a Texinfo command.
+\def\ctrl #1{{\tt \rawbackslash \hat}#1}
+
+% @file, @option are the same as @samp.
+\let\file=\samp
+\let\option=\samp
+
+% @code is a modification of @t,
+% which makes spaces the same size as normal in the surrounding text.
\def\tclose#1{%
{%
% Change normal interword space to be same as for the current font.
@@ -2476,7 +2498,7 @@ end
% We *must* turn on hyphenation at `-' and `_' in @code.
% Otherwise, it is too hard to avoid overfull hboxes
% in the Emacs manual, the Library manual, etc.
-%
+
% Unfortunately, TeX uses one parameter (\hyphenchar) to control
% both hyphenation at - and hyphenation within words.
% We must therefore turn them both off (\tclose does that)
@@ -2540,13 +2562,6 @@ end
\fi\fi
}
-% For @command, @env, @file, @option quotes seem unnecessary,
-% so use \code rather than \samp.
-\let\command=\code
-\let\env=\code
-\let\file=\code
-\let\option=\code
-
% @uref (abbreviation for `urlref') takes an optional (comma-separated)
% second argument specifying the text to display and an optional third
% arg as text to display instead of (rather than in addition to) the url
@@ -2693,6 +2708,10 @@ end
\let\email=\uref
\fi
+% @kbd is like @code, except that if the argument is just one @key command,
+% then @kbd has no effect.
+\def\kbd#1{{\setupmarkupstyle{kbd}\def\look{#1}\expandafter\kbdfoo\look??\par}}
+
% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
% `example' (@kbd uses ttsl only inside of @example and friends),
% or `code' (@kbd uses normal tty font always).
@@ -2716,36 +2735,16 @@ end
% Default is `distinct'.
\kbdinputstyle distinct
-% @kbd is like @code, except that if the argument is just one @key command,
-% then @kbd has no effect.
-\def\kbd#1{{\def\look{#1}\expandafter\kbdsub\look??\par}}
-
\def\xkey{\key}
-\def\kbdsub#1#2#3\par{%
- \def\one{#1}\def\three{#3}\def\threex{??}%
- \ifx\one\xkey\ifx\threex\three \key{#2}%
- \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi
- \else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi
-}
-
-% definition of @key that produces a lozenge. Doesn't adjust to text size.
-%\setfont\keyrm\rmshape{8}{1000}{OT1}
-%\font\keysy=cmsy9
-%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
-% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
-% \vbox{\hrule\kern-0.4pt
-% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
-% \kern-0.4pt\hrule}%
-% \kern-.06em\raise0.4pt\hbox{\angleright}}}}
+\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
+\ifx\one\xkey\ifx\threex\three \key{#2}%
+\else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi
+\else{\tclose{\kbdfont\setupmarkupstyle{kbd}\look}}\fi}
-% definition of @key with no lozenge. If the current font is already
-% monospace, don't change it; that way, we respect @kbdinputstyle. But
-% if it isn't monospace, then use \tt.
-%
-\def\key#1{{\setupmarkupstyle{key}%
- \nohyphenation
- \ifmonospace\else\tt\fi
- #1}\null}
+% For @indicateurl, @env, @command quotes seem unnecessary, so use \code.
+\let\indicateurl=\code
+\let\env=\code
+\let\command=\code
% @clicksequence{File @click{} Open ...}
\def\clicksequence#1{\begingroup #1\endgroup}
@@ -2853,9 +2852,6 @@ end
}
}
-% ctrl is no longer a Texinfo command, but leave this definition for fun.
-\def\ctrl #1{{\tt \rawbackslash \hat}#1}
-
% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}.
% Ignore unless FMTNAME == tex; then it is like @iftex and @tex,
% except specified as a normal braced arg, so no newlines to worry about.
@@ -3146,17 +3142,12 @@ end
% hopefully nobody will notice/care.
\edef\ecsize{\csname\curfontsize ecsize\endcsname}%
\edef\nominalsize{\csname\curfontsize nominalsize\endcsname}%
- \ifmonospace
- % typewriter:
- \font\thisecfont = ectt\ecsize \space at \nominalsize
+ \ifx\curfontstyle\bfstylename
+ % bold:
+ \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize
\else
- \ifx\curfontstyle\bfstylename
- % bold:
- \font\thisecfont = ecb\ifusingit{i}{x}\ecsize \space at \nominalsize
- \else
- % regular:
- \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize
- \fi
+ % regular:
+ \font\thisecfont = ec\ifusingit{ti}{rm}\ecsize \space at \nominalsize
\fi
\thisecfont
}
@@ -3269,20 +3260,6 @@ end
\finishedtitlepagetrue
}
-% Settings used for typesetting titles: no hyphenation, no indentation,
-% don't worry much about spacing, ragged right. This should be used
-% inside a \vbox, and fonts need to be set appropriately first. Because
-% it is always used for titles, nothing else, we call \rmisbold. \par
-% should be specified before the end of the \vbox, since a vbox is a group.
-%
-\def\raggedtitlesettings{%
- \rmisbold
- \hyphenpenalty=10000
- \parindent=0pt
- \tolerance=5000
- \ptexraggedright
-}
-
% Macros to be used within @titlepage:
\let\subtitlerm=\tenrm
@@ -3290,7 +3267,7 @@ end
\parseargdef\title{%
\checkenv\titlepage
- \vbox{\titlefonts \raggedtitlesettings #1\par}%
+ \leftline{\titlefonts\rmisbold #1}
% print a rule at the page bottom also.
\finishedtitlepagefalse
\vskip4pt \hrule height 4pt width \hsize \vskip4pt
@@ -4227,7 +4204,7 @@ end
}
\def\ifsetfail{\doignore{ifset}}
-% @ifclear VAR ... @end executes the `...' iff VAR has never been
+% @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been
% defined with @set, or has been undefined with @clear.
%
% The `\else' inside the `\doifset' parameter is a trick to reuse the
@@ -4238,35 +4215,6 @@ end
\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
\def\ifclearfail{\doignore{ifclear}}
-% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written
-% without the @) is in fact defined. We can only feasibly check at the
-% TeX level, so something like `mathcode' is going to considered
-% defined even though it is not a Texinfo command.
-%
-\makecond{ifcommanddefined}
-\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}}
-%
-\def\doifcmddefined#1#2{{%
- \makevalueexpandable
- \let\next=\empty
- \expandafter\ifx\csname #2\endcsname\relax
- #1% If not defined, \let\next as above.
- \fi
- \expandafter
- }\next
-}
-\def\ifcmddefinedfail{\doignore{ifcommanddefined}}
-
-% @ifcommandnotdefined CMD ... handled similar to @ifclear above.
-\makecond{ifcommandnotdefined}
-\def\ifcommandnotdefined{%
- \parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}}
-\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}}
-
-% Set the `txicommandconditionals' variable, so documents have a way to
-% test if the @ifcommand...defined conditionals are available.
-\set txicommandconditionals
-
% @dircategory CATEGORY -- specify a category of the dir file
% which this file should belong to. Ignore this in TeX.
\let\dircategory=\comment
@@ -4503,7 +4451,6 @@ end
\definedummyword\guillemetright
\definedummyword\guilsinglleft
\definedummyword\guilsinglright
- \definedummyword\lbracechar
\definedummyword\leq
\definedummyword\minus
\definedummyword\ogonek
@@ -4516,7 +4463,6 @@ end
\definedummyword\quoteleft
\definedummyword\quoteright
\definedummyword\quotesinglbase
- \definedummyword\rbracechar
\definedummyword\result
\definedummyword\textdegree
%
@@ -4568,7 +4514,6 @@ end
\definedummyword\t
%
% Commands that take arguments.
- \definedummyword\abbr
\definedummyword\acronym
\definedummyword\anchor
\definedummyword\cite
@@ -4580,9 +4525,7 @@ end
\definedummyword\emph
\definedummyword\env
\definedummyword\file
- \definedummyword\image
\definedummyword\indicateurl
- \definedummyword\inforef
\definedummyword\kbd
\definedummyword\key
\definedummyword\math
@@ -4629,10 +4572,7 @@ end
% content at all. So for index sorting, we map @{ and @} to strings
% starting with |, since that ASCII character is between ASCII { and }.
\def\{{|a}%
- \def\lbracechar{|a}%
- %
\def\}{|b}%
- \def\rbracechar{|b}%
%
% Non-English letters.
\def\AA{AA}%
@@ -5593,6 +5533,14 @@ end
% Define @majorheading, @heading and @subheading
+% NOTE on use of \vbox for chapter headings, section headings, and such:
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
+% 3) Likewise, headings look best if no \parindent is used, and
+% if justification is not attempted. Hence \raggedright.
+
\def\majorheading{%
{\advance\chapheadingskip by 10pt \chapbreak }%
\parsearg\chapheadingzzz
@@ -5600,8 +5548,10 @@ end
\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
\def\chapheadingzzz#1{%
- \vbox{\chapfonts \raggedtitlesettings #1\par}%
- \nobreak\bigskip \nobreak
+ {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\ptexraggedright
+ \rmisbold #1\hfill}}%
+ \bigskip \par\penalty 200\relax
\suppressfirstparagraphindent
}
@@ -5760,7 +5710,8 @@ end
%
% Typeset the actual heading.
\nobreak % Avoid page breaks at the interline glue.
- \vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright
+ \hangindent=\wd0 \centerparametersmaybe
\unhbox0 #1\par}%
}%
\nobreak\bigskip % no page break after a chapter title
@@ -5782,18 +5733,18 @@ end
\def\setchapterstyle #1 {\csname CHAPF#1\endcsname}
%
\def\unnchfopen #1{%
- \chapoddpage
- \vbox{\chapfonts \raggedtitlesettings #1\par}%
- \nobreak\bigskip\nobreak
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt\ptexraggedright
+ \rmisbold #1\hfill}}\bigskip \par\nobreak
}
\def\chfopen #1#2{\chapoddpage {\chapfonts
\vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}%
\par\penalty 5000 %
}
\def\centerchfopen #1{%
- \chapoddpage
- \vbox{\chapfonts \raggedtitlesettings \hfill #1\hfill}%
- \nobreak\bigskip \nobreak
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rmisbold #1}\hfill}}\bigskip \par\nobreak
}
\def\CHAPFopen{%
\global\let\chapmacro=\chfopen
@@ -6559,9 +6510,16 @@ end
\makedispenvdef{quotation}{\quotationstart}
%
\def\quotationstart{%
- \indentedblockstart % same as \indentedblock, but increase right margin too.
+ {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
+ \parindent=0pt
+ %
+ % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
\ifx\nonarrowing\relax
+ \advance\leftskip by \lispnarrowing
\advance\rightskip by \lispnarrowing
+ \exdentamount = \lispnarrowing
+ \else
+ \let\nonarrowing = \relax
\fi
\parsearg\quotationlabel
}
@@ -6587,32 +6545,6 @@ end
\fi
}
-% @indentedblock is like @quotation, but indents only on the left and
-% has no optional argument.
-%
-\makedispenvdef{indentedblock}{\indentedblockstart}
-%
-\def\indentedblockstart{%
- {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
- \parindent=0pt
- %
- % @cartouche defines \nonarrowing to inhibit narrowing at next level down.
- \ifx\nonarrowing\relax
- \advance\leftskip by \lispnarrowing
- \exdentamount = \lispnarrowing
- \else
- \let\nonarrowing = \relax
- \fi
-}
-
-% Keep a nonzero parskip for the environment, since we're doing normal filling.
-%
-\def\Eindentedblock{%
- \par
- {\parskip=0pt \afterenvbreak}%
-}
-\def\Esmallindentedblock{\Eindentedblock}
-
% LaTeX-like @verbatim...@end verbatim and @verb{<char>...<char>}
% If we want to allow any <char> as delimiter,
@@ -7091,10 +7023,7 @@ end
\df \sl \hyphenchar\font=0
%
% On the other hand, if an argument has two dashes (for instance), we
- % want a way to get ttsl. We used to recommend @var for that, so
- % leave the code in, but it's strange for @var to lead to typewriter.
- % Nowadays we recommend @code, since the difference between a ttsl hyphen
- % and a tt hyphen is pretty tiny. @code also disables ?` !`.
+ % want a way to get ttsl. Let's try @var for that.
\def\var##1{{\setupmarkupstyle{var}\ttslanted{##1}}}%
#1%
\sl\hyphenchar\font=45
@@ -7878,7 +7807,7 @@ end
\fi\fi
}
-%
+
% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is
% the node name, #2 the name of the Info cross-reference, #3 the printed
% node name, #4 the name of the Info file, #5 the name of the printed
@@ -7888,21 +7817,16 @@ end
\def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]}
\def\ref#1{\xrefX[#1,,,,,,,]}
%
-\newbox\toprefbox
+\newbox\topbox
\newbox\printedrefnamebox
-\newbox\infofilenamebox
\newbox\printedmanualbox
%
\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
\unsepspaces
%
- % Get args without leading/trailing spaces.
\def\printedrefname{\ignorespaces #3}%
\setbox\printedrefnamebox = \hbox{\printedrefname\unskip}%
%
- \def\infofilename{\ignorespaces #4}%
- \setbox\infofilenamebox = \hbox{\infofilename\unskip}%
- %
\def\printedmanual{\ignorespaces #5}%
\setbox\printedmanualbox = \hbox{\printedmanual\unskip}%
%
@@ -7937,18 +7861,11 @@ end
\turnoffactive
\makevalueexpandable
% This expands tokens, so do it after making catcode changes, so _
- % etc. don't get their TeX definitions. This ignores all spaces in
- % #4, including (wrongly) those in the middle of the filename.
+ % etc. don't get their TeX definitions.
\getfilename{#4}%
%
- % This (wrongly) does not take account of leading or trailing
- % spaces in #1, which should be ignored.
\edef\pdfxrefdest{#1}%
- \ifx\pdfxrefdest\empty
- \def\pdfxrefdest{Top}% no empty targets
- \else
- \txiescapepdf\pdfxrefdest % escape PDF special chars
- \fi
+ \txiescapepdf\pdfxrefdest
%
\leavevmode
\startlink attr{/Border [0 0 0]}%
@@ -7981,7 +7898,7 @@ end
\printedrefname
\fi
%
- % If the user also gave the printed manual name (fifth arg), append
+ % if the user also gave the printed manual name (fifth arg), append
% "in MANUALNAME".
\ifdim \wd\printedmanualbox > 0pt
\space \putwordin{} \cite{\printedmanual}%
@@ -7996,20 +7913,32 @@ end
% this is a loss. Therefore, we give the text of the node name
% again, so it is as if TeX is seeing it for the first time.
%
+ % Cross-manual reference. Only include the "Section ``foo'' in" if
+ % the foo is neither missing or Top. Thus, @xref{,,,foo,The Foo Manual}
+ % outputs simply "see The Foo Manual".
\ifdim \wd\printedmanualbox > 0pt
- % Cross-manual reference with a printed manual name.
+ % What is the 7sp about? The idea is that we also want to omit
+ % the Section part if we would be printing "Top", since they are
+ % clearly trying to refer to the whole manual. But, this being
+ % TeX, we can't easily compare strings while ignoring the possible
+ % spaces before and after in the input. By adding the arbitrary
+ % 7sp, we make it much less likely that a real node name would
+ % happen to have the same width as "Top" (e.g., in a monospaced font).
+ % I hope it will never happen in practice.
%
- \crossmanualxref{\cite{\printedmanual\unskip}}%
- %
- \else\ifdim \wd\infofilenamebox > 0pt
- % Cross-manual reference with only an info filename (arg 4), no
- % printed manual name (arg 5). This is essentially the same as
- % the case above; we output the filename, since we have nothing else.
+ % For the same basic reason, we retypeset the "Top" at every
+ % reference, since the current font is indeterminate.
%
- \crossmanualxref{\code{\infofilename\unskip}}%
- %
+ \setbox\topbox = \hbox{Top\kern7sp}%
+ \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}%
+ \ifdim \wd2 > 7sp
+ \ifdim \wd2 = \wd\topbox \else
+ \putwordSection{} ``\printedrefname'' \putwordin{}\space
+ \fi
+ \fi
+ \cite{\printedmanual}%
\else
- % Reference within this manual.
+ % Reference in this manual.
%
% _ (for example) has to be the character _ for the purposes of the
% control sequence corresponding to the node, but it has to expand
@@ -8030,37 +7959,11 @@ end
%
% output the `page 3'.
\turnoffactive \putwordpage\tie\refx{#1-pg}{}%
- \fi\fi
+ \fi
\fi
\endlink
\endgroup}
-% Output a cross-manual xref to #1. Used just above (twice).
-%
-% Only include the text "Section ``foo'' in" if the foo is neither
-% missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply
-% "see The Foo Manual", the idea being to refer to the whole manual.
-%
-% But, this being TeX, we can't easily compare our node name against the
-% string "Top" while ignoring the possible spaces before and after in
-% the input. By adding the arbitrary 7sp below, we make it much less
-% likely that a real node name would have the same width as "Top" (e.g.,
-% in a monospaced font). Hopefully it will never happen in practice.
-%
-% For the same basic reason, we retypeset the "Top" at every
-% reference, since the current font is indeterminate.
-%
-\def\crossmanualxref#1{%
- \setbox\toprefbox = \hbox{Top\kern7sp}%
- \setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}%
- \ifdim \wd2 > 7sp % nonempty?
- \ifdim \wd2 = \wd\toprefbox \else % same as Top?
- \putwordSection{} ``\printedrefname'' \putwordin{}\space
- \fi
- \fi
- #1%
-}
-
% This macro is called from \xrefX for the `[nodename]' part of xref
% output. It's a separate macro only so it can be changed more easily,
% since square brackets don't work well in some documents. Particularly
diff --git a/doc/troubleshooting.texi b/doc/troubleshooting.texi
index 18fee7a..f151153 100644
--- a/doc/troubleshooting.texi
+++ b/doc/troubleshooting.texi
@@ -2,23 +2,23 @@
@chapter Troubleshooting
@menu
-* Submitting a bugreport::
-* Generating backtrace::
+* Submitting a bugreport::
+* Generating backtrace::
* Debug messages::
@end menu
First of all, check the logs (@pxref{log}).
By default, Knot DNS logs all error messages to syslog. Enabling at least
-the @code{warning} message severity may help you identify some problems.
+the @code{warning} message severity may help you identify some problems.
@node Submitting a bugreport
@section Submitting a bugreport
If you are unable to solve the problem by yourselves, you can submit a
-bugreport to the Knot DNS team. For security issues (e.g. crash) do not
-use the public mailinglist. Instead, write to
-@url{mailto:knot-dns@@labs.nic.cz, knot-dns@@labs.nic.cz}. All other bugs
-and questions may be directed to the Knot DNS users mailinglist
+bugreport to the Knot DNS team. For security issues (e.g. crash) do not
+use the public mailinglist. Instead, write to
+@url{mailto:knot-dns@@labs.nic.cz, knot-dns@@labs.nic.cz}. All other bugs
+and questions may be directed to the Knot DNS users mailinglist
(@url{mailto:knot-dns-users@@lists.nic.cz, knot-dns-users@@lists.nic.cz}).
The bugreport should contain at least:
@@ -27,7 +27,7 @@ The bugreport should contain at least:
@item type and version of your operating system,
@item basic hardware information,
@item description of the bug,
-@item log output of all messages (category @code{any}) with severity Info
+@item log output of all messages (category @code{any}) with severity Info
and higher (severities @code{info, notice, warning, error}, or @code{any} if debug messages are not turned on (see below)),
@item steps to reproduce the bug (if known),
@item backtrace (if the bug caused a crash; see next section).
@@ -76,10 +76,10 @@ $ sudo gdb --pid <KNOT_PID>
In some cases the aforementioned information may not be enough to find
and fix the bug. In these cases it may be useful to turn on debug messages.
-Two steps are required in order to log debug messages. First you need to
+Two steps are required in order to log debug messages. First you need to
allow the debug messages in the server. Then the logging must be configured
-to log debug messages (@pxref{log}). It is recommended to log these
-messages to a file. Firstly, the debug output may be rather large and
+to log debug messages (@pxref{log}). It is recommended to log these
+messages to a file. Firstly, the debug output may be rather large and
secondly, it is easier to use the data for debugging.
@node Enabling debug messages in server
@@ -89,7 +89,7 @@ secondly, it is easier to use the data for debugging.
* Debug messages Example::
@end menu
-Allowing debug messages in the server is possible only when configuring the
+Allowing debug messages in the server is possible only when configuring the
sources. Two @command{configure} options are required to do this:
@itemize
@@ -99,15 +99,15 @@ want to enable debug messages. One or more of the following modules may be
listed, separated by commas:
@itemize
-@item @code{server} - Messages related to networking, threads and low-level
+@item @code{server} - Messages related to networking, threads and low-level
journal handling.
-@item @code{zones} - All operations with zones - loading, updating, saving,
+@item @code{zones} - All operations with zones - loading, updating, saving,
timers, high-level journal management.
@item @code{xfr} - AXFR, IXFR and NOTIFY handling.
@item @code{packet} - Packet parsing and response creation.
@item @code{dname} - Parsing, comparing and other operations on domain names.
@item @code{rr} - Details of processed resource records.
-@item @code{ns} - Query processing, high-level handling of all requests
+@item @code{ns} - Query processing, high-level handling of all requests
(transfers, NOTIFY, normal queries).
@item @code{hash} - Details of hash table (the main data structure) operation.
@item @code{compiler} - Zone file compilation.
@@ -116,7 +116,7 @@ listed, separated by commas:
@item
The @code{--enable-debuglevel} option is used to specify the verbosity of the
debug output. Be careful with this, as the @code{details} verbosity may produce
-really large logs (in order of GBs). There are three levels of verbosity:
+really large logs (in order of GBs). There are three levels of verbosity:
@code{brief}, @code{verbose} and @code{details}.
@end itemize
@@ -127,5 +127,3 @@ really large logs (in order of GBs). There are three levels of verbosity:
@example
$ ./configure --enable-debug=server,zones --enable-debuglevel=verbose
@end example
-
-
diff --git a/doc/version.texi b/doc/version.texi
new file mode 100644
index 0000000..b53f702
--- /dev/null
+++ b/doc/version.texi
@@ -0,0 +1,4 @@
+@set UPDATED 26 June 2013
+@set UPDATED-MONTH June 2013
+@set EDITION 1.3.0-rc3
+@set VERSION 1.3.0-rc3
diff --git a/install-sh b/install-sh
index 377bb86..a9244eb 100755
--- a/install-sh
+++ b/install-sh
@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
-scriptversion=2011-11-20.07; # UTC
+scriptversion=2011-01-19.21; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -35,7 +35,7 @@ scriptversion=2011-11-20.07; # UTC
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
-# 'make' implicit rules from creating a file called install from it
+# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
@@ -156,7 +156,7 @@ while test $# -ne 0; do
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
- # Protect names problematic for 'test' and other utilities.
+ # Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
@@ -190,7 +190,7 @@ if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
fi
shift # arg
dst_arg=$arg
- # Protect names problematic for 'test' and other utilities.
+ # Protect names problematic for `test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
@@ -202,7 +202,7 @@ if test $# -eq 0; then
echo "$0: no input file specified." >&2
exit 1
fi
- # It's OK to call 'install-sh -d' without argument.
+ # It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
@@ -240,7 +240,7 @@ fi
for src
do
- # Protect names problematic for 'test' and other utilities.
+ # Protect names problematic for `test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
@@ -354,7 +354,7 @@ do
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
- # other-writable bit of parent directory when it shouldn't.
+ # other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
diff --git a/knot.sample.conf.in b/knot.sample.conf.in
deleted file mode 100644
index db5c587..0000000
--- a/knot.sample.conf.in
+++ /dev/null
@@ -1,18 +0,0 @@
-system {
- identity "@package@ @version@";
- storage "@localstatedir@/@package@";
-}
-
-interfaces {
- ipv4 { address 127.0.0.1@53; }
-}
-
-zones {
- example.com {
- file "@sysconfdir@/example.com.zone";
- }
-}
-
-log {
- syslog { any warning, error, notice; }
-}
diff --git a/ltmain.sh b/ltmain.sh
index 16ddbf8..33f642a 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -70,7 +70,7 @@
# compiler: $LTCC
# compiler flags: $LTCFLAGS
# linker: $LD (gnu? $with_gnu_ld)
-# $progname: (GNU libtool) 2.4.2
+# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.1
# automake: $automake_version
# autoconf: $autoconf_version
#
@@ -80,7 +80,7 @@
PROGRAM=libtool
PACKAGE=libtool
-VERSION=2.4.2
+VERSION="2.4.2 Debian-2.4.2-1.1"
TIMESTAMP=""
package_revision=1.3337
@@ -1375,21 +1375,6 @@ func_replace_sysroot ()
func_infer_tag ()
{
$opt_debug
-
- # FreeBSD-specific: where we install compilers with non-standard names
- tag_compilers_CC="*cc cc* *gcc gcc* clang"
- tag_compilers_CXX="*c++ c++* *g++ g++* clang++"
- base_compiler=`set -- "$@"; echo $1`
-
- # If $tagname isn't set, then try to infer if the default "CC" tag applies
- if test -z "$tagname"; then
- for zp in $tag_compilers_CC; do
- case $base_compiler in
- $zp) tagname="CC"; break;;
- esac
- done
- fi
-
if test -n "$available_tags" && test -z "$tagname"; then
CC_quoted=
for arg in $CC; do
@@ -1426,22 +1411,7 @@ func_infer_tag ()
break
;;
esac
-
- # FreeBSD-specific: try compilers based on inferred tag
- if test -z "$tagname"; then
- eval "tag_compilers=\$tag_compilers_${z}"
- if test -n "$tag_compilers"; then
- for zp in $tag_compilers; do
- case $base_compiler in
- $zp) tagname=$z; break;;
- esac
- done
- if test -n "$tagname"; then
- break
- fi
- fi
- fi
- fi
+ fi
done
# If $tagname still isn't set, then no tagged configuration
# was found and let the user know that the "--tag" command
@@ -3547,9 +3517,6 @@ static const void *lt_preloaded_setup() {
;;
esac
;;
- *-*-freebsd*)
- # FreeBSD doesn't need this...
- ;;
*)
func_fatal_error "unknown suffix for \`$my_dlsyms'"
;;
@@ -5628,7 +5595,6 @@ func_mode_link ()
esac
;;
esac
- deplibs="$deplibs $arg"
continue
;;
@@ -6158,7 +6124,10 @@ func_mode_link ()
case $pass in
dlopen) libs="$dlfiles" ;;
dlpreopen) libs="$dlprefiles" ;;
- link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ link)
+ libs="$deplibs %DEPLIBS%"
+ test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs"
+ ;;
esac
fi
if test "$linkmode,$pass" = "lib,dlpreopen"; then
@@ -6201,30 +6170,13 @@ func_mode_link ()
finalize_deplibs="$deplib $finalize_deplibs"
else
func_append compiler_flags " $deplib"
- fi
-
- case $linkmode in
- lib)
- deplibs="$deplib $deplibs"
- test "$pass" = conv && continue
- newdependency_libs="$deplib $newdependency_libs"
- ;;
- prog)
- if test "$pass" = conv; then
- deplibs="$deplib $deplibs"
- continue
- fi
- if test "$pass" = scan; then
- deplibs="$deplib $deplibs"
- else
- compile_deplibs="$deplib $compile_deplibs"
- finalize_deplibs="$deplib $finalize_deplibs"
+ if test "$linkmode" = lib ; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
fi
- ;;
- *)
- ;;
- esac # linkmode
-
+ fi
continue
;;
-l*)
@@ -6495,19 +6447,19 @@ func_mode_link ()
# It is a libtool convenience library, so add in its objects.
func_append convenience " $ladir/$objdir/$old_library"
func_append old_convenience " $ladir/$objdir/$old_library"
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if $opt_preserve_dup_deps ; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done
elif test "$linkmode" != prog && test "$linkmode" != lib; then
func_fatal_error "\`$lib' is not a convenience library"
fi
- tmp_libs=
- for deplib in $dependency_libs; do
- deplibs="$deplib $deplibs"
- if $opt_preserve_dup_deps ; then
- case "$tmp_libs " in
- *" $deplib "*) func_append specialdeplibs " $deplib" ;;
- esac
- fi
- func_append tmp_libs " $deplib"
- done
continue
fi # $pass = conv
@@ -7400,6 +7352,9 @@ func_mode_link ()
revision="$number_minor"
lt_irix_increment=no
;;
+ *)
+ func_fatal_configuration "$modename: unknown library version type \`$version_type'"
+ ;;
esac
;;
no)
diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4
new file mode 100644
index 0000000..c3a8d69
--- /dev/null
+++ b/m4/ax_check_compile_flag.m4
@@ -0,0 +1,72 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
+#
+# DESCRIPTION
+#
+# Check whether the given FLAG works with the current language's compiler
+# or gives an error. (Warnings, however, are ignored)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# If EXTRA-FLAGS is defined, it is added to the current language's default
+# flags (e.g. CFLAGS) when the check is done. The check is thus made with
+# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
+# force the compiler to issue an error when a bad flag is given.
+#
+# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
+# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
+#
+# 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/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 2
+
+AC_DEFUN([AX_CHECK_COMPILE_FLAG],
+[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
+AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
+AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
+ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+ [AS_VAR_SET(CACHEVAR,[yes])],
+ [AS_VAR_SET(CACHEVAR,[no])])
+ _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
+AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
+ [m4_default([$2], :)],
+ [m4_default([$3], :)])
+AS_VAR_POPDEF([CACHEVAR])dnl
+])dnl AX_CHECK_COMPILE_FLAGS
diff --git a/m4/ax_check_compiler_flags.m4 b/m4/ax_check_compiler_flags.m4
deleted file mode 100644
index 05e5c3b..0000000
--- a/m4/ax_check_compiler_flags.m4
+++ /dev/null
@@ -1,78 +0,0 @@
-# ===========================================================================
-# http://autoconf-archive.cryp.to/ax_check_compiler_flags.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-# AX_CHECK_COMPILER_FLAGS(FLAGS, [ACTION-SUCCESS], [ACTION-FAILURE])
-#
-# DESCRIPTION
-#
-# Check whether the given compiler FLAGS work with the current language's
-# compiler, or whether they give an error. (Warnings, however, are
-# ignored.)
-#
-# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
-# success/failure.
-#
-# LAST MODIFICATION
-#
-# 2008-04-12
-#
-# COPYLEFT
-#
-# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
-# Copyright (c) 2008 Matteo Frigo
-#
-# 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/>.
-#
-# As a special exception, the respective Autoconf Macro's copyright owner
-# gives unlimited permission to copy, distribute and modify the configure
-# scripts that are the output of Autoconf when processing the Macro. You
-# need not follow the terms of the GNU General Public License when using
-# or distributing such scripts, even though portions of the text of the
-# Macro appear in them. The GNU General Public License (GPL) does govern
-# all other use of the material that constitutes the Autoconf Macro.
-#
-# This special exception to the GPL applies to versions of the Autoconf
-# Macro released by the Autoconf Macro Archive. When you make and
-# distribute a modified version of the Autoconf Macro, you may extend this
-# special exception to the GPL to apply to your modified version as well.
-
-AC_DEFUN([AX_CHECK_COMPILER_FLAGS],
-[AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX
-AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1])
-dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname:
-AS_LITERAL_IF([$1],
- [AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1), [
- ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
- _AC_LANG_PREFIX[]FLAGS="$1"
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
- AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes,
- AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no)
- _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])],
- [ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
- _AC_LANG_PREFIX[]FLAGS="$1"
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
- eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=yes,
- eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)=no)
- _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])
-eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_$1)
-AC_MSG_RESULT($ax_check_compiler_flags)
-if test "x$ax_check_compiler_flags" = xyes; then
- m4_default([$2], :)
-else
- m4_default([$3], :)
-fi
-])dnl AX_CHECK_COMPILER_FLAGS
diff --git a/m4/ax_ext.m4 b/m4/ax_ext.m4
index 898f2bf..9a288bc 100644
--- a/m4/ax_ext.m4
+++ b/m4/ax_ext.m4
@@ -39,13 +39,13 @@
AC_DEFUN([AX_EXT],
[
AC_REQUIRE([AX_GCC_X86_CPUID])
-
+
AX_GCC_X86_CPUID([0x00000001])
if test "$ax_cv_gcc_x86_cpuid_0x00000001" != "unknown"; then
ecx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 3`
edx=`echo $ax_cv_gcc_x86_cpuid_0x00000001 | cut -d ":" -f 4`
fi
-
+
AC_CACHE_CHECK([whether mmx is supported], [ax_cv_have_mmx_ext],
[
ax_cv_have_mmx_ext=no
@@ -98,22 +98,22 @@ AC_DEFUN([AX_EXT],
if test "$ax_cv_have_mmx_ext" = yes; then
AC_DEFINE(HAVE_MMX,,[Support mmx instructions])
- AX_CHECK_COMPILER_FLAGS([-mmmx], [SIMD_FLAGS="$SIMD_FLAGS -mmmx"], [])
+ AX_CHECK_COMPILE_FLAG([-mmmx], [SIMD_FLAGS="$SIMD_FLAGS -mmmx"], [])
fi
if test "$ax_cv_have_sse_ext" = yes; then
AC_DEFINE(HAVE_SSE,,[Support SSE (Streaming SIMD Extensions) instructions])
- AX_CHECK_COMPILER_FLAGS([-msse], [SIMD_FLAGS="$SIMD_FLAGS -msse"], [])
+ AX_CHECK_COMPILE_FLAG([-msse], [SIMD_FLAGS="$SIMD_FLAGS -msse"], [])
fi
if test "$ax_cv_have_sse2_ext" = yes; then
AC_DEFINE(HAVE_SSE2,,[Support SSE2 (Streaming SIMD Extensions 2) instructions])
- AX_CHECK_COMPILER_FLAGS([-msse2], [SIMD_FLAGS="$SIMD_FLAGS -msse2"], [])
+ AX_CHECK_COMPILE_FLAG([-msse2], [SIMD_FLAGS="$SIMD_FLAGS -msse2"], [])
fi
if test "$ax_cv_have_sse3_ext" = yes; then
AC_DEFINE(HAVE_SSE3,,[Support SSE3 (Streaming SIMD Extensions 3) instructions])
- AX_CHECK_COMPILER_FLAGS([-msse3], [SIMD_FLAGS="$SIMD_FLAGS -msse3"], [])
+ AX_CHECK_COMPILE_FLAG([-msse3], [SIMD_FLAGS="$SIMD_FLAGS -msse3"], [])
fi
if test "$ax_cv_have_ssse3_ext" = yes; then
diff --git a/m4/ax_gcc_x86_cpuid.m4 b/m4/ax_gcc_x86_cpuid.m4
index e9231b8..792e684 100644
--- a/m4/ax_gcc_x86_cpuid.m4
+++ b/m4/ax_gcc_x86_cpuid.m4
@@ -57,7 +57,7 @@ AC_CACHE_CHECK([for x86 cpuid $1 output], [ax_cv_gcc_x86_cpuid_$1],
fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx);
fclose(f);
return 0;
-])],
+])],
[ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid],
[ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid],
[ax_cv_gcc_x86_cpuid_$1=unknown])])
diff --git a/m4/ax_recvmmsg.m4 b/m4/ax_recvmmsg.m4
index eb5c4d6..bc7bfe3 100644
--- a/m4/ax_recvmmsg.m4
+++ b/m4/ax_recvmmsg.m4
@@ -37,7 +37,7 @@ AC_DEFUN([AX_MSG_WAITFORONE],
volatile int _intr = 0;
void sighandle(int s) {
- _intr = 1;
+ _intr = 1;
}
]],[[
#ifndef MSG_WAITFORONE
@@ -45,7 +45,7 @@ void sighandle(int s) {
#else
int port = 35353;
int fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd < 0) return 1;
+ if (fd < 0) return 1;
struct mmsghdr msgs[2];
struct iovec iovecs[2];
char bufs[2][64];
@@ -63,7 +63,7 @@ void sighandle(int s) {
sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sa.sin_port = htons(port); /* Find free port. */
while (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
- if (errno == EADDRINUSE) sa.sin_port = ++port;
+ if (errno == EADDRINUSE) sa.sin_port = ++port;
else break;
}
@@ -83,7 +83,7 @@ void sighandle(int s) {
close(fd);
if (ret < 0) { /* Completely failed. */
return 2;
- }
+ }
return _intr; /* OK if not interrupted. */
#endif
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 44e0ecf..534d1cc 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -2512,17 +2512,6 @@ freebsd* | dragonfly*)
esac
;;
-gnu*)
- version_type=linux # correct to gnu/linux during the next big refactor
- need_lib_prefix=no
- need_version=no
- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
- soname_spec='${libname}${release}${shared_ext}$major'
- shlibpath_var=LD_LIBRARY_PATH
- shlibpath_overrides_runpath=no
- hardcode_into_libs=yes
- ;;
-
haiku*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
@@ -2639,7 +2628,7 @@ linux*oldld* | linux*aout* | linux*coff*)
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
version_type=linux # correct to gnu/linux during the next big refactor
need_lib_prefix=no
need_version=no
@@ -2684,6 +2673,18 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu)
dynamic_linker='GNU/Linux ld.so'
;;
+netbsdelf*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='NetBSD ld.elf_so'
+ ;;
+
netbsd*)
version_type=sunos
need_lib_prefix=no
@@ -3243,10 +3244,6 @@ freebsd* | dragonfly*)
fi
;;
-gnu*)
- lt_cv_deplibs_check_method=pass_all
- ;;
-
haiku*)
lt_cv_deplibs_check_method=pass_all
;;
@@ -3285,11 +3282,11 @@ irix5* | irix6* | nonstopux*)
;;
# This must be glibc/ELF.
-linux* | k*bsd*-gnu | kopensolaris*-gnu)
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
-netbsd*)
+netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
else
@@ -4037,7 +4034,7 @@ m4_if([$1], [CXX], [
;;
esac
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# KAI C++ Compiler
@@ -4101,7 +4098,7 @@ m4_if([$1], [CXX], [
;;
esac
;;
- netbsd*)
+ netbsd* | netbsdelf*-gnu)
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -4336,7 +4333,7 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
# old Intel for x86_64 which still supported -KPIC.
ecc*)
@@ -4578,6 +4575,9 @@ m4_if([$1], [CXX], [
;;
esac
;;
+ linux* | k*bsd*-gnu | gnu*)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
;;
@@ -4640,6 +4640,9 @@ dnl Note also adjust exclude_expsyms for C++ above.
openbsd*)
with_gnu_ld=no
;;
+ linux* | k*bsd*-gnu | gnu*)
+ _LT_TAGVAR(link_all_deplibs, $1)=no
+ ;;
esac
_LT_TAGVAR(ld_shlibs, $1)=yes
@@ -4861,7 +4864,7 @@ _LT_EOF
fi
;;
- netbsd*)
+ netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
@@ -5038,6 +5041,7 @@ _LT_EOF
if test "$aix_use_runtimelinking" = yes; then
shared_flag="$shared_flag "'${wl}-G'
fi
+ _LT_TAGVAR(link_all_deplibs, $1)=no
else
# not using gcc
if test "$host_cpu" = ia64; then
@@ -5342,7 +5346,7 @@ _LT_EOF
_LT_TAGVAR(link_all_deplibs, $1)=yes
;;
- netbsd*)
+ netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
@@ -6222,9 +6226,6 @@ if test "$_lt_caught_CXX_error" != yes; then
_LT_TAGVAR(ld_shlibs, $1)=yes
;;
- gnu*)
- ;;
-
haiku*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
_LT_TAGVAR(link_all_deplibs, $1)=yes
@@ -6386,7 +6387,7 @@ if test "$_lt_caught_CXX_error" != yes; then
_LT_TAGVAR(inherit_rpath, $1)=yes
;;
- linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
case $cc_basename in
KCC*)
# Kuck and Associates, Inc. (KAI) C++ Compiler
diff --git a/m4/visibility.m4 b/m4/visibility.m4
new file mode 100644
index 0000000..2ff6330
--- /dev/null
+++ b/m4/visibility.m4
@@ -0,0 +1,52 @@
+# visibility.m4 serial 1 (gettext-0.15)
+dnl Copyright (C) 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl Tests whether the compiler supports the command-line option
+dnl -fvisibility=hidden and the function and variable attributes
+dnl __attribute__((__visibility__("hidden"))) and
+dnl __attribute__((__visibility__("default"))).
+dnl Does *not* test for __visibility__("protected") - which has tricky
+dnl semantics (see the 'vismain' test in glibc) and does not exist e.g. on
+dnl MacOS X.
+dnl Does *not* test for __visibility__("internal") - which has processor
+dnl dependent semantics.
+dnl Does *not* test for #pragma GCC visibility push(hidden) - which is
+dnl "really only recommended for legacy code".
+dnl Set the variable CFLAG_VISIBILITY.
+dnl Defines and sets the variable HAVE_VISIBILITY.
+
+AC_DEFUN([gl_VISIBILITY],
+[
+ AC_REQUIRE([AC_PROG_CC])
+ CFLAG_VISIBILITY=
+ HAVE_VISIBILITY=0
+ if test -n "$GCC"; then
+ AC_MSG_CHECKING([for simple visibility declarations])
+ AC_CACHE_VAL(gl_cv_cc_visibility, [
+ gl_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ AC_TRY_COMPILE(
+ [extern __attribute__((__visibility__("hidden"))) int hiddenvar;
+ extern __attribute__((__visibility__("default"))) int exportedvar;
+ extern __attribute__((__visibility__("hidden"))) int hiddenfunc (void);
+ extern __attribute__((__visibility__("default"))) int exportedfunc (void);],
+ [],
+ gl_cv_cc_visibility=yes,
+ gl_cv_cc_visibility=no)
+ CFLAGS="$gl_save_CFLAGS"])
+ AC_MSG_RESULT([$gl_cv_cc_visibility])
+ if test $gl_cv_cc_visibility = yes; then
+ CFLAG_VISIBILITY="-fvisibility=hidden"
+ HAVE_VISIBILITY=1
+ fi
+ fi
+ AC_SUBST([CFLAG_VISIBILITY])
+ AC_SUBST([HAVE_VISIBILITY])
+ AC_DEFINE_UNQUOTED([HAVE_VISIBILITY], [$HAVE_VISIBILITY],
+ [Define to 1 or 0, depending whether the compiler supports simple visibility declarations.])
+])
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..a6f4010
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,2 @@
+MANPAGES = knot.conf.5 knotc.8 knotd.8 kdig.1 khost.1 knsupdate.1
+dist_man_MANS = $(MANPAGES)
diff --git a/man/Makefile.in b/man/Makefile.in
new file mode 100644
index 0000000..3c98806
--- /dev/null
+++ b/man/Makefile.in
@@ -0,0 +1,609 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = man
+DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in $(srcdir)/kdig.1.in $(srcdir)/khost.1.in \
+ $(srcdir)/knot.conf.5.in $(srcdir)/knotc.8.in \
+ $(srcdir)/knotd.8.in $(srcdir)/knsupdate.1.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_ext.m4 \
+ $(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
+ $(top_srcdir)/m4/ax_recvmmsg.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES = khost.1 knotc.8 knotd.8 kdig.1 knsupdate.1 \
+ knot.conf.5
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+man1dir = $(mandir)/man1
+am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \
+ "$(DESTDIR)$(man8dir)"
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+NROFF = nroff
+MANS = $(dist_man_MANS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FSM_TYPE = @FSM_TYPE@
+GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RAGEL = @RAGEL@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SIMD_FLAGS = @SIMD_FLAGS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libcrypto_CFLAGS = @libcrypto_CFLAGS@
+libcrypto_LIBS = @libcrypto_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+liburcu_CFLAGS = @liburcu_CFLAGS@
+liburcu_LIBS = @liburcu_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+run_dir = @run_dir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+storage_dir = @storage_dir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+MANPAGES = knot.conf.5 knotc.8 knotd.8 kdig.1 khost.1 knsupdate.1
+dist_man_MANS = $(MANPAGES)
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits man/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnits man/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+khost.1: $(top_builddir)/config.status $(srcdir)/khost.1.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+knotc.8: $(top_builddir)/config.status $(srcdir)/knotc.8.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+knotd.8: $(top_builddir)/config.status $(srcdir)/knotd.8.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+kdig.1: $(top_builddir)/config.status $(srcdir)/kdig.1.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+knsupdate.1: $(top_builddir)/config.status $(srcdir)/knsupdate.1.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+knot.conf.5: $(top_builddir)/config.status $(srcdir)/knot.conf.5.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-man1: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(dist_man_MANS)'; \
+ test -n "$(man1dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.1[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man1:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man1dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.1[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+install-man5: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(dist_man_MANS)'; \
+ test -n "$(man5dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.5[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man5:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man5dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.5[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
+install-man8: $(dist_man_MANS)
+ @$(NORMAL_INSTALL)
+ @list1=''; \
+ list2='$(dist_man_MANS)'; \
+ test -n "$(man8dir)" \
+ && test -n "`echo $$list1$$list2`" \
+ || exit 0; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
+ { for i in $$list1; do echo "$$i"; done; \
+ if test -n "$$list2"; then \
+ for i in $$list2; do echo "$$i"; done \
+ | sed -n '/\.8[a-z]*$$/p'; \
+ fi; \
+ } | while read p; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; echo "$$p"; \
+ done | \
+ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+ sed 'N;N;s,\n, ,g' | { \
+ list=; while read file base inst; do \
+ if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ fi; \
+ done; \
+ for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+ while read files; do \
+ test -z "$$files" || { \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
+ done; }
+
+uninstall-man8:
+ @$(NORMAL_UNINSTALL)
+ @list=''; test -n "$(man8dir)" || exit 0; \
+ files=`{ for i in $$list; do echo "$$i"; done; \
+ l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+ sed -n '/\.8[a-z]*$$/p'; \
+ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
+ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+ @list='$(MANS)'; if test -n "$$list"; then \
+ list=`for p in $$list; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
+ if test -n "$$list" && \
+ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
+ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \
+ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
+ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
+ echo " typically \`make maintainer-clean' will remove them" >&2; \
+ exit 1; \
+ else :; fi; \
+ else :; fi
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(MANS)
+installdirs:
+ for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1 install-man5 install-man8
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-man
+
+uninstall-man: uninstall-man1 uninstall-man5 uninstall-man8
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-man1 \
+ install-man5 install-man8 install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am \
+ uninstall-man uninstall-man1 uninstall-man5 uninstall-man8
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/man/kdig.1 b/man/kdig.1
new file mode 100644
index 0000000..de740cf
--- /dev/null
+++ b/man/kdig.1
@@ -0,0 +1,195 @@
+.TH "kdig" "1" "April 2013" "CZ.NIC Labs" "Knot DNS, version 1.3.0-rc3"
+.SH NAME
+.B kdig
+\- Advanced DNS lookup utility (libknot equivalent of ISC dig)
+.SH SYNOPSIS
+.B kdig
+[\fIcommon-settings\fR] [\fIquery\fR [\fIsettings\fR]]...
+.TP 5
+.B kdig
+\fB-h\fR
+.SH DESCRIPTION
+This utility sends one or more DNS \fIqueries\fR to a nameserver. Each query can
+have individual \fIsettings\fR, or it can be specified globally via \fIcommon-settings\fR,
+which must precede \fIquery\fR specification.
+.TP 4
+\fIquery
+\fIname\fR | \fB-q\fR \fIname\fR | \fB-x\fR \fIaddress\fR
+.TP
+\fIcommon-settings, settings
+[\fIclass\fR] [\fItype\fR] [\fB@\fIserver\fR]... [\fIoptions\fR]
+.TP
+\fIname\fR
+Is a domain name that is to be looked up.
+.TP
+\fIserver\fR
+Is a name or an address of the nameserver to send a query to. The address
+can be specified using [address]:port notation. If no server is specified
+the servers from \fB/etc/resolv.conf\fR are used.
+.TP
+If no arguments are provided, \fBkdig\fR sends \fINS\fR query for root zone.
+.SH OPTIONS
+.TP 4
+.BI -4
+Use IPv4 protocol only.
+.TP
+.BI -6
+Use IPv6 protocol only.
+.TP
+.BI -b \ address
+Set the source IP address of the query to \fIaddress\fR. The address
+can be specified using [address]:port notation.
+.TP
+.BI -c \ class
+Set query class (e.g. \fICH\fR, \fICLASS4\fR).
+An explicit variant of \fIclass\fR specification.
+The default class is \fIIN\fR.
+.TP
+.BI -d
+Enable debug messages if any.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print short help.
+.TP
+.BI -k \ keyfile
+Use TSIG or SIG\-0 key stored in a file \fIkeyfile\fR to authenticate the request.
+Supported file format is the same as generated by ISC \fBdnssec\-keygen\fR.
+The key comprises of public (.key extension) and private part (.private extension).
+Either of these file names or a name without the extension can be specified as \fIkeyfile\fR
+parameter.
+.TP
+.BI -p \ port
+Set nameserver port number or service name to send a query to.
+The default port is \fI53\fR.
+.TP
+.BI -q \ name
+Set query name. An explicit variant of \fIname\fR specification.
+.TP
+.BI -t \ type
+Set query type (e.g. \fINS\fR, \fIIXFR=12345\fR, \fITYPE65535\fR).
+An explicit variant of \fItype\fR specification. The default type is \fIA\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print program version.
+.TP
+.BI -x \ address
+Send \fIPTR\fR query for IPv4 or IPv6 \fIaddress\fR.
+.TP
+.BI -y \ \fR[\fIalgo:\fR]\fIkeyname:key\fR
+Use TSIG key with a name \fIkeyname\fR to authenticate the request. The \fIalgo\fR
+part specifies the algorithm (the default is hmac\-md5) and \fIkey\fR specifies
+the shared secret encoded in Base64.
+.TP
+\fB+\fR[\fBno\fR]\fBmultiline\fR
+Wrap long records to more lines.
+.TP
+\fB+\fR[\fBno\fR]\fBshort\fR
+Show record data only.
+.TP
+\fB+\fR[\fBno\fR]\fBaaflag\fR
+Set AA flag.
+.TP
+\fB+\fR[\fBno\fR]\fBtcflag\fR
+Set TC flag.
+.TP
+\fB+\fR[\fBno\fR]\fBrdflag\fR
+Set RD flag.
+.TP
+\fB+\fR[\fBno\fR]\fBrecurse\fR
+Same as +\fR[\fBno\fR]\fBrdflag\fR
+.TP
+\fB+\fR[\fBno\fR]\fBrec\fR
+Same as +\fR[\fBno\fR]\fBrdflag\fR
+.TP
+\fB+\fR[\fBno\fR]\fBraflag\fR
+Set RA flag.
+.TP
+\fB+\fR[\fBno\fR]\fBzflag\fR
+Set zero flag bit.
+.TP
+\fB+\fR[\fBno\fR]\fBadflag\fR
+Set AD flag.
+.TP
+\fB+\fR[\fBno\fR]\fBcdflag\fR
+Set CD flag.
+.TP
+\fB+\fR[\fBno\fR]\fBdnssec\fR
+Set DO flag.
+.TP
+\fB+\fR[\fBno\fR]\fBall\fR
+Show all packet sections.
+.TP
+\fB+\fR[\fBno\fR]\fBqr\fR
+Show query packet.
+.TP
+\fB+\fR[\fBno\fR]\fBheader\fR
+Show packet header.
+.TP
+\fB+\fR[\fBno\fR]\fBedns\fR
+Show EDNS pseudosectio.
+.TP
+\fB+\fR[\fBno\fR]\fBquestion\fR
+Show question section.
+.TP
+\fB+\fR[\fBno\fR]\fBanswer\fR
+Show answer section.
+.TP
+\fB+\fR[\fBno\fR]\fBauthority\fR
+Show authority section.
+.TP
+\fB+\fR[\fBno\fR]\fBadditional\fR
+Show additional section.
+.TP
+\fB+\fR[\fBno\fR]\fBstats\fR
+Show trailing packet statistics.
+.TP
+\fB+\fR[\fBno\fR]\fBcl\fR
+Show DNS class.
+.TP
+\fB+\fR[\fBno\fR]\fBttl\fR
+Show TTL value.
+.TP
+\fB+time=\fIT\fR
+Set wait for reply interval in seconds (default is 5 seconds).
+.TP
+\fB+retries=\fIN\fR
+Set number of retries (default is 2). This doesn't apply to AXFR or IXFR.
+.TP
+\fB+bufsize=\fIB\fR
+Set EDNS buffer size in bytes (default is 512 bytes).
+.TP
+\fB+\fR[\fBno\fR]\fBtcp\fR
+Use TCP protocol.
+.TP
+\fB+\fR[\fBno\fR]\fBfail\fR
+Stop if SERVFAIL.
+.TP
+\fB+\fR[\fBno\fR]\fBignore\fR
+Don't use TCP automatically if truncated reply is received.
+.TP
+\fB+\fR[\fBno\fR]\fBnsid\fR
+Request nameserver identifier (NSID).
+.SH NOTE
+Options \fB-k\fR and \fB-y\fR cannot be used mutually.
+.SH EXAMPLES
+.B Example 1. Get A record for example.com:
+.TP
+# kdig example.com A
+.TP
+.B Example 2. Perform AXFR for zone example.com from the server 192.0.2.1:
+.TP
+# kdig example.com -t AXFR @192.0.2.1
+.TP 12
+.B Example 3. Send one A query for example.com from 192.0.2.1 and one reverse \
+lookup for address 2001:DB8::1 from 192.0.2.2. Both using TCP protocol:
+.TP
+# kdig +tcp example.com -t A @192.0.2.1 -x 2001:DB8::1 @192.0.2.2
+.SH FILES
+.BI /etc/resolv.conf
+.SH AUTHOR
+Daniel Salzman (\fBhttp://knot-dns.cz\fR)
+.TP
+Please send any bugs or comments to \fBknot-dns@labs.nic.cz\fR
+.SH SEE ALSO
+.BI khost\fR(8),
+.BI knsupdate\fR(8).
diff --git a/man/kdig.1.in b/man/kdig.1.in
new file mode 100644
index 0000000..473bf69
--- /dev/null
+++ b/man/kdig.1.in
@@ -0,0 +1,195 @@
+.TH "kdig" "1" "April 2013" "CZ.NIC Labs" "Knot DNS, version @VERSION@"
+.SH NAME
+.B kdig
+\- Advanced DNS lookup utility (libknot equivalent of ISC dig)
+.SH SYNOPSIS
+.B kdig
+[\fIcommon-settings\fR] [\fIquery\fR [\fIsettings\fR]]...
+.TP 5
+.B kdig
+\fB-h\fR
+.SH DESCRIPTION
+This utility sends one or more DNS \fIqueries\fR to a nameserver. Each query can
+have individual \fIsettings\fR, or it can be specified globally via \fIcommon-settings\fR,
+which must precede \fIquery\fR specification.
+.TP 4
+\fIquery
+\fIname\fR | \fB-q\fR \fIname\fR | \fB-x\fR \fIaddress\fR
+.TP
+\fIcommon-settings, settings
+[\fIclass\fR] [\fItype\fR] [\fB@\fIserver\fR]... [\fIoptions\fR]
+.TP
+\fIname\fR
+Is a domain name that is to be looked up.
+.TP
+\fIserver\fR
+Is a name or an address of the nameserver to send a query to. The address
+can be specified using [address]:port notation. If no server is specified
+the servers from \fB/etc/resolv.conf\fR are used.
+.TP
+If no arguments are provided, \fBkdig\fR sends \fINS\fR query for root zone.
+.SH OPTIONS
+.TP 4
+.BI -4
+Use IPv4 protocol only.
+.TP
+.BI -6
+Use IPv6 protocol only.
+.TP
+.BI -b \ address
+Set the source IP address of the query to \fIaddress\fR. The address
+can be specified using [address]:port notation.
+.TP
+.BI -c \ class
+Set query class (e.g. \fICH\fR, \fICLASS4\fR).
+An explicit variant of \fIclass\fR specification.
+The default class is \fIIN\fR.
+.TP
+.BI -d
+Enable debug messages if any.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print short help.
+.TP
+.BI -k \ keyfile
+Use TSIG or SIG\-0 key stored in a file \fIkeyfile\fR to authenticate the request.
+Supported file format is the same as generated by ISC \fBdnssec\-keygen\fR.
+The key comprises of public (.key extension) and private part (.private extension).
+Either of these file names or a name without the extension can be specified as \fIkeyfile\fR
+parameter.
+.TP
+.BI -p \ port
+Set nameserver port number or service name to send a query to.
+The default port is \fI53\fR.
+.TP
+.BI -q \ name
+Set query name. An explicit variant of \fIname\fR specification.
+.TP
+.BI -t \ type
+Set query type (e.g. \fINS\fR, \fIIXFR=12345\fR, \fITYPE65535\fR).
+An explicit variant of \fItype\fR specification. The default type is \fIA\fR.
+.TP
+\fB\-v\fR, \fB\-\-version\fR
+Print program version.
+.TP
+.BI -x \ address
+Send \fIPTR\fR query for IPv4 or IPv6 \fIaddress\fR.
+.TP
+.BI -y \ \fR[\fIalgo:\fR]\fIkeyname:key\fR
+Use TSIG key with a name \fIkeyname\fR to authenticate the request. The \fIalgo\fR
+part specifies the algorithm (the default is hmac\-md5) and \fIkey\fR specifies
+the shared secret encoded in Base64.
+.TP
+\fB+\fR[\fBno\fR]\fBmultiline\fR
+Wrap long records to more lines.
+.TP
+\fB+\fR[\fBno\fR]\fBshort\fR
+Show record data only.
+.TP
+\fB+\fR[\fBno\fR]\fBaaflag\fR
+Set AA flag.
+.TP
+\fB+\fR[\fBno\fR]\fBtcflag\fR
+Set TC flag.
+.TP
+\fB+\fR[\fBno\fR]\fBrdflag\fR
+Set RD flag.
+.TP
+\fB+\fR[\fBno\fR]\fBrecurse\fR
+Same as +\fR[\fBno\fR]\fBrdflag\fR
+.TP
+\fB+\fR[\fBno\fR]\fBrec\fR
+Same as +\fR[\fBno\fR]\fBrdflag\fR
+.TP
+\fB+\fR[\fBno\fR]\fBraflag\fR
+Set RA flag.
+.TP
+\fB+\fR[\fBno\fR]\fBzflag\fR
+Set zero flag bit.
+.TP
+\fB+\fR[\fBno\fR]\fBadflag\fR
+Set AD flag.
+.TP
+\fB+\fR[\fBno\fR]\fBcdflag\fR
+Set CD flag.
+.TP
+\fB+\fR[\fBno\fR]\fBdnssec\fR
+Set DO flag.
+.TP
+\fB+\fR[\fBno\fR]\fBall\fR
+Show all packet sections.
+.TP
+\fB+\fR[\fBno\fR]\fBqr\fR
+Show query packet.
+.TP
+\fB+\fR[\fBno\fR]\fBheader\fR
+Show packet header.
+.TP
+\fB+\fR[\fBno\fR]\fBedns\fR
+Show EDNS pseudosectio.
+.TP
+\fB+\fR[\fBno\fR]\fBquestion\fR
+Show question section.
+.TP
+\fB+\fR[\fBno\fR]\fBanswer\fR
+Show answer section.
+.TP
+\fB+\fR[\fBno\fR]\fBauthority\fR
+Show authority section.
+.TP
+\fB+\fR[\fBno\fR]\fBadditional\fR
+Show additional section.
+.TP
+\fB+\fR[\fBno\fR]\fBstats\fR
+Show trailing packet statistics.
+.TP
+\fB+\fR[\fBno\fR]\fBcl\fR
+Show DNS class.
+.TP
+\fB+\fR[\fBno\fR]\fBttl\fR
+Show TTL value.
+.TP
+\fB+time=\fIT\fR
+Set wait for reply interval in seconds (default is 5 seconds).
+.TP
+\fB+retries=\fIN\fR
+Set number of retries (default is 2). This doesn't apply to AXFR or IXFR.
+.TP
+\fB+bufsize=\fIB\fR
+Set EDNS buffer size in bytes (default is 512 bytes).
+.TP
+\fB+\fR[\fBno\fR]\fBtcp\fR
+Use TCP protocol.
+.TP
+\fB+\fR[\fBno\fR]\fBfail\fR
+Stop if SERVFAIL.
+.TP
+\fB+\fR[\fBno\fR]\fBignore\fR
+Don't use TCP automatically if truncated reply is received.
+.TP
+\fB+\fR[\fBno\fR]\fBnsid\fR
+Request nameserver identifier (NSID).
+.SH NOTE
+Options \fB-k\fR and \fB-y\fR cannot be used mutually.
+.SH EXAMPLES
+.B Example 1. Get A record for example.com:
+.TP
+# kdig example.com A
+.TP
+.B Example 2. Perform AXFR for zone example.com from the server 192.0.2.1:
+.TP
+# kdig example.com -t AXFR @192.0.2.1
+.TP 12
+.B Example 3. Send one A query for example.com from 192.0.2.1 and one reverse \
+lookup for address 2001:DB8::1 from 192.0.2.2. Both using TCP protocol:
+.TP
+# kdig +tcp example.com -t A @192.0.2.1 -x 2001:DB8::1 @192.0.2.2
+.SH FILES
+.BI /etc/resolv.conf
+.SH AUTHOR
+Daniel Salzman (\fBhttp://knot-dns.cz\fR)
+.TP
+Please send any bugs or comments to \fBknot-dns@labs.nic.cz\fR
+.SH SEE ALSO
+.BI khost\fR(8),
+.BI knsupdate\fR(8).
diff --git a/man/khost.1 b/man/khost.1
new file mode 100644
index 0000000..f68519a
--- /dev/null
+++ b/man/khost.1
@@ -0,0 +1,89 @@
+.TH "khost" "1" "April 2013" "CZ.NIC Labs" "Knot DNS, version 1.3.0-rc3"
+.SH NAME
+.B khost
+\- Simple DNS lookup utility (libknot equivalent of ISC host)
+.SH SYNOPSIS
+.B khost
+[\fIoptions\fR] \fIname\fR [\fIserver\fR]
+.SH DESCRIPTION
+This utility sends a DNS query for the \fIname\fR to the \fIserver\fR and prints
+a reply in more user-readable form. For more advanced DNS queries use \fBkdig\fR instead.
+.TP 4
+\fI name\fR
+Is a domain name that is to be looked up.
+If the \fIname\fR is IPv4 or IPv6 address the \fIPTR\fR query type is used.
+.TP
+\fI server\fR
+Is a name or an address of the nameserver to send a query to. The address
+can be specified using [address]:port notation. If no server is specified
+the servers from \fB/etc/resolv.conf\fR are used.
+.TP
+If no arguments are provided, \fBkhost\fR prints short help.
+.SH OPTIONS
+.TP 4
+.BI -4
+Use IPv4 protocol only.
+.TP
+.BI -6
+Use IPv6 protocol only.
+.TP
+.BI -a
+Send ANY query with verbose mode.
+.TP
+.BI -d
+Enable debug messages if any.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help.
+.TP
+.BI -r
+Disable recursion.
+.TP
+.BI -s
+Stop quering next nameserver if SERVFAIL response is received.
+.TP
+.BI -T
+Use TCP protocol.
+.TP
+.BI -v
+Enable verbose output.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print program version.
+.TP
+.BI -w
+Wait forever for the reply.
+.TP
+.BI -c \ class
+Set query class (e.g. \fICH\fR, \fICLASS4\fR). The default class is \fIIN\fR.
+.TP
+.BI -t \ type
+Set query type (e.g. \fINS\fR, \fIIXFR=12345\fR, \fITYPE65535\fR).
+The default is to send 3 queries (\fIA\fR, \fIAAAA\fR and \fIMX\fR).
+.TP
+.BI -R \ retries
+The number of UDP retries to query a nameserver. The default is \fI1\fR.
+.TP
+.BI -W \ wait
+The time to wait for a reply in seconds. The default is \fI2\fR seconds.
+.SH EXAMPLES
+.B Example 1. Get A, AAAA and MX records for example.com:
+.TP
+# khost example.com
+.TP
+.B Example 2. Get reverse record for address 192.0.2.1:
+.TP
+# khost 192.0.2.1
+.TP
+.B Example 3. Perform verbose zone transfer for zone example.com:
+.TP
+# khost -t AXFR -v example.com
+.SH FILES
+.BI /etc/resolv.conf
+.SH AUTHOR
+Daniel Salzman (\fBhttp://knot-dns.cz\fR)
+.TP
+Please send any bugs or comments to \fBknot-dns@labs.nic.cz\fR
+.SH SEE ALSO
+.BI kdig\fR(8),
+.BI knsupdate\fR(8).
diff --git a/man/khost.1.in b/man/khost.1.in
new file mode 100644
index 0000000..a931968
--- /dev/null
+++ b/man/khost.1.in
@@ -0,0 +1,89 @@
+.TH "khost" "1" "April 2013" "CZ.NIC Labs" "Knot DNS, version @VERSION@"
+.SH NAME
+.B khost
+\- Simple DNS lookup utility (libknot equivalent of ISC host)
+.SH SYNOPSIS
+.B khost
+[\fIoptions\fR] \fIname\fR [\fIserver\fR]
+.SH DESCRIPTION
+This utility sends a DNS query for the \fIname\fR to the \fIserver\fR and prints
+a reply in more user-readable form. For more advanced DNS queries use \fBkdig\fR instead.
+.TP 4
+\fI name\fR
+Is a domain name that is to be looked up.
+If the \fIname\fR is IPv4 or IPv6 address the \fIPTR\fR query type is used.
+.TP
+\fI server\fR
+Is a name or an address of the nameserver to send a query to. The address
+can be specified using [address]:port notation. If no server is specified
+the servers from \fB/etc/resolv.conf\fR are used.
+.TP
+If no arguments are provided, \fBkhost\fR prints short help.
+.SH OPTIONS
+.TP 4
+.BI -4
+Use IPv4 protocol only.
+.TP
+.BI -6
+Use IPv6 protocol only.
+.TP
+.BI -a
+Send ANY query with verbose mode.
+.TP
+.BI -d
+Enable debug messages if any.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help.
+.TP
+.BI -r
+Disable recursion.
+.TP
+.BI -s
+Stop quering next nameserver if SERVFAIL response is received.
+.TP
+.BI -T
+Use TCP protocol.
+.TP
+.BI -v
+Enable verbose output.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print program version.
+.TP
+.BI -w
+Wait forever for the reply.
+.TP
+.BI -c \ class
+Set query class (e.g. \fICH\fR, \fICLASS4\fR). The default class is \fIIN\fR.
+.TP
+.BI -t \ type
+Set query type (e.g. \fINS\fR, \fIIXFR=12345\fR, \fITYPE65535\fR).
+The default is to send 3 queries (\fIA\fR, \fIAAAA\fR and \fIMX\fR).
+.TP
+.BI -R \ retries
+The number of UDP retries to query a nameserver. The default is \fI1\fR.
+.TP
+.BI -W \ wait
+The time to wait for a reply in seconds. The default is \fI2\fR seconds.
+.SH EXAMPLES
+.B Example 1. Get A, AAAA and MX records for example.com:
+.TP
+# khost example.com
+.TP
+.B Example 2. Get reverse record for address 192.0.2.1:
+.TP
+# khost 192.0.2.1
+.TP
+.B Example 3. Perform verbose zone transfer for zone example.com:
+.TP
+# khost -t AXFR -v example.com
+.SH FILES
+.BI /etc/resolv.conf
+.SH AUTHOR
+Daniel Salzman (\fBhttp://knot-dns.cz\fR)
+.TP
+Please send any bugs or comments to \fBknot-dns@labs.nic.cz\fR
+.SH SEE ALSO
+.BI kdig\fR(8),
+.BI knsupdate\fR(8).
diff --git a/src/knot.conf.5 b/man/knot.conf.5
index 361bbb1..00d7542 100644
--- a/src/knot.conf.5
+++ b/man/knot.conf.5
@@ -1,8 +1,8 @@
-.TH "knot.conf" "5" "March 2013" "CZ.NIC Labs" "Knot DNS, version 1.2.0"
+.TH "knot.conf" "5" "September 2012" "CZ.NIC Labs" "Knot DNS, version 1.3.0-rc3"
.SH "NAME"
.LP
.B knot.conf
-\- Configuration file manual for Knot DNS server.
+\- Configuration file manual for Knot DNS server.
.SH "SYNOPSIS"
.LP
.B knot.conf
@@ -11,40 +11,37 @@
serves as an example of the configuration for knotc(8) and knotd(8).
.SH "EXAMPLE"
.LP
- #
- # knot.sample.conf
- #
- # This is a sample configuration file for Knot DNS server.
- #
-
- # This is a comment.
#
- # There are 5 main sections of this config file:
- # system, zones, interfaces, control and log
+ # There are 7 main sections of this config file:
+ # system, interfaces, remotes, groups, zones, control and log
#
# Section 'system' contains general options for the server
system {
- # Identity of the server (see RFC 4892). Not used yet.
+ # Identity of the server (see RFC 4892).
identity "I have no mouth and must scream";
- # Version of the server (see RFC 4892). Not used yet.
- version "1.2;
+ # Version of the server (see RFC 4892).
+ version "1.3";
- # Server identifier
+ # Host name of the server (see RFC 4892).
+ hostname "myserver0.ns.example.com";
+
+ # Server identifier
# Use string format "text"
# Or hexstring 0x01ab00
nsid "myserver0";
# Working directory of the server
# Used to store compiled zones and PID file
- storage "/tmp/knot-sample";
+ # default: ${sharedstatedir}/knot, configured with --with-storage
+ storage "/var/lib/knot";
- # Custom pidfile path
- # default: pidfile is created in 'storage'.
- pidfile "/tmp/knot.pid";
+ # Directory for storing run-time data
+ # default: ${localstatedir}/run/knot, configured with --with-rundir
+ rundir "/var/run/knot";
# Number of workers per interface
# This option is used to force number of threads used per interface
@@ -74,6 +71,12 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# Default: 10s
max-conn-reply 10s;
+ # Number of parallel transfers
+ # This number also includes pending SOA queries
+ # Minimal value is number of CPUs
+ # Default: 10
+ transfers 10;
+
# Rate limit
# in queries / second
# Default: off (=0)
@@ -83,47 +86,53 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# Number of hashtable buckets, set to reasonable value as default.
# We chose a reasonably large prime number as it's used for hashtable size,
# it is recommended to do so as well due to better distribution.
- # Tweak if you experience a lot of hash collisions, estimated memory overhead
- # is approx. 16B per bucket
- # Default: 1572869
- rate-limit-size 1572869;
+ # Rule of thumb is to set it to about 1.2 * (maximum_qps)
+ # Memory cost is approx. 32B per bucket
+ # Default: 393241
+ rate-limit-size 393241;
- # Rate limit SLIP
+ # Rate limit SLIP
# Each Nth blocked response will be sent as truncated, this is a way to allow
- # legitimate requests to get a chance to reconnect using TCP
+ # legitimate requests to get a chance to reconnect using TCP
# Default: 2
rate-limit-slip 2;
}
- # Section 'keys' contains list of TSIG keys
- keys {
+ # Includes can be placed anywhere at any level in the configuration file. The
+ # file name can be relative to current file or absolute.
+ #
+ # This include includes keys which are commented out in next section.
+ include "knot.keys.conf";
- # TSIG key
- #
- # format: name key-type "<key>";
- # where key-type may be one of the following:
- # hmac-md5
- # hmac-sha1
- # hmac-sha224
- # hmac-sha256
- # hmac-sha384
- # hmac-sha512
- # and <key> is the private key
- key0.server0 hmac-md5 "Wg==";
-
- # TSIG key for zone
- key0.example.com hmac-md5 "==gW";
- }
+ # Section 'keys' contains list of TSIG keys
+ #keys {
+ #
+ # # TSIG key
+ # #
+ # # format: name key-type "<key>";
+ # # where key-type may be one of the following:
+ # # hmac-md5
+ # # hmac-sha1
+ # # hmac-sha224
+ # # hmac-sha256
+ # # hmac-sha384
+ # # hmac-sha512
+ # # and <key> is the private key
+ # key0.server0 hmac-md5 "Wg==";
+ #
+ # # TSIG key for zone
+ # key0.example.com hmac-md5 "==gW";
+ #}
# Section 'interfaces' contains definitions of listening interfaces.
interfaces {
# Interface entry
- #
+ #
# Format 1: <name> { address <address>; [port <port>;] }
ipv4 { # <name> is an arbitrary symbolic name
address 127.0.0.1; # <address> may be ither IPv4 or IPv6 address
- port 53531; # port is required for XFR/IN and NOTIFY/OUT
+ port 53531; # port is required for XFR/IN and NOTIFY/OUT
}
# Format 2: <name> { address <address>@<port>; }
@@ -163,21 +172,35 @@ serves as an example of the configuration for knotc(8) and knotd(8).
server1 {
address 127.0.0.1@53001;
}
+
+ admin-alice {
+ address 192.168.100.1;
+ }
+
+ admin-bob {
+ address 192.168.100.2;
+ }
+ }
+
+ groups {
+ admins { admin-alice, admin-bob }
}
# Section 'control' specifies on which interface to listen for RC commands
control {
# Specifies interface, syntax is exactly the same as in 'interfaces' section
- # Note: as of now, it is possible replay commands in a short time frame
- # with MitM type attacks, so you should keep the interface on localnet.
- # Default port is: 5553
- listen-on { address 127.0.0.1@5553; }
-
+ # Default: OFF
+ listen-on "knot.sock";
+
+ # As an alternative, you can use an IPv4/v6 address and port
+ # listen-on { address 127.0.0.1@5533; }
+
# Specifies ACL list for remote control
# Same syntax as for ACLs in zones
- # List of remotes delimited by comma
- allow server0;
+ # List of remotes or groups delimited by comma
+ # Notice: keep in mind that ACLs bear no effect with UNIX sockets
+ # allow server0, admins;
}
# Section 'zones' contains information about zones to be served.
@@ -195,7 +218,7 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# Possible values: on|off
# Default value: off
semantic-checks off;
-
+
# Disable ANY type queries for authoritative answers (if 'on')
# Possible values: on|off
# Default value: off
@@ -233,7 +256,7 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# it is considered relative to the current directory from which the server
# was started.
file "samples/example.com.zone";
-
+
# Build differences from zone file changes
# Possible values: on|off
# Default value: off
@@ -266,34 +289,34 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# f.e. 1s = 1 second, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
zonefile-sync 1h;
- # XFR master server
+ # XFR master server
xfr-in server0;
# ACL list of XFR slaves
xfr-out server0, server1;
- # ACL list of servers allowed to send NOTIFY queries
+ # ACL list of servers allowed to send NOTIFY queries
notify-in server0;
- # List of servers to send NOTIFY to
+ # List of servers to send NOTIFY to
notify-out server0, server1;
# List of servers to allow UPDATE queries
- update-in server0;
+ update-in server0, admins;
}
}
# Section 'log' configures logging of server messages.
#
- # Logging recognizes 3 symbolic names of log devices:
+ # Logging recognizes 3 symbolic names of log devices:
# stdout - Standard output
# stderr - Standard error output
# syslog - Syslog
- #
+ #
# In addition, arbitrary number of log files may be specified (see below).
#
# Log messages are characterized by severity and category.
- # Supported severities:
+ # Supported severities:
# debug - Debug messages. Must be turned on at compile time.
# info - Informational messages.
# notice - Notices and hints.
@@ -312,8 +335,8 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# any - All categories
#
# More severities (separated by commas) may be listed for each category.
- # All applicable severities must be listed.
- # (I.e. specifying 'error' severity does mean: 'log error messages',
+ # All applicable severities must be listed.
+ # (I.e. specifying 'error' severity does mean: 'log error messages',
# and NOT 'log all messages of severity error and above'.)
#
# Default settings (in case there are no entries in 'log' section or the section
@@ -325,14 +348,14 @@ serves as an example of the configuration for knotc(8) and knotd(8).
# Log entry
#
- # Format 1:
- # <log> {
- # <category1> <severity1> [, <severity2> ...];
+ # Format 1:
+ # <log> {
+ # <category1> <severity1> [, <severity2> ...];
# <category2> <severity1> [, <severity2> ...];
# ...
- # }
+ # }
syslog { # <log> is a symbolic name of a log device (see above)
- # log errors of any category
+ # log errors of any category
any error; # for <category> and <severity> see above
# log also warnings and notices from category 'zone'
zone warning, notice;
diff --git a/man/knot.conf.5.in b/man/knot.conf.5.in
new file mode 100644
index 0000000..d8a0d67
--- /dev/null
+++ b/man/knot.conf.5.in
@@ -0,0 +1,383 @@
+.TH "knot.conf" "5" "September 2012" "CZ.NIC Labs" "Knot DNS, version @VERSION@"
+.SH "NAME"
+.LP
+.B knot.conf
+\- Configuration file manual for Knot DNS server.
+.SH "SYNOPSIS"
+.LP
+.B knot.conf
+.SH "DESCRIPTION"
+.B knot.conf
+serves as an example of the configuration for knotc(8) and knotd(8).
+.SH "EXAMPLE"
+.LP
+
+ #
+ # There are 7 main sections of this config file:
+ # system, interfaces, remotes, groups, zones, control and log
+ #
+
+ # Section 'system' contains general options for the server
+ system {
+
+ # Identity of the server (see RFC 4892).
+ identity "I have no mouth and must scream";
+
+ # Version of the server (see RFC 4892).
+ version "1.3";
+
+ # Host name of the server (see RFC 4892).
+ hostname "myserver0.ns.example.com";
+
+ # Server identifier
+ # Use string format "text"
+ # Or hexstring 0x01ab00
+ nsid "myserver0";
+
+ # Working directory of the server
+ # Used to store compiled zones and PID file
+ # default: ${sharedstatedir}/knot, configured with --with-storage
+ storage "/var/lib/knot";
+
+ # Directory for storing run-time data
+ # default: ${localstatedir}/run/knot, configured with --with-rundir
+ rundir "/var/run/knot";
+
+ # Number of workers per interface
+ # This option is used to force number of threads used per interface
+ # Default: unset (auto-estimates optimal value from the number of online CPUs)
+ # workers 3;
+
+ # User for running server
+ # May also specify user.group (e.g. knot.users)
+ # user knot.users;
+
+ # Maximum idle time between requests on a TCP connection
+ # It is also possible to suffix with unit size [s/m/h/d]
+ # f.e. 1s = 1 second, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
+ # Default: 60s
+ max-conn-idle 60s;
+
+ # Maximum time between newly accepted TCP connection and first query
+ # This is useful to disconnect inactive connections faster
+ # It is also possible to suffix with unit size [s/m/h/d]
+ # f.e. 1s = 1 second, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
+ # Default: 10s
+ max-conn-handshake 10s;
+
+ # Maximum time to wait for a reply to SOA query
+ # It is also possible to suffix with unit size [s/m/h/d]
+ # f.e. 1s = 1 second, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
+ # Default: 10s
+ max-conn-reply 10s;
+
+ # Number of parallel transfers
+ # This number also includes pending SOA queries
+ # Minimal value is number of CPUs
+ # Default: 10
+ transfers 10;
+
+ # Rate limit
+ # in queries / second
+ # Default: off (=0)
+ rate-limit 0;
+
+ # Rate limit bucket size
+ # Number of hashtable buckets, set to reasonable value as default.
+ # We chose a reasonably large prime number as it's used for hashtable size,
+ # it is recommended to do so as well due to better distribution.
+ # Rule of thumb is to set it to about 1.2 * (maximum_qps)
+ # Memory cost is approx. 32B per bucket
+ # Default: 393241
+ rate-limit-size 393241;
+
+ # Rate limit SLIP
+ # Each Nth blocked response will be sent as truncated, this is a way to allow
+ # legitimate requests to get a chance to reconnect using TCP
+ # Default: 2
+ rate-limit-slip 2;
+ }
+
+ # Includes can be placed anywhere at any level in the configuration file. The
+ # file name can be relative to current file or absolute.
+ #
+ # This include includes keys which are commented out in next section.
+ include "knot.keys.conf";
+
+ # Section 'keys' contains list of TSIG keys
+ #keys {
+ #
+ # # TSIG key
+ # #
+ # # format: name key-type "<key>";
+ # # where key-type may be one of the following:
+ # # hmac-md5
+ # # hmac-sha1
+ # # hmac-sha224
+ # # hmac-sha256
+ # # hmac-sha384
+ # # hmac-sha512
+ # # and <key> is the private key
+ # key0.server0 hmac-md5 "Wg==";
+ #
+ # # TSIG key for zone
+ # key0.example.com hmac-md5 "==gW";
+ #}
+
+ # Section 'interfaces' contains definitions of listening interfaces.
+ interfaces {
+
+ # Interface entry
+ #
+ # Format 1: <name> { address <address>; [port <port>;] }
+ ipv4 { # <name> is an arbitrary symbolic name
+ address 127.0.0.1; # <address> may be ither IPv4 or IPv6 address
+ port 53531; # port is required for XFR/IN and NOTIFY/OUT
+ }
+
+ # Format 2: <name> { address <address>@<port>; }
+ # shortipv4 {
+ # address 127.0.0.1@53532;
+ #}
+
+ # Format 1 (IPv6 interface)
+ # ipv6 {
+ # address ::1@53533;
+ # }
+
+ # Format 2 (IPv6 interface)
+ # ipv6b {
+ # address [::1]@53534;
+ # }
+
+ }
+
+ # Section 'remotes' contains symbolic names for remote servers.
+ # Syntax for 'remotes' is the same as for 'interfaces'.
+ remotes {
+
+ # Remote entry
+ #
+ # Format 1: <name> { address <address>; [port <port>;] }
+ server0 { # <name> is an arbitrary symbolic name
+ address 127.0.0.1; # <address> may be ither IPv4 or IPv6 address
+ port 53531; # port is optional (default: 53)
+ key key0.server0; # (optional) specification of TSIG key associated for this remote
+ via ipv4; # (optional) source interface for queries
+ via 82.35.64.59; # (optional) source interface for queries, direct IPv4
+ via [::cafe]; # (optional) source interface for queries, direct IPv6
+ }
+
+ # Format 2: <name> { address <address>@<port>; }
+ server1 {
+ address 127.0.0.1@53001;
+ }
+
+ admin-alice {
+ address 192.168.100.1;
+ }
+
+ admin-bob {
+ address 192.168.100.2;
+ }
+ }
+
+ groups {
+ admins { admin-alice, admin-bob }
+ }
+
+ # Section 'control' specifies on which interface to listen for RC commands
+ control {
+
+ # Specifies interface, syntax is exactly the same as in 'interfaces' section
+ # Default: OFF
+ listen-on "knot.sock";
+
+ # As an alternative, you can use an IPv4/v6 address and port
+ # listen-on { address 127.0.0.1@5533; }
+
+ # Specifies ACL list for remote control
+ # Same syntax as for ACLs in zones
+ # List of remotes or groups delimited by comma
+ # Notice: keep in mind that ACLs bear no effect with UNIX sockets
+ # allow server0, admins;
+ }
+
+ # Section 'zones' contains information about zones to be served.
+ zones {
+
+ # Shared options for all listed zones
+ #
+
+ # Build differences from zone file changes. EXPERIMENTAL feature.
+ # Possible values: on|off
+ # Default value: off
+ ixfr-from-differences off;
+
+ # Enable semantic checks for all zones (if 'on')
+ # Possible values: on|off
+ # Default value: off
+ semantic-checks off;
+
+ # Disable ANY type queries for authoritative answers (if 'on')
+ # Possible values: on|off
+ # Default value: off
+ disable-any off;
+
+ # NOTIFY response timeout
+ # Possible values: <1,...> (seconds)
+ # Default value: 60
+ notify-timeout 60;
+
+ # Number of retries for NOTIFY
+ # Possible values: <1,...>
+ # Default value: 5
+ notify-retries 5;
+
+ # Timeout for syncing changes from zone database to zonefile
+ # Possible values: <1..INT_MAX> (seconds)
+ # Default value: 1h (1 hour)
+ # It is also possible to suffix with unit size [s/m/h/d]
+ # f.e. 1s = 1 day, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
+ zonefile-sync 1h;
+
+ # File size limit for IXFR journal
+ # Possible values: <1..INT_MAX>
+ # Default value: N/A (infinite)
+ # It is also possible to suffix with unit size [k/M/G]
+ # f.e. 1k, 100M, 2G
+ ixfr-fslimit 1G;
+
+ # Zone entry
+ #
+ # Format: <zone-name> { file "<path-to-zone-file>"; }
+ example.com { # <zone-name> is the DNS name of the zone (zone root)
+ # <path-to-zone-file> may be either absolute or relative, in which case
+ # it is considered relative to the current directory from which the server
+ # was started.
+ file "samples/example.com.zone";
+
+ # Build differences from zone file changes
+ # Possible values: on|off
+ # Default value: off
+ ixfr-from-differences off;
+
+ # Disable ANY type queries for authoritative answers (if 'on')
+ # Possible values: on|off
+ # Default value: off
+ disable-any off;
+
+ # Enable zone semantic checks
+ # Possible values: on|off
+ # Default value: off
+ semantic-checks on;
+
+ # NOTIFY response timeout (specific for current zone)
+ # Possible values: <1,...> (seconds)
+ # Default value: 60
+ notify-timeout 60;
+
+ # Number of retries for NOTIFY (specific for current zone)
+ # Possible values: <1,...>
+ # Default value: 5
+ notify-retries 5;
+
+ # Timeout for syncing changes from zone database to zonefile
+ # Possible values: <1..INT_MAX> (seconds)
+ # Default value: inherited from zones.zonefile-sync
+ # It is also possible to suffix with unit size [s/m/h/d]
+ # f.e. 1s = 1 second, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
+ zonefile-sync 1h;
+
+ # XFR master server
+ xfr-in server0;
+
+ # ACL list of XFR slaves
+ xfr-out server0, server1;
+
+ # ACL list of servers allowed to send NOTIFY queries
+ notify-in server0;
+
+ # List of servers to send NOTIFY to
+ notify-out server0, server1;
+
+ # List of servers to allow UPDATE queries
+ update-in server0, admins;
+ }
+ }
+
+ # Section 'log' configures logging of server messages.
+ #
+ # Logging recognizes 3 symbolic names of log devices:
+ # stdout - Standard output
+ # stderr - Standard error output
+ # syslog - Syslog
+ #
+ # In addition, arbitrary number of log files may be specified (see below).
+ #
+ # Log messages are characterized by severity and category.
+ # Supported severities:
+ # debug - Debug messages. Must be turned on at compile time.
+ # info - Informational messages.
+ # notice - Notices and hints.
+ # warning - Warnings. An action from the operator may be required.
+ # error - Recoverable error. Some action should be taken.
+ # fatal - Non-recoverable errors resulting in server shutdown.
+ # (Not supported yet.)
+ # all - All severities.
+ #
+ # Categories designate the source of the log message and roughly correspond
+ # to server modules
+ # Supported categories:
+ # server - Messages related to general operation of the server.
+ # zone - Messages related to zones, zone parsing and loading.
+ # answering - Messages regarding query processing and response creation.
+ # any - All categories
+ #
+ # More severities (separated by commas) may be listed for each category.
+ # All applicable severities must be listed.
+ # (I.e. specifying 'error' severity does mean: 'log error messages',
+ # and NOT 'log all messages of severity error and above'.)
+ #
+ # Default settings (in case there are no entries in 'log' section or the section
+ # is missing at all):
+ #
+ # stderr { any error; }
+ # syslog { any error; }
+ log {
+
+ # Log entry
+ #
+ # Format 1:
+ # <log> {
+ # <category1> <severity1> [, <severity2> ...];
+ # <category2> <severity1> [, <severity2> ...];
+ # ...
+ # }
+ syslog { # <log> is a symbolic name of a log device (see above)
+ # log errors of any category
+ any error; # for <category> and <severity> see above
+ # log also warnings and notices from category 'zone'
+ zone warning, notice;
+ # log info from server
+ server info;
+ }
+
+ # Log fatal, warnings and errors to stderr
+ stderr {
+ any error, warning;
+ }
+
+ # Format 2:
+ # file <path> {
+ # <category1> <severity1> [, <severity2> ...];
+ # <category2> <severity1> [, <severity2> ...];
+ # }
+ file "/tmp/knot-sample/knotd.debug" { # <path> is absolute or relative path to log file
+ server debug;
+ }
+ }
+
+.SH "SEE ALSO"
+.LP
+knotd(8), knotc(8)
diff --git a/src/knotc.8 b/man/knotc.8
index b043ebe..7864cff 100644
--- a/src/knotc.8
+++ b/man/knotc.8
@@ -1,4 +1,4 @@
-.TH knotc "8" "March 2013" "CZ.NIC Labs" "Knot DNS, version 1.2.0"
+.TH knotc "8" "September 2012" "CZ.NIC Labs" "Knot DNS, version 1.3.0-rc3"
.SH NAME
.B knotc
\- Knot DNS control utility
@@ -10,16 +10,13 @@
.HP
\fB\-c\fR [file], \fB\-\-config\fR=\fI[file]\fR Select configuration file.
.TP
-\fB\-j\fR [num], \fB\-\-jobs\fR=\fI[num]\fR
-Number of parallel tasks to run (only for 'compile').
+\fB\-s\fR [server]\fR Remote UNIX socket/IP address (default @rundir@/knot.sock)
.TP
-\fB\-s\fR [server]\fR Remote server address (default 127.0.0.1)
-.TP
-\fB\-p\fR [port]\fR Remote server port (default 5553)
+\fB\-p\fR [port]\fR Remote server port (only for IP).
.TP
\fB\-y\fR [hmac:]name:key]\fR Use key_id for specified on the command line.
.TP
-\fB\-k\fR [file]\fR Use key file (as in config section 'keys').
+\fB\-k\fR [file]\fR Use key file (as in config section 'keys').
f.e. echo "knotc-key hmac-md5 Wg==" > knotc.key
If you omit algorithm, hmac-md5 will be used as default.
.TP
@@ -38,9 +35,6 @@ Wait for the server to finish start/stop operations.
\fB\-i\fR, \fB\-\-interactive\fR
Interactive mode (do not daemonize).
.TP
-\fB\-a\fR, \fB\-\-auto\fR
-Enable automatic recompilation (start or reload).
-.TP
\fB\-h\fR, \fB\-\-help\fR
Print help and usage.
.SS "Actions:"
@@ -55,7 +49,7 @@ restart
Stops and then starts knot server daemon.
.TP
reload
-Reload knot configuration and compiled zones.
+Reload knot configuration and zones.
.TP
flush
Flush journal and update zone files.
@@ -66,9 +60,6 @@ Check if server is running.
zonestatus
Show status of configured zones.
.TP
-compile
-Compile zone file.
-.TP
refresh
Refresh slave zones (all if not specified).
.TP
@@ -77,11 +68,14 @@ Check server configuration.
.TP
checkzone
Check zones before compiling (accepts specific zones, f.e. 'knotc checkzone example1.com example2.com').
-.SS "EXAMPLES"
+.TP
+memstats
+Estimate memory consumption for zone files. Useful mainly for big zones.
+.SS "EXAMPLES"
.TP
.B Setup a keyfile for remote control
.TP
-1. Generate keys
+1. Generate keys
dnssec-keygen -a hmac-md5 -b 256 -n HOST knotc-key
.TP
2. Extract secret in base64 format and create keyfile
diff --git a/man/knotc.8.in b/man/knotc.8.in
new file mode 100644
index 0000000..f845c96
--- /dev/null
+++ b/man/knotc.8.in
@@ -0,0 +1,101 @@
+.TH knotc "8" "September 2012" "CZ.NIC Labs" "Knot DNS, version @VERSION@"
+.SH NAME
+.B knotc
+\- Knot DNS control utility
+.SH SYNOPSIS
+.B knotc
+[\fIparameters\fR] \fI<action>\fR [\fIaction_args\fR]
+.SH DESCRIPTION
+.SS "Parameters:"
+.HP
+\fB\-c\fR [file], \fB\-\-config\fR=\fI[file]\fR Select configuration file.
+.TP
+\fB\-s\fR [server]\fR Remote UNIX socket/IP address (default @rundir@/knot.sock)
+.TP
+\fB\-p\fR [port]\fR Remote server port (only for IP).
+.TP
+\fB\-y\fR [hmac:]name:key]\fR Use key_id for specified on the command line.
+.TP
+\fB\-k\fR [file]\fR Use key file (as in config section 'keys').
+f.e. echo "knotc-key hmac-md5 Wg==" > knotc.key
+If you omit algorithm, hmac-md5 will be used as default.
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Force operation \- override some checks.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Verbose mode \- additional runtime information.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print knot server version.
+.TP
+\fB\-w\fR, \fB\-\-wait\fR
+Wait for the server to finish start/stop operations.
+.TP
+\fB\-i\fR, \fB\-\-interactive\fR
+Interactive mode (do not daemonize).
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help and usage.
+.SS "Actions:"
+.TP
+start
+Start knot server daemon (no\-op if running).
+.TP
+stop
+Stop knot server daemon (no\-op if not running).
+.TP
+restart
+Stops and then starts knot server daemon.
+.TP
+reload
+Reload knot configuration and zones.
+.TP
+flush
+Flush journal and update zone files.
+.TP
+status
+Check if server is running.
+.TP
+zonestatus
+Show status of configured zones.
+.TP
+refresh
+Refresh slave zones (all if not specified).
+.TP
+checkconf
+Check server configuration.
+.TP
+checkzone
+Check zones before compiling (accepts specific zones, f.e. 'knotc checkzone example1.com example2.com').
+.TP
+memstats
+Estimate memory consumption for zone files. Useful mainly for big zones.
+.SS "EXAMPLES"
+.TP
+.B Setup a keyfile for remote control
+.TP
+1. Generate keys
+dnssec-keygen -a hmac-md5 -b 256 -n HOST knotc-key
+.TP
+2. Extract secret in base64 format and create keyfile
+echo "knotc-key hmac-md5 <secret>" > knotc.key
+
+Make sure the key can be read/written only by owner for
+security reasons.
+.TP
+
+.B Reload server remotely
+knotc -s 127.0.0.1 -k knotc.key reload
+.SH "SEE ALSO"
+The full documentation for
+.B Knot
+is maintained as a Texinfo manual. If the
+.B info
+and
+.B Knot
+programs are properly installed at your site, the command
+.IP
+.B info Knot
+.PP
+should give you access to the complete manual.
diff --git a/src/knotd.8 b/man/knotd.8
index 426668c..1809c9c 100644
--- a/src/knotd.8
+++ b/man/knotd.8
@@ -1,4 +1,4 @@
-.TH "knotd" "8" "March 2013" "CZ.NIC Labs" "Knot DNS, version 1.2.0"
+.TH "knotd" "8" "September 2012" "CZ.NIC Labs" "Knot DNS, version 1.3.0-rc3"
.SH NAME
.B knotd
\- Knot DNS daemon
diff --git a/man/knotd.8.in b/man/knotd.8.in
new file mode 100644
index 0000000..83088c5
--- /dev/null
+++ b/man/knotd.8.in
@@ -0,0 +1,35 @@
+.TH "knotd" "8" "September 2012" "CZ.NIC Labs" "Knot DNS, version @VERSION@"
+.SH NAME
+.B knotd
+\- Knot DNS daemon
+.SH SYNOPSIS
+.B knotd
+[\fIparameters\fR]
+.SH DESCRIPTION
+.SS "Parameters:"
+.HP
+\fB\-c\fR, \fB\-\-config\fR [file] Select configuration file.
+.TP
+\fB\-d\fR, \fB\-\-daemonize\fR
+Run server as a daemon.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Verbose mode \- additional runtime information.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print version of the server.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print help and usage.
+.SH "SEE ALSO"
+The full documentation for
+.B Knot
+is maintained as a Texinfo manual. If the
+.B info
+and
+.B Knot
+programs are properly installed at your site, the command
+.IP
+.B info Knot
+.PP
+should give you access to the complete manual.
diff --git a/man/knsupdate.1 b/man/knsupdate.1
new file mode 100644
index 0000000..5d2bd32
--- /dev/null
+++ b/man/knsupdate.1
@@ -0,0 +1,147 @@
+.TH "knsupdate" "1" "April 2013" "CZ.NIC Labs" "Knot DNS, version 1.3.0-rc3"
+.SH NAME
+.TP 10
+.B knsupdate
+\- Dynamic DNS update utility (libknot equivalent of ISC nsupdate)
+.SH SYNOPSIS
+.B knsupdate
+[\fIoptions\fR] [\fIfilename\fR]
+
+.SH DESCRIPTION
+
+The utility sends Dynamic DNS update message to DNS server. Update content is
+read from a file (if the parameter \fIfilename\fR is given) or from standard
+input. The format of the update is described in \fBINPUT FORMAT\fR section.
+
+.SH OPTIONS
+.TP 4
+.BI -d
+Enable debugging messages.
+.TP
+.BI -v
+Use TCP protocol instead of the default UDP.
+.TP
+.BI -p \ port
+Set the port to use when connecting to server and the port was not explicitly
+specified in the update. The default is 53.
+.TP
+.BI -t \ timeout
+The timeout of the update request in seconds. The default is 12. If set to
+zero, the timeout is infinite.
+.TP
+.BI -r \ retries
+The number of retries for UDP requests. The default is 3. Partial timeout for
+each try is computed from total timeout (option \fB-t\fR).
+.TP
+.BI -k \ keyfile
+Use TSIG or SIG\-0 key stored in file to authenticate the request. The tool
+supports keys generated by ISC \fBdnssec\-keygen\fR. The key comprises of
+public (.key extension) and private part (.private extension). Either of these
+file names or a name without the extension can be specified as \fIkeyfile\fR
+parameter.
+
+.TP
+.BI -y \ \fR[\fIhmac:\fR]\fIname:key
+Use TSIG key to authenticate the request. The \fIhmac\fR part specifies the
+algorithm (the default is hmac\-md5), \fIname\fR specifies the key name, and
+\fIkey\fR specifies the shared secret encoded in Base64.
+
+.TP
+\fB\-\-help\fR
+Print help.
+
+.TP
+\fB\-\-version\fR
+Print program version.
+
+.TP
+Options \fB-k\fR and \fB-y\fR cannot be used mutually.
+
+.SH INPUT FORMAT
+
+The input format is textual and is made up of commands. Every command is placed
+on a separate line of the input. Lines starting with a semicolon are comments
+and are not processed.
+
+List of commands format and their description:
+
+.TP
+\fBserver\fR \fIname\fR [\fIport\fR]
+
+Specifies a receiving server of the dynamic update message. Parameter \fIname\fR
+can be either a host name or an IP address. If the \fIport\fR is not specified,
+default port is used. The default port value can be controlled using program
+option \fB-p\fR.
+
+.TP
+\fBzone\fR \fIname\fR
+
+Specifies that all updates are done within a zone named \fIname\fR. If not used,
+the default zone is the root zone.
+
+.TP
+\fBorigin\fR \fIname\fR
+
+Specifies fully qualified domain name suffix which is appended to
+non-fqd owners in update commands. The default origin is the root zone.
+
+.TP
+\fBclass\fR \fIname\fR
+
+Sets \fIname\fR as a default class for all updates. If not used, the default
+class is IN.
+
+.TP
+\fBttl\fR \fIvalue\fR
+
+Sets \fIvalue\fR as a default TTL (time to live) in seconds. If not used, the
+default value is zero.
+
+.TP
+\fBkey\fB \fIname\fR \fIkey\fR
+
+Specifies TSIG key to authenticate the request. This command has the same
+semantics as the program option \fB\-y\fR, except that the MAC algorithm
+cannot be set.
+
+.TP
+[\fBupdate\fR] \fBadd\fR \fIname\fR \fIttl\fR [\fIclass\fR] \fItype\fR \fIdata\fR
+
+Adds a request to add a new resource record into the zone. Please note that if the
+\fIname\fR is not fully qualified domain name, current \fIorigin\fR name is appended to it.
+
+.TP
+[\fBupdate\fR] \fBdel\fR[\fBete\fR] \fIname\fR [\fIttl\fR] [\fIclass\fR] [\fItype\fR] [\fIdata\fR]
+
+Adds a request to remove all (or matching \fIclass\fR, \fItype\fR, \fIdata\fR)
+resource records from the zone. There is the same requirement for the
+\fIname\fR parameter as in the \fBupdate add\fR command. The \fIttl\fR item is ignored.
+
+.TP
+\fBshow\fR
+
+Displays current content of the update message.
+
+.TP
+\fBsend\fR
+
+Sends the current update message and cleans the list of updates.
+
+.TP
+\fBanswer\fR
+
+Displays the last answer from the server.
+
+.TP
+\fBdebug\fR
+
+Enable debugging. This command has the same meaning as program option \fB\-d\fR.
+
+.SH BUGS
+
+Please note that there are slight differences from ISC nsupdate and some
+features are not supported. Any bugs, comments, or feature requests can be sent
+to \fBknot-dns@labs.nic.cz\fR.
+.SH SEE ALSO
+.BI khost\fR(8),
+.BI kdig\fR(8).
diff --git a/man/knsupdate.1.in b/man/knsupdate.1.in
new file mode 100644
index 0000000..847475b
--- /dev/null
+++ b/man/knsupdate.1.in
@@ -0,0 +1,147 @@
+.TH "knsupdate" "1" "April 2013" "CZ.NIC Labs" "Knot DNS, version @VERSION@"
+.SH NAME
+.TP 10
+.B knsupdate
+\- Dynamic DNS update utility (libknot equivalent of ISC nsupdate)
+.SH SYNOPSIS
+.B knsupdate
+[\fIoptions\fR] [\fIfilename\fR]
+
+.SH DESCRIPTION
+
+The utility sends Dynamic DNS update message to DNS server. Update content is
+read from a file (if the parameter \fIfilename\fR is given) or from standard
+input. The format of the update is described in \fBINPUT FORMAT\fR section.
+
+.SH OPTIONS
+.TP 4
+.BI -d
+Enable debugging messages.
+.TP
+.BI -v
+Use TCP protocol instead of the default UDP.
+.TP
+.BI -p \ port
+Set the port to use when connecting to server and the port was not explicitly
+specified in the update. The default is 53.
+.TP
+.BI -t \ timeout
+The timeout of the update request in seconds. The default is 12. If set to
+zero, the timeout is infinite.
+.TP
+.BI -r \ retries
+The number of retries for UDP requests. The default is 3. Partial timeout for
+each try is computed from total timeout (option \fB-t\fR).
+.TP
+.BI -k \ keyfile
+Use TSIG or SIG\-0 key stored in file to authenticate the request. The tool
+supports keys generated by ISC \fBdnssec\-keygen\fR. The key comprises of
+public (.key extension) and private part (.private extension). Either of these
+file names or a name without the extension can be specified as \fIkeyfile\fR
+parameter.
+
+.TP
+.BI -y \ \fR[\fIhmac:\fR]\fIname:key
+Use TSIG key to authenticate the request. The \fIhmac\fR part specifies the
+algorithm (the default is hmac\-md5), \fIname\fR specifies the key name, and
+\fIkey\fR specifies the shared secret encoded in Base64.
+
+.TP
+\fB\-\-help\fR
+Print help.
+
+.TP
+\fB\-\-version\fR
+Print program version.
+
+.TP
+Options \fB-k\fR and \fB-y\fR cannot be used mutually.
+
+.SH INPUT FORMAT
+
+The input format is textual and is made up of commands. Every command is placed
+on a separate line of the input. Lines starting with a semicolon are comments
+and are not processed.
+
+List of commands format and their description:
+
+.TP
+\fBserver\fR \fIname\fR [\fIport\fR]
+
+Specifies a receiving server of the dynamic update message. Parameter \fIname\fR
+can be either a host name or an IP address. If the \fIport\fR is not specified,
+default port is used. The default port value can be controlled using program
+option \fB-p\fR.
+
+.TP
+\fBzone\fR \fIname\fR
+
+Specifies that all updates are done within a zone named \fIname\fR. If not used,
+the default zone is the root zone.
+
+.TP
+\fBorigin\fR \fIname\fR
+
+Specifies fully qualified domain name suffix which is appended to
+non-fqd owners in update commands. The default origin is the root zone.
+
+.TP
+\fBclass\fR \fIname\fR
+
+Sets \fIname\fR as a default class for all updates. If not used, the default
+class is IN.
+
+.TP
+\fBttl\fR \fIvalue\fR
+
+Sets \fIvalue\fR as a default TTL (time to live) in seconds. If not used, the
+default value is zero.
+
+.TP
+\fBkey\fB \fIname\fR \fIkey\fR
+
+Specifies TSIG key to authenticate the request. This command has the same
+semantics as the program option \fB\-y\fR, except that the MAC algorithm
+cannot be set.
+
+.TP
+[\fBupdate\fR] \fBadd\fR \fIname\fR \fIttl\fR [\fIclass\fR] \fItype\fR \fIdata\fR
+
+Adds a request to add a new resource record into the zone. Please note that if the
+\fIname\fR is not fully qualified domain name, current \fIorigin\fR name is appended to it.
+
+.TP
+[\fBupdate\fR] \fBdel\fR[\fBete\fR] \fIname\fR [\fIttl\fR] [\fIclass\fR] [\fItype\fR] [\fIdata\fR]
+
+Adds a request to remove all (or matching \fIclass\fR, \fItype\fR, \fIdata\fR)
+resource records from the zone. There is the same requirement for the
+\fIname\fR parameter as in the \fBupdate add\fR command. The \fIttl\fR item is ignored.
+
+.TP
+\fBshow\fR
+
+Displays current content of the update message.
+
+.TP
+\fBsend\fR
+
+Sends the current update message and cleans the list of updates.
+
+.TP
+\fBanswer\fR
+
+Displays the last answer from the server.
+
+.TP
+\fBdebug\fR
+
+Enable debugging. This command has the same meaning as program option \fB\-d\fR.
+
+.SH BUGS
+
+Please note that there are slight differences from ISC nsupdate and some
+features are not supported. Any bugs, comments, or feature requests can be sent
+to \fBknot-dns@labs.nic.cz\fR.
+.SH SEE ALSO
+.BI khost\fR(8),
+.BI kdig\fR(8).
diff --git a/missing b/missing
index 9a55648..86a8fc3 100755
--- a/missing
+++ b/missing
@@ -1,9 +1,10 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
-scriptversion=2012-01-06.18; # UTC
+scriptversion=2012-01-06.13; # UTC
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
@@ -25,7 +26,7 @@ scriptversion=2012-01-06.18; # UTC
# the same distribution terms that you use for the rest of that program.
if test $# -eq 0; then
- echo 1>&2 "Try '$0 --help' for more information"
+ echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
@@ -33,7 +34,7 @@ run=:
sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
-# In the cases where this matters, 'missing' is being run in the
+# In the cases where this matters, `missing' is being run in the
# srcdir already.
if test -f configure.ac; then
configure_ac=configure.ac
@@ -64,7 +65,7 @@ case $1 in
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
-Handle 'PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
@@ -73,20 +74,20 @@ Options:
--run try to run the given command, and emulate it if it fails
Supported PROGRAM values:
- aclocal touch file 'aclocal.m4'
- autoconf touch file 'configure'
- autoheader touch file 'config.h.in'
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
autom4te touch the output file, or create a stub one
- automake touch all 'Makefile.in' files
- bison create 'y.tab.[ch]', if possible, from existing .[ch]
- flex create 'lex.yy.c', if possible, from existing .c
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
help2man touch the output file
- lex create 'lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
- yacc create 'y.tab.[ch]', if possible, from existing .[ch]
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]
-Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
-'g' are ignored when checking the name.
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
Send bug reports to <bug-automake@gnu.org>."
exit $?
@@ -98,8 +99,8 @@ Send bug reports to <bug-automake@gnu.org>."
;;
-*)
- echo 1>&2 "$0: Unknown '$1' option"
- echo 1>&2 "Try '$0 --help' for more information"
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
@@ -126,7 +127,7 @@ case $1 in
exit 1
elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
# Could not run --version or --help. This is probably someone
- # running '$TOOL --version' or '$TOOL --help' to check whether
+ # running `$TOOL --version' or `$TOOL --help' to check whether
# $TOOL exists and not knowing $TOOL uses missing.
exit 1
fi
@@ -138,27 +139,27 @@ esac
case $program in
aclocal*)
echo 1>&2 "\
-WARNING: '$1' is $msg. You should only need it if
- you modified 'acinclude.m4' or '${configure_ac}'. You might want
- to install the Automake and Perl packages. Grab them from
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acinclude.m4' or \`${configure_ac}'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf*)
echo 1>&2 "\
-WARNING: '$1' is $msg. You should only need it if
- you modified '${configure_ac}'. You might want to install the
- Autoconf and GNU m4 packages. Grab them from any GNU
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`${configure_ac}'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader*)
echo 1>&2 "\
-WARNING: '$1' is $msg. You should only need it if
- you modified 'acconfig.h' or '${configure_ac}'. You might want
- to install the Autoconf and GNU m4 packages. Grab them
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`acconfig.h' or \`${configure_ac}'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
test -z "$files" && files="config.h"
@@ -175,9 +176,9 @@ WARNING: '$1' is $msg. You should only need it if
automake*)
echo 1>&2 "\
-WARNING: '$1' is $msg. You should only need it if
- you modified 'Makefile.am', 'acinclude.m4' or '${configure_ac}'.
- You might want to install the Automake and Perl packages.
+WARNING: \`$1' is $msg. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+ You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
@@ -186,10 +187,10 @@ WARNING: '$1' is $msg. You should only need it if
autom4te*)
echo 1>&2 "\
-WARNING: '$1' is needed, but is $msg.
+WARNING: \`$1' is needed, but is $msg.
You might have modified some files without having the
proper tools for further handling them.
- You can get '$1' as part of Autoconf from any GNU
+ You can get \`$1' as part of \`Autoconf' from any GNU
archive site."
file=`echo "$*" | sed -n "$sed_output"`
@@ -209,10 +210,10 @@ WARNING: '$1' is needed, but is $msg.
bison*|yacc*)
echo 1>&2 "\
-WARNING: '$1' $msg. You should only need it if
- you modified a '.y' file. You may need the Bison package
+WARNING: \`$1' $msg. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
- Bison from any GNU archive site."
+ \`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if test $# -ne 1; then
eval LASTARG=\${$#}
@@ -239,10 +240,10 @@ WARNING: '$1' $msg. You should only need it if
lex*|flex*)
echo 1>&2 "\
-WARNING: '$1' is $msg. You should only need it if
- you modified a '.l' file. You may need the Flex package
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
- Flex from any GNU archive site."
+ \`Flex' from any GNU archive site."
rm -f lex.yy.c
if test $# -ne 1; then
eval LASTARG=\${$#}
@@ -262,10 +263,10 @@ WARNING: '$1' is $msg. You should only need it if
help2man*)
echo 1>&2 "\
-WARNING: '$1' is $msg. You should only need it if
+WARNING: \`$1' is $msg. You should only need it if
you modified a dependency of a manual page. You may need the
- Help2man package in order for those modifications to take
- effect. You can get Help2man from any GNU archive site."
+ \`Help2man' package in order for those modifications to take
+ effect. You can get \`Help2man' from any GNU archive site."
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
@@ -280,12 +281,12 @@ WARNING: '$1' is $msg. You should only need it if
makeinfo*)
echo 1>&2 "\
-WARNING: '$1' is $msg. You should only need it if
- you modified a '.texi' or '.texinfo' file, or any other file
+WARNING: \`$1' is $msg. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
- call might also be the consequence of using a buggy 'make' (AIX,
- DU, IRIX). You might want to install the Texinfo package or
- the GNU make package. Grab either from any GNU archive site."
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
# The file to touch is that specified with -o ...
file=`echo "$*" | sed -n "$sed_output"`
test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
@@ -309,12 +310,12 @@ WARNING: '$1' is $msg. You should only need it if
*)
echo 1>&2 "\
-WARNING: '$1' is needed, and is $msg.
+WARNING: \`$1' is needed, and is $msg.
You might have modified some files without having the
- proper tools for further handling them. Check the 'README' file,
+ proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequisites for installing
this package. You may also peek at any GNU archive site, in case
- some other package would contain this missing '$1' program."
+ some other package would contain this missing \`$1' program."
exit 1
;;
esac
diff --git a/resource.sh b/resource.sh
index c73d681..277d95d 100755
--- a/resource.sh
+++ b/resource.sh
@@ -15,12 +15,12 @@ hd="hexdump -v -e"
fmt="\"0\" \"x\" 1/1 \"%02X\" \", \""
# Preparse source file name
-header="${1%.*}_rc"
-header=`basename ${header}`
+# header="${1%.*}_rc"
+header=$(basename ${1}_rc)
# Get file size and dump content
-size=`wc -c ${1} | awk '{print $1}' 2>/dev/null`
-dump=`${hd} "${fmt}" ${1} 2>/dev/null`
+size=$(wc -c "${1}" | awk '{print $1}' 2>/dev/null)
+dump=$(${hd} "${fmt}" "${1}" 2>/dev/null)
# Format file size variable
echo "static const unsigned ${header}_size = ${size};"
diff --git a/samples/Makefile.am b/samples/Makefile.am
index f9aa616..755ef07 100644
--- a/samples/Makefile.am
+++ b/samples/Makefile.am
@@ -5,20 +5,26 @@ edit = sed \
-e 's|@prefix[@]|$(prefix)|g' \
-e 's|@sysconfdir[@]|$(sysconfdir)|g'
-knot.sample.conf: Makefile
+knot.sample.conf: knot.sample.conf.in
rm -f $@ $@.tmp
srcdir=''; \
test -f ./$@.in || srcdir=$(srcdir)/; \
$(edit) $${srcdir}$@.in >$@.tmp
mv $@.tmp $@
-knot.sample.conf: knot.sample.conf.in
+EXTRA_DIST = knot.sample.conf.in knot.full.conf knot.keys.conf example.com.zone
install-data-local: knot.sample.conf
[ -d $(DESTDIR)/$(sysconfdir) ] || \
$(INSTALL) -d $(DESTDIR)/$(sysconfdir)
[ -f $(DESTDIR)/$(sysconfdir)/knot.sample.conf ] || \
- $(INSTALL_DATA) knot.sample.conf example.com.zone $(DESTDIR)/$(sysconfdir)
+ $(INSTALL_DATA) knot.sample.conf $(srcdir)/example.com.zone $(DESTDIR)/$(sysconfdir)
+
+uninstall-local:
+ [ -f $(DESTDIR)/$(sysconfdir)/knot.sample.conf ] && \
+ rm -f $(DESTDIR)/$(sysconfdir)/knot.sample.conf
+ [ -f $(DESTDIR)/$(sysconfdir)/example.com.zone ] && \
+ rm -f $(DESTDIR)/$(sysconfdir)/example.com.zone
clean-local:
rm -f knot.sample.conf
diff --git a/samples/Makefile.in b/samples/Makefile.in
index b307eda..582a416 100644
--- a/samples/Makefile.in
+++ b/samples/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.12.6 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
-
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -52,19 +53,25 @@ host_triplet = @host@
subdir = samples
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compiler_flags.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_ext.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_recvmmsg.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/src/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
@@ -75,6 +82,7 @@ am__can_run_installinfo = \
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -83,6 +91,7 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -97,7 +106,9 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+FSM_TYPE = @FSM_TYPE@
GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -131,6 +142,10 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RAGEL = @RAGEL@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -173,8 +188,12 @@ htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
+libcrypto_CFLAGS = @libcrypto_CFLAGS@
+libcrypto_LIBS = @libcrypto_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+liburcu_CFLAGS = @liburcu_CFLAGS@
+liburcu_LIBS = @liburcu_LIBS@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
@@ -184,9 +203,11 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+run_dir = @run_dir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
+storage_dir = @storage_dir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
@@ -199,6 +220,7 @@ edit = sed \
-e 's|@prefix[@]|$(prefix)|g' \
-e 's|@sysconfdir[@]|$(sysconfdir)|g'
+EXTRA_DIST = knot.sample.conf.in knot.full.conf knot.keys.conf example.com.zone
all: all-am
.SUFFIXES:
@@ -211,9 +233,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu samples/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits samples/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu samples/Makefile
+ $(AUTOMAKE) --gnits samples/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -244,8 +266,6 @@ TAGS:
ctags: CTAGS
CTAGS:
-cscope cscopelist:
-
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@@ -375,7 +395,7 @@ ps: ps-am
ps-am:
-uninstall-am:
+uninstall-am: uninstall-local
.MAKE: install-am install-strip
@@ -389,23 +409,27 @@ uninstall-am:
install-ps-am install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
- ps ps-am uninstall uninstall-am
+ ps ps-am uninstall uninstall-am uninstall-local
-knot.sample.conf: Makefile
+knot.sample.conf: knot.sample.conf.in
rm -f $@ $@.tmp
srcdir=''; \
test -f ./$@.in || srcdir=$(srcdir)/; \
$(edit) $${srcdir}$@.in >$@.tmp
mv $@.tmp $@
-knot.sample.conf: knot.sample.conf.in
-
install-data-local: knot.sample.conf
[ -d $(DESTDIR)/$(sysconfdir) ] || \
$(INSTALL) -d $(DESTDIR)/$(sysconfdir)
[ -f $(DESTDIR)/$(sysconfdir)/knot.sample.conf ] || \
- $(INSTALL_DATA) knot.sample.conf example.com.zone $(DESTDIR)/$(sysconfdir)
+ $(INSTALL_DATA) knot.sample.conf $(srcdir)/example.com.zone $(DESTDIR)/$(sysconfdir)
+
+uninstall-local:
+ [ -f $(DESTDIR)/$(sysconfdir)/knot.sample.conf ] && \
+ rm -f $(DESTDIR)/$(sysconfdir)/knot.sample.conf
+ [ -f $(DESTDIR)/$(sysconfdir)/example.com.zone ] && \
+ rm -f $(DESTDIR)/$(sysconfdir)/example.com.zone
clean-local:
rm -f knot.sample.conf
diff --git a/samples/bogus25.com.zone b/samples/bogus25.com.zone
deleted file mode 100644
index 5260270..0000000
--- a/samples/bogus25.com.zone
+++ /dev/null
@@ -1,16 +0,0 @@
-$TTL 3600
-bogus25.com. IN SOA ns1.bogus25.com. support.bogus25.com. (
- 20010923; Serial
- 10800 ; Refresh after 3hrs
- 3600 ; Retry after 1 hr
- 604800 ; Expire in 1 week
- 86400 ) ; Minimum ttl 1 day
-
-@ IN NS ns1.bogus25.com.
-@ IN NS ns2.bogus25.com.
-@ IN MX 10 mail
-bogus25.com. IN A 72.96.52.127
-www IN CNAME bogus25.com.
-ftp IN CNAME bogus25.com.
-mail IN A 72.96.52.127
-
diff --git a/samples/example.com.zone b/samples/example.com.zone
index c6a0aef..ee51895 100644
--- a/samples/example.com.zone
+++ b/samples/example.com.zone
@@ -1,69 +1,22 @@
-$TTL 1h ; The default expiration time of a resource record without its own TTL value
$ORIGIN example.com.
-@ IN SOA ns.example.com. username.example.com. (
- 2007120713 ; serial number of this zone file
- 10 ; slave refresh (10 seconds)
- 30 ; slave retry time in case of a problem (30 seconds)
- 4w ; slave expiration time (4 weeks)
- 1h ; minimum caching time in case of failed lookups (1 hour)
- )
- NS ns ; ns.example.com is the nameserver for example.com
- NS ns.somewhere.com. ; ns.somewhere.com is a backup nameserver for example.com
- MX 10 mail.example.com. ; mail.example.com is the mailserver for example.com
-@ MX 20 mail2.example.com. ; Similar to above line, but using "@" to say "use $ORIGIN"
- MX 50 mail3 ; Similar to above line, but using a host within this domain
- A 10.0.0.1 ; ip address for "example.com"
-ns A 10.0.0.2 ; ip address for "ns.example.com". Since there is no "." after ns, $ORIGIN is attached
-www CNAME ns ; "www.example.com" is an alias for "ns.example.com"
-wwwtest CNAME www ; "wwwtest.example.com" is another alias for "www.example.com"
-mail A 10.0.0.3 ; ip address for "mail.example.com", any MX record host must be
-ns.sub A 10.1.0.1 ; glue
+$TTL 3600
-;ns.sub TYPE23444 \# abcedfg
+@ SOA dns1.example.com. hostmaster.example.com. (
+ 2010111213 ; serial
+ 6h ; refresh
+ 1h ; retry
+ 1w ; expire
+ 1d ) ; minimum
-a A 10.0.0.4
-*.a A 10.0.0.5
+ NS dns1
+ NS dns2
+ MX 10 mail
-c CNAME c.a.example.com.
-@ NS ns2
-ns2 A 10.0.0.6
-@ NS c.a.example.com.
+dns1 A 192.0.2.1
+ AAAA 2001:DB8::1
-sub2 NS ns.sub2.example.com.
-*.sub2 A 10.2.0.1
+dns2 A 192.0.2.2
+ AAAA 2001:DB8::2
-_foobar._tcp SRV 0 1 9 old-slow-box.example.com.
- SRV 0 3 9 new-fast-box.example.com.
-; if neither old-slow-box or new-fast-box is up, switch to
-; using the sysdmin's box and the server
- SRV 1 0 9 sysadmins-box.example.com.
- SRV 1 0 9 server.example.com.
-server A 172.30.79.10
-old-slow-box A 172.30.79.11
-sysadmins-box A 172.30.79.12
-new-fast-box A 172.30.79.13
-; NO other services are supported
-*._tcp SRV 0 0 0 .
-*._udp SRV 0 0 0 .
-
-sub3 NS ns.sub2.example.com.
-sub4 NS ns.example.com.
-
-d CNAME non-existing.example.com.
-e DNAME bogus25.com.
-f CNAME e.example.com.
-g CNAME www.bogus25.com.
-
-f.g A 10.0.0.20
-h.i.j.k A 10.0.0.21
-*.j.k A 10.0.0.22
-
-sub5 CNAME sub3
-*.l CNAME c.example.com.
-;*.m NS ns.sub2.example.com.
-*.n DNAME bogus25.com.
-o CNAME a.e.example.com.
-p CNAME a.sub.example.com.
-r CNAME a.l.example.com.
-*.s CNAME s
-s A 10.1.1.1
+mail A 192.0.2.3
+ AAAA 2001:DB8::3
diff --git a/samples/example.com.zone.signed b/samples/example.com.zone.signed
deleted file mode 100644
index d57b39b..0000000
--- a/samples/example.com.zone.signed
+++ /dev/null
@@ -1,1686 +0,0 @@
-; File written on Fri Feb 10 13:40:36 2012
-; dnssec_signzone version 9.7.3
-example.com. 3600 IN SOA ns.example.com. username.example.com. (
- 2007120711 ; serial
- 86400 ; refresh (1 day)
- 86400 ; retry (1 day)
- 2419200 ; expire (4 weeks)
- 3600 ; minimum (1 hour)
- )
- 3600 RRSIG SOA 7 2 3600 20120311113926 (
- 20120210113926 13760 example.com.
- qeUEedzQrkf6Cjz94WT1EGT3WjqM8h3Sk7x0
- 6Yh9KILdnT5pb+Vr7cbqtd2OWl2Pje6qxNnH
- w2ZIZN8f7DADz55BhYlT0Fvo8UBc6MaLDp3k
- /8d18oNMEyRSd5/pJkjoJaJNAkHRQ/Mov6rT
- 9fSUgAnJK7muHZanbgLN+WMIGlM= )
- 3600 RRSIG SOA 7 2 3600 20120311114013 (
- 20120210114013 59507 example.com.
- hFSbRH5nZGOZMGhTsKDoAweBLwyoO1OweuMi
- CWg/ABcOl/RkLsSvoPgDl8SITMi6r2l6Sc7B
- TOktcW9BGfHY6XOOx/fGZK8lICGStsGGSs5q
- owbDFFDaBffVbMjJueOMx8vF5FFKQ2A2L/2F
- TQTduwav0Q2GJlMsmj3SGcCmUeo= )
- 3600 RRSIG SOA 7 2 3600 20120311114036 (
- 20120210114036 58574 example.com.
- JJrtIed56dztpBx9xesWIAX1kRDtxJsUkzrh
- a2BB2LhkjZDyhdQSX8kBhBzp6du9w3DDL5au
- sG8mhAX14FOPdtGS/CRY3MmLZrTU2R75N7u0
- aRt3PSH5tYCj7Vhvyk+7XQyXVjh3OzPhTxju
- oJVX2W6dfe8yTXDHwbRKnPmfEq4= )
- 3600 NS c.a.example.com.
- 3600 NS ns.example.com.
- 3600 NS ns.somewhere.com.
- 3600 NS ns2.example.com.
- 3600 RRSIG NS 7 2 3600 20120311113926 (
- 20120210113926 13760 example.com.
- NddhSfnU9UdLkyD64EtrEuNiIuAupw8elpyf
- 2jouZOcbhW/ZKQUvbIMhU3a3I28LqG3fxlcr
- uTR2C163Qei1r3rvq9+dUEDzb5J15orGCpP1
- bSeca64RQ0ptda3tMJHiDuq1i6evocFFBnAH
- YChMxdfMet4mRZD866ge+E7W08w= )
- 3600 RRSIG NS 7 2 3600 20120311114013 (
- 20120210114013 59507 example.com.
- Q/7tyQTriPFc6SQYKv7nDylu8CiaPlOq973I
- N5YGUCVflEnoRbL8f55bMUhllQqa/4RX8sS1
- ZzM8vuXlwfeP/7qtGgLt5kElUYjS2bUDRJJM
- g83HlX/9dfwGKdXIU6GUsJ6jvW5mZO9ahTLI
- oAqw8vVyb3+nwJAheW/6BaiOMJk= )
- 3600 RRSIG NS 7 2 3600 20120311114036 (
- 20120210114036 58574 example.com.
- iA72EF8VQy04OUVZs4xf/GG8qKGOGTwgzQXZ
- he7CnZHNjZ6wTUA1D8FoH71ZiLOiTJds9Im+
- HoxaynVnTSogxs5i0/HDdxtDonv5o81kf+aJ
- XgRtsoE69Nl+54/xKePizzH7hgetcHca4lNe
- uDMh186bBjzRobYICghSMuCrVZU= )
- 3600 A 10.0.0.1
- 3600 RRSIG A 7 2 3600 20120311113926 (
- 20120210113926 13760 example.com.
- F9Xe34UUok3PMJd/gfI+zwKZA574ndjaRLXc
- iI++XwiuvIF65D6qiXsTKj/a3xwzNewo7HW0
- u465laJZkVeJwoB1lvWLXEo+6Ay/6hYM9UrZ
- rqsZvKLENRwZnbCijgq3r27FZG28KV7KO7gR
- KgneNutPNOk/acfQ86XhlPHmGgw= )
- 3600 RRSIG A 7 2 3600 20120311114013 (
- 20120210114013 59507 example.com.
- F5LZdgZKg4+uJ06pf5FTcLuH3h65NGtxXcKH
- /KazE+YiXBxYJLdEZvOtxqDtaoDtjTRer2O/
- lMO0MiLyY5CBDMB30U5GvfM8GfK+LTPa96k4
- fF7fFAOj1HlgoxQHgU2wvqG2V/2Pht6MRnSw
- Wnd20BNvh2Qn/RbXf612bcMT5Xg= )
- 3600 RRSIG A 7 2 3600 20120311114036 (
- 20120210114036 58574 example.com.
- ud19/QunaJLw5n0JFlbsBoKO/biKmOFG+EE1
- 5fP3cSP78ecZTDjyReuOxQRphxXal+msogRr
- xVs655a1Auwe8e4SwLkVoBZXaPdwB05H7Uv5
- 6bfTx5CghzU2PhOqh/b6WSp2nE+98x9qmfXi
- zyv5ZWWmxtUzBq75DJ8AEicvH/E= )
- 3600 MX 10 mail.example.com.
- 3600 MX 20 mail2.example.com.
- 3600 MX 50 mail3.example.com.
- 3600 RRSIG MX 7 2 3600 20120311113926 (
- 20120210113926 13760 example.com.
- g4iyNVNDBUD7SpiJIfm/BMlLvYj7Y/1cm6vs
- 15zX82fUwxKPMEzVicrTwyvQPBs1G1KOxyGx
- e0jMIIs/WDD9ZzG+xYBrct/pnGZFm/ztgKE0
- vcc9dW6On1qUcH4+VcOvauN2IpJELM3oyJil
- 0QDO1xYwEzfcEsBmPnRDXPr+PzU= )
- 3600 RRSIG MX 7 2 3600 20120311114013 (
- 20120210114013 59507 example.com.
- qsyCaJyTlST5swZgPFDWu4L7p7iNsg4ZUBH8
- /VxM+0WWkbKEg9uUoQouiA+3R89n64uzNFAp
- tZS43DZ7G/P0JflxmSZT9Yiqb9uLYlRlx8JX
- mvz6RXRkiJIBOwkDyZ2NBzrHRR/O5babTOzW
- pg4le1zbH/QlhhiCdOtTbJoPxpU= )
- 3600 RRSIG MX 7 2 3600 20120311114036 (
- 20120210114036 58574 example.com.
- lGiTwXcAu50SDtxLHCcKHjkNdK22mFjJzFmU
- aPa7Rx+ZtGioKBNkRH6sfLmGmckAeotCu79u
- ZZzuSksQd0fj4TwmjuHyw1SRoAuWmpR3BeKk
- 0s3anU/wl0F686JJA9VPUB/VmZpVJJnIyUki
- 6eX9rC25SSPENZz6r7LyNlB7JRk= )
- 3600 DNSKEY 256 3 7 (
- AwEAAar2/5Ofpjw0RYuiet7Vzmqp2eCchCkP
- 0qfud2TF19PtGPu1tXkHd+NL+ZhnM+EDgYUh
- H7V9mkBV6pv0Scjv3dre/vjrIl/doNvlrbjH
- y1k3Jb8SfnwsCldzwZ3KHROre3XL8uMiuShK
- TtwjHaCoOYNA0h1mIMsHd5o54NzGn5Q5
- ) ; key id = 13760
- 3600 DNSKEY 256 3 7 (
- AwEAAbvwMH12OejpiaI8weXipEquyNyzOffu
- Dv/GGDJ4UiJqZSPb0YWzuG6LcL4BB+X4npDQ
- SZQGOb26uiQnML2H3ZWsbKu+7qh2YDonSRKi
- yqLnlv/oFbbz26HNVWjl+rGaIRcmw7IxTJcI
- kk5DXClzeuYs7NQzxN7asDdFkE++qVCX
- ) ; key id = 58574
- 3600 DNSKEY 256 3 7 (
- AwEAAdq9WVhtJHuVPUvhkH8BFw6JVCQC9r8K
- ti/sRDFtJPbX9wKtONBjbzD7lw/6myXZC0Qm
- BK3rRYG3EkpH1lbfqnXxe7A9qiniOsr2QqEO
- hN8iQY92tib3TaIBQH38P7irejPbMFbeHYB3
- O3iZkYnnr/TpnyD3Oob/CNX2Dg6Jb8/7
- ) ; key id = 59507
- 3600 DNSKEY 256 3 8 (
- AwEAAbns20HerHdgnwqTXVG1a3764I7hVAzp
- ahf9AF2dq+f+/aC8CWwow9BxU2uUSxDGj33c
- 6LQLaJm9gx1y1o5lB/0iM4Oui6/xfx4xi5vR
- SRE4fWPnWexH8SeHQgQOaq8ALUQGwIQ1l1bP
- lWNKDg8AL1ohQERLQf0Skpgi9psrkPNR
- ) ; key id = 46476
- 3600 DNSKEY 256 3 8 (
- AwEAAdC9GxD5zDPcTe6UdoZp+rm9EdFnV0mI
- z/zFz8qRop9mLq/QBFaYsjpQdOahHQgk5FtH
- OUywUaDKCorZuw8dH4iWpt/OqW79l8KMCNzd
- xTV9Qky/ZRwO7Le/LbhsYgzw6eSE8d1xOUrb
- 3w9PL8Zn5/059TE4yjmO8W73AZakgMtL
- ) ; key id = 20058
- 3600 DNSKEY 257 3 7 (
- AwEAAbteFDeDikHmJRer5eXnEPdkbSOyrg4I
- qOYl9eTUEyFxxGBuNBwpQ69iDLsBeznnTJSe
- 6vbywUwBzEkm3g3APYSkQthXjYm7c4D+XK3h
- GIEhX0GpCQfHVfhcxgB2NidLQTNm7SiZSSYM
- m29MM6wfJaSRtq5uclRZcEwDQXfAFP24QT4g
- oi4bsyoeh+3n/AuAi7KXy4e8sAGJqdJTjuCZ
- DWCUpz6yBeLQBPihn0/6VnIjlioMTuaIeHEV
- qhDp2OaLrFScy7A7n5fzCNRUsdZYdv3JsgN5
- p/bTx3Uep9nlSXmpAFzESHSVnSElCF47t2ww
- 4Og1SxsPhUcHiBMw1ftMYdM=
- ) ; key id = 12624
- 3600 DNSKEY 257 3 7 (
- AwEAAb+dffUyUGEOYSUc6GFnm1m7Mq57YEpz
- knSMY+US+7RWnzw5pPoGI8vEqVdFJ/q4pzVH
- lgNAnVFxaWRE94c29RCjdX9RF8FY4g1/nEQ8
- 5ZlAgSK/HKBrS+mOumjkx6hVHH7ZPVt2RM4D
- /6qTqEQJ/9S5UB/k2CPL2tGJg5t5AeljiiTt
- gNVsVR2BAKnQw1cGuUoKsdEtPNg02uB1b4uC
- DDfLb8pJcJPWneW8a5iPJaL/MsDf41BxUxXe
- /f2T3Zq00p/UL6iiJBifQs0oFuz+zOfkBAwV
- hc8ABzb+gdeMqYhfTROXSLPL1F8iG/6Yxhou
- s1KPPGhr/wHxEckGXNX+cpk=
- ) ; key id = 58515
- 3600 DNSKEY 257 3 7 (
- AwEAAeUpOTLiCuENRlyGBJLs14RUY2vyBDrY
- tjd4y6SzbnSpAMxFcv8Lk+ehhOIYnk6fcF41
- nGpr9+UsFadfQ6gUQj/7Zw3Tb3vGXzT16X/C
- cVOwC1f5qzgNdVeHJtpV3xv5+4Mjh0LCsJlT
- tF2qsMwOBqELm78+RK+11NlmYA2zI/lsvSci
- f1CIYX769oWR7ZX6E4jpgvEsSpqGpI+RgZa+
- E4yrwxnPRsRXE9WCLvykIhmftg77/8G8olYD
- +/3S7iHecIqKaJ2mgZWpub8rryJOFfzXT8+T
- ZCTo8fJ3qoyEscT3OyBzPqV64rluexzHdXaw
- u+nNPps38uYchpCOS2wxWwk=
- ) ; key id = 47859
- 3600 DNSKEY 257 3 8 (
- AwEAAdA0zDQsBM+2/OI8I1lAmAvdf8cB5jiS
- wyyrjRjpWHlMQYiNXNTigb7fZdTx1SfX05Vf
- yERfWy9ACRcssjf47rQLvmvE+sRAP7mOaRIY
- 7CjD1kQCTYf3TybqAX5/MXZbl5OibvS4hpjj
- SYO1lg/tITefq/Z1JpNUnyzwiuzQbu2MUytv
- qqnkrVIBp0AmPenomFmaJ7chi3s9TMrkiBvc
- 58S5a3jEvQR/U/B6hw1ruCP6EOhBg/KHApPn
- eVHeMCtv7LLf1+xNQ2j6k3N5sCXQ89EooLO/
- WNsrCmbQE3zpwZsa7pCC8LW7YQowTtbjOIhZ
- DsatvWPhGGUaCemoTt2ceH0=
- ) ; key id = 49540
- 3600 RRSIG DNSKEY 7 2 3600 20120311114036 (
- 20120210114036 12624 example.com.
- PFHuIix2X5Cecl4x9dit0Q3gJ/+6XmvAb71W
- z2+BOXI3pQTObtR0nXJTrpEeWeyTNcaejVu2
- DsiqUkrNfmmEptu1SwtNO/obKST0ewwmfZC0
- fT/MT5FlRcdXNMXYbzTtykqfebCaQFEvDqtu
- xMnKVlMn6Gl1GhJWL/FOCbx+h4M8j/7XeYMc
- LeA5AUFxGJ9u7o2heWk218Q8wDas4ohsmkE8
- h6EAo1A6qzWvtYZBJ40iUibC01w2oSfqqN46
- /GdzHB1+SDomrctfwSOaVFuF2mSC1X+iy7GG
- tX2Mq/kl5wEGrz9vgms6s9Y75oozIq0JOkWN
- XYD9Nx5c0SsehA15sQ== )
- 3600 RRSIG DNSKEY 7 2 3600 20120311114036 (
- 20120210114036 58574 example.com.
- ULc5iLBsBLh3hvOGEF9wXbhoPWVOsMdeXx79
- 0UPi/Ro/c92so7WiF8hZpXNKkuISOZsp/7C5
- kpO2Ds3qwHukLmcb60mdm2ORja5rG2vq9L6V
- 8L9zOki6+uqCiBQr0yTmxKH2snI74O5xA2NW
- 8e4Lqhm+8kqlarFOXdac+yPNdmY= )
- 0 NSEC3PARAM 1 0 10 AD3302FF
- 0 RRSIG NSEC3PARAM 7 2 0 20120311113926 (
- 20120210113926 13760 example.com.
- G/XZq9xvzAe34fFEBEbE/rsRvD9datHP4EJ+
- V6z0a0gfFlkY9dbkIe6Qtbd6vR3cXPqKTgEW
- yOYf2qNs/ZW3lfskq4JNTsCgtw/ZnY5XwiNi
- Blt32YKmtu6VpReXK1cdFkQ08nFeugW4S6aG
- jFfzXAe3YAYa+Bwz/4Ku/E533fE= )
- 0 RRSIG NSEC3PARAM 7 2 0 20120311114013 (
- 20120210114013 59507 example.com.
- sM4Zu2O4BVU7XRF9wPm2kpLgwdZJ3lkuJsbS
- aVX0ZZsee1DgBwJc9E/LiCmP0yn9XhL2Iro7
- O/yKwD2dcg21kO97mnrFxBh4FwCBtgPU6W1R
- TEt3QFhqG+qmhsESgPTntnpUncMWy+wo9pma
- Q8Q01AOO41RjOcC4uee76V81Ajg= )
- 0 RRSIG NSEC3PARAM 7 2 0 20120311114036 (
- 20120210114036 58574 example.com.
- KhqJ0xarqvbLOikDJgjg+mJ512KRlqxAtYRD
- xS5HJ4xtbpaVSdJW88ROFZClAfETXHLFdZwV
- yByF/d+cSSXM9BdmZRgr0fXjPVvVIzP0PvNW
- kQar8vufIEAigxSX8gDXM9WTYonE1vfRc/Dx
- RqmK8Mu5dFAGDA31A/ELVOvlKRk= )
-_foobar._tcp.example.com. 3600 IN SRV 0 1 9 old-slow-box.example.com.
- 3600 IN SRV 0 3 9 new-fast-box.example.com.
- 3600 IN SRV 1 0 9 server.example.com.
- 3600 IN SRV 1 0 9 sysadmins-box.example.com.
- 3600 RRSIG SRV 7 4 3600 20120311113926 (
- 20120210113926 13760 example.com.
- lsx9zG/XlVYf+5KwWAQIrO9dyjfrRg9jNXTL
- Hr9k9cSwAo08lgiLBL+O9oSIYBoCE6ACR7bv
- o3IMb8uhQmx5TOcmBZLC/9lV/E074aQfC2gc
- AoQsc3djYzRnoLqFZutHF8vtTQGTtaTh6o3U
- 4YwOrsJNE0/mey7QZh34CJgsbc4= )
- 3600 RRSIG SRV 7 4 3600 20120311114013 (
- 20120210114013 59507 example.com.
- 1MZAWcrEJFkQn9y7urePqFVEP9Pw5bJdESjA
- w19FeHRlqQpSxcxM9KPoTFDopFSRbcCMnVf+
- qNzeSjyM7m4n+B9F0L/ga/vlfO6JIc+klcV1
- 4nf775cBZNFhP3yiMhvQdFnu8KGdxPG+MKWj
- 2eNPnYzjixr89NMTdAYULyCRhBc= )
- 3600 RRSIG SRV 7 4 3600 20120311114036 (
- 20120210114036 58574 example.com.
- chZW5V4d2FPj/vPI7+ImeIxVFZ1xrK3D9/Gm
- r3ssEGhtVwd7MvUDuZyNsTjQCjwahoB0PcPh
- IZanWyFf0nFRNQ0LdMxpCqgzT1zkzdo4/lf6
- PJi0OxKvB+yiSg7VAihABUJ2dFdVIuUx28Ep
- q7y+0mnJG1KErKbUNk35V1ZlJsg= )
-*._tcp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- K/uSiRdsTASX/dlfEFWCsfPMimzdFWU/L5UL
- c6ZZdiz5v22vhVMMlKuNEIqOnBvkjh/nGJRb
- ZVW/yfPeclrdgBBw7qxGJE8B6z3qoAyyjuEW
- 2Eoh5eWxuPWTyc0DWsRxyY6WAgK7vKUcdeCd
- PSLFF28pOBkqsmpnCgi3xC/PvW8= )
- 3600 RRSIG SRV 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- lUIdAHJ8vHyuGJk15SWXGvbcoWRUY/Wvxj9D
- QglTe/VeBVrQtQe4kPiM9NyfKxW26QABrvb9
- pU8PJPN9KLLeGoZvLvkEwbyGIdq5jI7gp9mt
- WXQUSegexHlAcL9BxzrO7sXBoomyWkzesLqs
- f7P2qiR1Mnta59tctQ8crfy88a0= )
- 3600 RRSIG SRV 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- aiCp2Z/Skts3Wsn82oPP1OfBO60VmtC9ydDK
- TwwrL5t0jipNIST8CUgrc33fZE4xrKLze3QG
- G2UjpNZUk75/vbGMaSqPdwpOg+1ZXC+eM+BI
- Rhhg8PE8yqfbHXOaCgbHzEDH2c8aZeeuAHXE
- xbjuRntIOCJL/aZwciu2U8pi0Pw= )
-*._udp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- XnZgnLEz7E5rAboyJWVu6/t1rDvVfDGk7Zs5
- 5zpv+Ue1PDzpAnATldNqzyg3su4knjZf9uEu
- wPeQ85YzGV+++YhmkfLCVtyjQl9+od3S2IOL
- KOc6plEA/wxeKtQZooYOA2BSOcY9n+pn4CMc
- +N1N0K5HKVD25wFIa5JqmeGvVq8= )
- 3600 RRSIG SRV 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- qLv8BCXSeS37ZEyfkQ+Dk/LLhdatK4yLLWwR
- 06Xq+yBxa2Abax1zhnvwpJeW+3gR9X90Y/pr
- dgc4QIcO/EiKMUI83+993lcmEvwMHcKHddNZ
- LDujo/hgO8Qy+yUu7rs1x59dFa+jua1fwjZr
- XlQ7OCerB3sxpkqoNFTDANc0TpU= )
- 3600 RRSIG SRV 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- OhyGUYdZTY1tDWHF0UKqHlXPQh92JS0krNBy
- uD5F6HdeZP/nGW1hIiMx7y7dvCnWb8rRdHyC
- yVH3ilGtiS9kAnFI4OTCfzYYopKcC13H0mzN
- /MoSxpzvXer9UDtIM0GQcJFGJnvY4sMwTMa6
- ggRagi0EqBuimuJCaxPBXCAAOUw= )
-a.example.com. 3600 IN A 10.0.0.4
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- ib2NUsqQbTKZd7Rxe+UGX3GbEzlNB+IogQg4
- Dh0fyvi8hZlMT/3JSzVyTMggjvvD5yNiXQJO
- 7QepRRTS3s8a/4w67g3GtI55umVgk9P7amrn
- dkgVbhbUfNvtj1UHpE8bSntWjEJdwUczH+Hd
- Rps+WWdtcQer9oHijs6T7sFweiI= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- HuovqaRWsK22AL4UamGL3IGxuV7Su6X6pYms
- oFWGYwp1EIh7zLtyFbE+K87HQ2Uuoj/edcqe
- gxmyAzPvZjv8M9J5N4DgLs2wHNK/aqjCcQwK
- v9QoymZVwZPOeAkIHO6FW6+ez1V1uL2g0Dyd
- 4sRRctkZw9k2dW5G6ZAi9cnf7Eo= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- MTtOXhChyvgyFVMr9DoM+Q6CEXmcXSjBR4PO
- wIUQ/vjp//8B11WJGrJoOFJo4dzuWp7LO1eP
- zGyrzCIj46ALhj1R+Vt/YJLuFEWwsj+RnYTW
- RTtEdgD7/sN2R21HC+UOGe3tgAWMWBxIHaC6
- elzE2yderm0aTs1o8UduCJEWNf8= )
-*.a.example.com. 3600 IN A 10.0.0.5
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- ig0iVfSdt1gbjMe6NtCLNZS+GAqeAV72cPNy
- KRAtd9sorH2A/sfLRHET0FRjHqgFkoN3tMlD
- g7Fl8N8rd4f6pofemt9VrhNqO4v4cIS+F60q
- QYn0WAvBPpnBR9HRSOfkMve+Offa2E2Z0kai
- EZ/FtyueZAa2pZwcdEMK0FHyxcU= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- TrA7KYJuGNJzBHDdVwkgpDGWyN0gG82nU0k8
- qTgBKTNDoMXqR0z6dgaghLzbCN3N5iRDWeHN
- /gXB4bfyy0Tpr7JxTSHaHqFyxztAcSZBv4xr
- Qv0ij9pTJJge44+H2cHikcE/yptVQsr5iTNW
- 2u0R3k+1GrmmuuDZtE7JkUu8puQ= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- Cpm2UdGKo6fwa7+DIj03t2qdjM497Va2dHLF
- +MWgfWOnubJdZ8lO3Omr01MRAwxqtDZztkKE
- xIdps9n3dhNrAoVTPKO8ITnO5ku44fhrQ0Jd
- Quimk88sMgZlYaL4xs1uKFX5U7WeIdYO0CkW
- ycnD1UA20BvJejStxofTkqYF4yY= )
-d.example.com. 3600 IN CNAME non-existing.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- BHiNhy1zE1ziC5xkpamNHfTYGFqpLprApsxZ
- PSwnguEVR8GeCyCsD9IA0/1/uqPVrDlLlZtd
- znztcUuG7iJCxN+mUtILjx9SsDeeHzOIDAz0
- sJbV/383B6SkbbhTWgLobg2HvCyieJCqY1M6
- yQ0zePBZi7YMc3E7qBriGF1crWg= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- J81+CQdrbye+lOEAuACsTdUhC5POtpQ2iHxe
- HswN3pVr+9E2NZHeOExPdikWH/HrS7IwfeYE
- eo8TuiZnygvxljK6pEASEL8cXrYahSVgjIPh
- W+68MjxtkJIaFalWisgiffRgIbpo+HlhB4wK
- OFYKHlocZLzPr24VX89DfYnVgH0= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- PShNWIZ4zS/VYTOsIEMSLmDgufGD3wJp2QyS
- 2JXxj/rv0o644QlBcR9rz0CMhJBri4pochIa
- 2Hb1i+WCFCFCEHuvU6DS5R42M2T2OQ96xjbk
- bvYN6+h6Qle/N/Y0N20wZPFsQQvPXbL/xNSH
- VaYxS1j66Jw+Wx7CCNEXl2UBU30= )
-e.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- dFPAkQVZNn4La6rZgfRZW5Xf5XqMol5bBHHJ
- tslLotEN4OGHGKfqY0AmNJ6BbaWm/pug0Ne4
- sflPqt9YX1le04WMkQg577OI3yjXKpb7leht
- YFiLzAg7hdskQ+xlq74wBWrn6WoO2yZhP/fw
- 0Ik8hdc5ktbvzr+/GOu01hNH1vQ= )
- 3600 RRSIG DNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- xKtV9LuyzQYmhPETm3gbG83EBTx+SbtQPMMG
- byisttKCVIzNOGrDibcn74EiL4K+pVxxv2/d
- 1Bs+wPdjH/9OWddsdflwwhbSzB/hhptH0sYz
- VfLewN4+XXeMNZO7ofvoI6TKPNkti1bxiJlK
- 7tXprVyQRbqrT23WeHy1zHJ6Mlo= )
- 3600 RRSIG DNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- F92JDZa+GomHTzEno6YB1oYcnvFPvfRybfhk
- 9CHJ5MY+elSYVVG27veVYqgEGCshqTwYzP46
- S0jJF/H3muFXa5A3at+8BNEoKj5PEZFNMe+8
- 8YVSIjOpLdecPCZFqrjQCqwNUInzrpzHuk2w
- BOWgLfAfBTq/thRG6admkJ2ROnA= )
-c.example.com. 3600 IN CNAME c.a.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- MCvKWbCBNUANSmRvzR+/p/qtJ7MDwBoHeCcq
- zIRwrJIeLozb8+tjwk65pR4M936Me+CNLzaI
- ToNZQecxnZfK5qp68KSKtJxsJ5gCI/VXy7S0
- mNodC1ER2Pp1/RTpRWzhp3syQ7VduK3iDIT1
- xh782chcZl2JOMyIHvlqxRNXSH8= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- MO2QcNGMPeDtMMIK0oChbxdCkUqcgtTFPmnH
- 8pjXnHm04T1n7ABIIXU+NQikyjDw6WMclPJv
- E6wmPmutp/ofVwvc5sqhePCM5wxfU70zZWGh
- eAf3uT2O91qA3whptN6n8ATxWU6YKUzsc8lH
- wcNQCBHZApKHhe4BX041hjxcXYk= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- euNFkmfD0fvlwJyRZVRrjDiqNGjWDKYPEBhn
- GebVKZXQuoyVzabzhTFggK5IPAkv78VwBYDK
- DYJ611l2jkspYw7F7BwatMwlo/coCksSmG1Q
- jrPmQ3dqDTZwbf7w1hQEaAIh2hQuacQh/H/m
- W1kufmhNcVShIzrmyUw1VpFvAa4= )
-f.example.com. 3600 IN CNAME e.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- AUq/kYNePn4R4w5YddqK07RaFSvCLDVdRPPv
- fU5ICNb/A6pdmuhk1OHi3iG2LSMdNhmSoa90
- PazNVOakW5UPpoIdNuvpNudnG+X5792X1B+b
- 3ZcvPMkqlHKc14/Nh6U0njghlbBD1jFwHiqQ
- xB4pjcv+mHBuGi7kIAmIa4L4oZY= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- s+KE8eUyftH6PawCzIHLrd9gZo1psXlnU1Hj
- s5xERhyBCexFnYnIhd6MLmNfV89nMgjpRaDt
- wrBML9tOqCjURBqBdNrN8hKPtNHP85zxTdrj
- dshRFhhh91RFohJsGd3e1uFZ0e3eonOSGCmm
- JzRtM8B/dKzd80ebnFkSjz3yV6Q= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- YHCSKb3hW5OSuqKTPlravCFlwFymQqRZg9z3
- SD4Hqjny69Lv2NEL9eU+DXzT5sUZn9ipueSY
- 0/+WGYJUSotgrINgzVDvIlhYuBPvRAQJE+Fa
- PT8HwO6BI/nw57+zUtnxpnphB9E6OvKNSa81
- qEvtb/q9AQANp4b/YhmGf0kwOmY= )
-f.g.example.com. 3600 IN A 10.0.0.20
- 3600 RRSIG A 7 4 3600 20120311113926 (
- 20120210113926 13760 example.com.
- AieEyxCXhj81os9lt1WfH72+/cm8Ff2IKe+O
- f9oGk8bNi1EqYGIw8oGjwBMovrfmgxFM7vw8
- yU2TF5yKjjjIIo4iMkxQWPi5z/COxERXrNDJ
- VuIgYQB7OgoXdkENHNTVXxm5R97r5n2vBKJR
- pvfIixoPPmmoWEvGQNd4DykX320= )
- 3600 RRSIG A 7 4 3600 20120311114013 (
- 20120210114013 59507 example.com.
- mO/ICPyqa/8kY+9jxVVSwdezxeaUpdmQQIrv
- Ppvm9Q5dyFguHVMeoRewUoYz129ZXZMUXkEm
- ZghIE0uaotgkSA0/YjVIMIGAPP5fl5oITKbm
- GOUE4cZq3w2k0QtZ1ASnv8FWqMd2ZTRS0BdZ
- NMRFZ/0RM9OJ2mm+vUq08vmc3wc= )
- 3600 RRSIG A 7 4 3600 20120311114036 (
- 20120210114036 58574 example.com.
- F3Z83j1JjMr6B6gOcDaSw3I7HEgUBi1aSpQi
- 0Es2CWc7WlJ5KXB/kvBas3F9qiyC1/Lje86v
- x9LU+Nk63RHRRFvFCGynrZTFGgvR33ZT2v4x
- adAExnwOij0e9W4PX3hmjwuh/Fa99lmJKV2T
- Shw37xX35ahEjIqvJZ1IsgMAy+k= )
-g.example.com. 3600 IN CNAME www.bogus25.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- Rr1o+aiADRswGkANUQcAx+GFYHlWPC9pVx+y
- jv9JlvfhpO+F6B5SdBIh+BDw57l6TOBD5AqF
- ZH3hqfepTHL45sQ76+g4h0cwwQ2Mv83+SopC
- HkWZoTBqOm4o7dETajZctlWrWzYy15H9YWo6
- VJz6PNjUFBQN9x7qitTc28xynG4= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- Q4Ti66ZAJXoiFlHi6TUEH+RXb7YR7BnS6RAa
- 4A/7pEia5f6TclezkKLqT40+CaoIVRKm/TSl
- hglITjs2lezvg4QKPqSqEk40Wg+lIL96+nYJ
- SnwB88oSJxeECBcFW9qnqbr8Hbo2/4RGXDlG
- cyfz698QmuenSgFzGYgARPB/dU8= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- eJ6BkMvJbhwfkjn6mtToSW9CFeRHOhA4ffUK
- zh5iNL5BwZVs1JsTp7Pp9g2BnA/yv3Qt3cPp
- Y44NjN4+CxQvQ3iSpkwJSG98b8QO7TioMC1x
- xSpYimqjIO8duuPCJUdfN/tMrbX1Hu0sZXyg
- RGrNjyK/zdq1GFkq/zKZL5JNGv0= )
-h.i.j.k.example.com. 3600 IN A 10.0.0.21
- 3600 RRSIG A 7 6 3600 20120311113926 (
- 20120210113926 13760 example.com.
- aX1wWf9oiP1B3jM1zbQsg2rrVf0HR3MIugsE
- k3CXZ848XmdLFy6tU2/ZochGwfKnS8XN9G7Z
- LT+oN/eTYc3F2Mfg5TBkPF990KDwnHGtMYiQ
- pg80IaPEZBmaY+U8orjUFM6Gg0U2DJOfKBLQ
- fJH2jpZgqiQYyzV1ho+s1aIOJEI= )
- 3600 RRSIG A 7 6 3600 20120311114013 (
- 20120210114013 59507 example.com.
- riGA8p/s7c4pX7ftA1jK+6+c43VTgWYhWq21
- sC2azv8XVQEoXvhRz/X4Qk56YlihPX+oGn5m
- LlBCa7Zan+JDpJ67wfBnVlNZCbqxyE1eZOZ3
- H6o3mRT2OhTEmdyogI/sXsjOn/XXd0B6O0r2
- /VsSmnpsRX+v5HEzBJ9PeIz+GVo= )
- 3600 RRSIG A 7 6 3600 20120311114036 (
- 20120210114036 58574 example.com.
- W0GiAkNUBtaQFmPFD6Vk8MRkPwuRfQ6DMw60
- 3ZWkL/acliVdPjEJkqo3RnXaJpxs+sa80KUv
- vO6MUNonsRyBx1LtxNkR74MF+DjDBpN1WqND
- 2RbsGMNfFvOvQYdTq5C2hXIbz51KNdykm/Xc
- QcENLRQxkZYW0uwM7SWeg0EB4is= )
-mail.example.com. 3600 IN A 10.0.0.3
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- TJUSJxyBdrie+gGZ6r3Lay1eeowmYvz3UcII
- nTpoFq9jHodDL99EXZ+sCu2pf/OMx5Ema3DU
- MSznJobBsrTGzZyUcCfYbbSdGZbcBGs9izBn
- KU8HJQYIWGx0WCpuvrLINsv6+1GoaWdemVZg
- A4FMaGR7FaXif/dI9aJ+tqwp+8E= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- KgyWfvPIJ024fWUzf3z0RCodgiWRN2QKBAwN
- Mm1XevQn7gp4JQ7mR+FJttvi87Xp+2OJsEIo
- ueMZR1QD6aDK+sgbsM7Tajhq3Z556FE4rSab
- 8WJf39LRBry9tgH9FslDuNlIWk/We1H2o6cm
- eg5iXj0U7X/91lhKgoNdP1ddMsQ= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- pvOxt+RdNf3ua9pN1BVXxLoRHTy/kccP2xQr
- kxMa+3wvrmc7vML+/gD980xhZZ0rBas8kGV8
- ze9M2u+cX78/utyxVJYtv7NG+LNOBXIu/7is
- Q5SKaegZ3asLF6LbV6IbruQ0QDSy41Oqxhpz
- 9ePzKj/Q9Csp2DWBfwwzxuiPokE= )
-*.j.k.example.com. 3600 IN A 10.0.0.22
- 3600 RRSIG A 7 4 3600 20120311113926 (
- 20120210113926 13760 example.com.
- dLQwDNg/9Gcxo/rpskAs8dt8fEOEdy7fFx1W
- VUu1ZqEPjq00YLW9YHNy/h8ej+TSRUp/HONu
- 4nX/MflexL5lWuqpszE823Yn9heOymH2HWu8
- q53vzETP9T/ZCvpnn7pJ06MRLQEch3Z7NSuJ
- Ny642jlGMFkiP/2ES1dOZu9qLMA= )
- 3600 RRSIG A 7 4 3600 20120311114013 (
- 20120210114013 59507 example.com.
- XxFMfqTLkVu/+yk4jN1TLdiBb1GQ9Ixk7k5t
- X7d/80ACVp4JuaP21JlyDoFHqb+Zi08ZV4ZC
- zr4H8ljlBBaD90u40fX5UY7t8cdqCmDX55/Z
- 37Z4YRr/K+qM8p70K4J693o7fvbhmz5OriFt
- 5QJRTXs5eMqfL9g/0oYQbmrAfBQ= )
- 3600 RRSIG A 7 4 3600 20120311114036 (
- 20120210114036 58574 example.com.
- oUjQJX27CxtHnHu2DwGtrLYB/hB9SenofrDt
- unJLWuyNuwwj7zWm9LEp42stvHRriTf36kk9
- kz7zHr2WnS5z3+tskZhWQuDx/OBidCfpwzvB
- 4Y0qEckGdPyT2gk3iNLhxme5A7vmtEUfiibP
- HWQYtUZPzbXK+4PEAeshF/7x68I= )
-*.l.example.com. 3600 IN CNAME c.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- FE/DRNChjWQr5UQUnr5uyv78LqVC2Eu4z5x+
- 9eJbUBarGeu+zpMauBfS/Unni8kZ/1LcD4/5
- z74CyTZIDG1ZaZJ81Osl5eVxCjGbyQNzzX6Q
- v3Bpk2panHieIzKJdAFoPjgyteQQUD0JmPyI
- h1VVuE1mPG0Q0DXV+ED3PJbk5ys= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- q3dxD/z/bMhBmv0Ui0nA6ii+1yndPxrnrYP4
- DDZymcbO5DX5+ZZjOAtUbFLHS+u0ZBkE9zTI
- fYVVzsqRF8DBU+AhHezsYIJexExrBImJW4v8
- +ShIm85213nnyU1ZfLfwKpfJXTQ1gPWj6qAl
- 0UZyPvCq7riyXYHTMzXk2IdzuxQ= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- XqLkSp6x+UINFdBNqFYfqg5qAA/yj12icenM
- M8VLrf7eSaD9ADssVDSZQ8Zh8TEdTJtl+V1Q
- KI67+UatPVymvrkCCCZeV5Pj4+iEqHJatpCw
- x75+xRyVXkWCFTeKXdyTMU+6nBMoE+oSIN8Z
- D6O+nmGX3aEUU5uyrTwg+lve0gM= )
-ns.example.com. 3600 IN A 10.0.0.2
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- O3VYWRVnAspmT89PkbAOtzLoVaCt0Nx2k46f
- qHRf/iBgICBY0w1ugRbLWB3Zf9AFrJnk0/X+
- 7iWq80FwRcsSStXSIxB+mRGFxRTB41sHxhNS
- gRUgbB0VDE+UfMXOEHqjOzKw2L5s4HPKyo11
- sUmLO9prjHS+/TlWn9QV1OhV8nI= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- rutrFJR2YwhpCtNiz3nkaqwYAfqJklrwT5AI
- 95T9nUZoT5IAcfhT2E2imm9ovvJ3LHX8eSxi
- ffLcnhfPs+iXPTK4HUnooKvGD4QOEgN0MCBd
- S+5dI4tZqX6Oa09JpnyFxHQjT2bHtviNa0oY
- kdDjeFhl5pfrdTfBy0IeSU7UzqA= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- JLBOPoGSb+/QFg08RPs8Rl3q3vSxMC0sZcMS
- XRL+OhWOKdg0fHMu8zOJ0AlaFnmQAGETKEGC
- cUw/wC3HjBE8KNgnDzMP9cwgYxgMauh2+7Tp
- 6WUe6Z2qdYb5OIfuWjb00aHUK5a1cx/kb+pc
- zigJlsSVN34EcaQHdvenBXqbwds= )
-*.n.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- YpRP8uc0g55raFFpFkY17ZARRML0vuNJJlsn
- EXUD1s48+is2eoMhZQNXWchmcGrcPOcdGP3X
- 2/L+laJDLcAYcSQrEJQtcXyjLz5nqaRKm28x
- 0bsDFlM1dbI5bOP6JSPS/cCHRy1PbfZlI9GR
- 04kl6sCzAzcFaJKtwK2qLhIsYSo= )
- 3600 RRSIG DNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- xTzl2eq7QImosoIU4nzEp5KkBWMAeuhSJrmi
- dj9/jIuXRLBuOe1eVtC0639/SOJWWAMSGD5p
- 6oKj8lAYhwU04h2JglH5LubpPeV6TVbteZRp
- 7+Va+7NioEdyxncWoVW7Xsn7lOGQ78++dmYJ
- yS3x4SbEw0W+jgW0vowJxEohsEc= )
- 3600 RRSIG DNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- tILOJHeCI6hgEYTKzEyMYjc60FFxHfn85Nhs
- QiMex8bzGcbuIwdEt5vcC1pO5nDJjcmtyDZ/
- EOJILY0eaYuZDHwNODG2TEpQo9PNKe/ufzZ4
- lZR+Z9UnjuZaxAls62FsDatO30MwucabcehV
- dAiO1jxlg1EiwrhUh6S1ub+hYZE= )
-o.example.com. 3600 IN CNAME a.e.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- StHh2y6i8Wy6z6vL1Hi5ANcCCHHYBceKRFyG
- lvpCrYV3JUIhPIVfes4cRMW4umhq/BrD0+Hp
- gUroc/B8RKrnklo28rPu9ooj1X16d4JhrDmZ
- 1Lb9jeWuKrdNbL2rvsG1MmsdjwjWl6MDbmoc
- MK9k860eEqGzbFDQq/N86j51VQE= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- ph1n8IxZ37Uh/adaYXeUf8eoSv3sQ8fWxHBi
- Px69Aqh2KSjWbmmxXjlDeqYOJLhURYGPzoe+
- cVxIqMehVIX7GqKEO5O7ax6kYuXfBW2CluYs
- LOC+6MmCvEMe8hdinGiH08N1G/P/8zTdPPjL
- ckWdkMrEqaqrTcpfO2JuyS61wm8= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- mt/kg83oCi2ONU25Vmb9wztOMTp0ql0bJ5TW
- X1vXheYNcss8Aah4iXkt+ubxTLkFEfqt3W1e
- +ZOWm0+WwGQMFcwUBH8l3Rqf8UdhDRi1Kru+
- mI3kuHCffygLVtUilS5GfsGgamItgz6QiE0p
- y/eLr3oIoTok4+Nrme0t/UKKMoI= )
-new-fast-box.example.com. 3600 IN A 172.30.79.13
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- eujmHzNAKlZqXN9jSh0C9d5LTACh3WezXKgP
- B/IGo3d2VOxIjiHPLgRIgmyTQOyo+iMIgqai
- lgws/TxTeNe+olyDo4ijmXe3JEHRvt3k3Klv
- soj7moubP2nBDUOL+RPGum1pKfepsYzvyp/o
- v8ngIrMiYinBETP4su9UyXce7uU= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- CKfoEKHS6pzYQZnB+NvTVA5ejrX7sj1GYihJ
- xCIZ4ATPkuJGPGmGHDO5DnUC485rIxYh5KdX
- KtUZYOO1MmUBG+mDBZg2s3ITdIyhO4eCuEWz
- 8SEimWMwfkZg3+dydfNLOC54Wqb13EMIpgFv
- 6qc/7Qr3uNMx4LAUMD+fur754o4= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- jnisCwvrzRKVkP5HGETwkHeKN6SLRLWwvCiV
- r/I8L+l1+6E/emB0J2ufm9J6TmE2M2AcSeCN
- 72/feKcmaKiCk2JfkV/lG8/dR/2NKx1LoIlM
- /PVL1xz9Dw2j7WV2uhnj0GRhBAkW79aq6Xj8
- cY2aLX7pg0qWKkZ7E+sPX6OWfpM= )
-server.example.com. 3600 IN A 172.30.79.10
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- YLVX509yH2zq3++9qh5Oy9uZWL5+C9dIn8RW
- W+lEfoFtwQLpj/y3oIM7mm4xsM0V9o7+z6YJ
- MxPVV/ZFmBRdGKDQF9krH+nR6q89lCc13t01
- tN9spDH73S41jnMQw27Y19rYKIVu61MXOfGR
- 7KEv5WHOVkkER98bHb+bCK5yBD4= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- UVSj/Uujr7B/Jts7Hh1yLOkQsjlyEzSGQyb7
- yWzRyN3U7dOpmuU8yKZ0vbPscsBS8yEgvtqT
- WeWfqiJ0/SI6WAY7IveLhzj724w2Ks8JRxUm
- mH4thHGLN3tbXA4iXWge1WV3TAMuTXZ+nbrN
- PaIx1PlE0/ZehIAFDrw0e1ffHqA= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- A5Y4Wly9iZUxYf3z1Nx+ehOHpSkHm7DbkP8v
- mJIUK7g3FMcXEDFqcdbJ99o3ZoAAfpXZ+7ej
- KfTTiPRrVoKalf/lHVrJsnoF+6LOfOxKkv4U
- Vs6ETZssT/7HjHlZ/AbT3oi94zexh/8pweut
- H3pGgxFN+inHP19L88y3JYX0RhQ= )
-sub.example.com. 3600 IN NS ns.sub.example.com.
-ns.sub.example.com. 3600 IN A 10.1.0.1
-sub2.example.com. 3600 IN NS ns.sub2.example.com.
-*.sub2.example.com. 3600 IN A 10.2.0.1
-sub3.example.com. 3600 IN NS ns.sub2.example.com.
-sub4.example.com. 3600 IN NS ns.example.com.
-ns2.example.com. 3600 IN A 10.0.0.6
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- RtHrh3MAsZtWfaIkPvMZZnZZzN2W1umMTkEY
- 55HH2pnPPE2VATR/lm4xf0la0FeB1jLWLUQ9
- 4TLuy1GARwrlqswvQNHRy1nwcUdHD6OEaKS3
- qsoLanpQtik5nJUwM5dx0hMrrdGPRYgyApBA
- iSbOJI3VNUKr81kPz0zGaiWdTTk= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- n0bkcmtuzcTAk2gSSq+4GGY85YpHBQwXJi2d
- Iw6GaWoXyXVDfy1+AzFfOD6V5EPv7v5x9xY7
- RmMiTvl6YF+4w2DHj38Ti3JB8agfzeQf/q7E
- AX1RigpCgroCcGHbonW5497MbNmnG7CLthLI
- wEyDwYOLlD7Kbwcgjf9tUxzsXfU= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- Fu11GG7pPC5WN8oNvrRE17Roy9b281A0/WqY
- XyXSr3CU3GLIV7wg4w4Miig437ShK47GpHLt
- mGBTNZAaRFQmWIC/jNfuJa/VynDytMjyu+Oa
- cDpKVaMdO5CFVHyCC25LPorVGZOn8cll19DQ
- hRbqAld7APpG7mdTdrO/sP/eqqo= )
-p.example.com. 3600 IN CNAME a.sub.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- etVmE9Klo4wb9DW6QLgm3sJckAGpSDjIp10k
- 7ITKrsiK6c0bMV0rznp2tlWEa5tQkmgTbpeI
- MxNCd8XHa9/OSHlV6LdQPYtzVujWPftOwfiA
- FMdhzEnDh4dl6s7kuryzVjQfNCN9NbhwjaaM
- muyrjUNGFjB2rcimQU76AKJzgDM= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- ztWlq1uFc4gkNpkPRyNGo3FsK3weYU8J0gBU
- CQpHyE1RrGcD6upk3lh6r+TEiTHlNtAPYfK+
- RoAqVt9hPgTq6bErrsY53Ux9kVRwEIqQ6vIC
- S6OEsEJjQkdJZ9X+4LMRxzWNNozbpe9YnBLI
- COh0bm9vCY9Wryxkrlt9FzWrSEk= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- jOkv1c+V1vaBTcIOQdHlubwMjR2sFYzbDaSM
- IBRsmuD3WtAmhNDO0yZLVjqkfNYTnA80at6B
- P3n28xhJUIyxp9k7l2TSCBgHDK9NAeIj2PTe
- KMLKsj8ZKg9W3lCa1XnMqbi/sqgKBMWt7GDs
- e6g5LbPj8JVp3tdH0dv6KqRT7rg= )
-www.example.com. 3600 IN CNAME ns.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- CXfi5IjLMEJi/3V2PFsXZDVw4VH4QqrJhpcW
- Y4do17PP9VjKpoqQBOR8VZz+WIVU6Y7ljaoj
- kzvktCi+h3ZTa6/xWicAItN3H2/ZQpNJoQOQ
- hE7O5BGE+/PAvd2LlQnEcN26flcKiutyZ51j
- AuJ4LPsbmOFkm+zYYnITDbEOcwQ= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- B/G4dvFwNMaKID9C71Ic5DKEUpvSJOBJYqiF
- whpHMweLnDNTvQwVpxyZMG9tRWzPyDoy3MWs
- 0+KYqgBqoou51h9/W/SCTMFypmAwVD7Ln7f5
- 4vqXcP6fzKO14uk6HO0XtMvN67vNQ6MKxSCm
- 1xrB8rworij3GlZzZAfIaJqpYms= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- Hfb+gJ4MSnrR0ng1EMiS1G+huX/WnI+0k3zC
- Akkuqfg93Svnkzl7IiYCd5q4+S8MbZJHuqdk
- jO/juQxdQMTu+pr03u0vJI3swgn5bAnYwEGq
- /4aWbfbADJ3qZmeNSgqMlUgOzLY0kZRd+hhy
- h178rruFMiRXZtcYZ82zzAw6Nwo= )
-old-slow-box.example.com. 3600 IN A 172.30.79.11
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- JMMCGey2OfFJRAoBZIq6+4fTF5iu1KGONFnm
- 9tW/KAzAxAfhJYtrpUOX5mqXPiJJPBzq2/0V
- BzhuxRaAZ8zQ7xv0HjchGRonkBkD+arCQTlD
- Z4XBg83SfZ11yBvDjNpdoqhuqmUKKpxAGb7K
- raoS89RnzG584+MOFiSBjK0BhRg= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- MfXNI2pFznN5m3gFUKZIGRGTwzW0+neZnHpB
- 3org3XKj7PdEnESBiLHsqPpTTAv0GPMbdDcR
- y4P2/TCXQajeq0bltIJ23k4yemesEKnENLB3
- VDFrcH+U0j4Zaj9PMWhaPsPMqIgDRml3Eflw
- 2mqp30YOHQJKstmT9ney/gUagNQ= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- S+F0ghsUivJDNdZTuEpuz23HTpifoI6PQCjQ
- xc8rU8yDh1f5mIBttEF1eL6Kl8TLJiHEnp6Y
- qV1eZ8MzIruokK4sZjbqGT91Qadg3CQziC6M
- SGBg1dzGnubD4EkqDhUgiReKHKphGOMh6hGA
- z9ZLmq284c3MhE8HCQVm/Gzbao8= )
-sub5.example.com. 3600 IN CNAME sub3.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- LwmV0GyJSmiA04UvzBtEXTqxNGQoJuw1WNkC
- TUHcw+RMTp3dEa94cA3HvN4J9mFAONI7Py3s
- t7ebHB7mgQ0ksYbAE+kzr5FeUFR+g3Di/h5S
- ZtlwfpIMNSczM0OgZP77PPqkY1LPHTRDIXa2
- 3UZ7FgU6n5k7XA/36SrYALdlN1U= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- UsLiqhIFddPFAIITmc0n6fJz5YAFKXYjuGAN
- wNam8W+dTtmdj48FOInJecWRX1byEFIdBp6S
- 5QjRB/vLMjPhIVpGD0WZYj5QxCZZ1gwTXy+P
- /nN5bkvNbkMPoplSBUNKMmtxOJbbA7ZgOiiK
- ZLqLSeQIYbSZ89hyxpIZmXRsOiI= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- p6wqmfuG7A8F5zYvYatnq59OlRnD5XS9qrVF
- ygaih/fN84cOP8O5wXJr7fmuhVWejorseI6r
- 3m5pHum6UekHf+2xSziyFs3cIJfFKmJQ5uh2
- JR7sEiIe+hwgSGWVx/RyirW16ol+fWYhYE9e
- IzzqeswPEe6dBZMUk4OqIT5GTsY= )
-sysadmins-box.example.com. 3600 IN A 172.30.79.12
- 3600 RRSIG A 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- ItoQw3SlGTWVcpQKf2W0n8hCQzAGBvhMTYhM
- p5Vq3Ks9Sf8iiBi525i4s2jjo/bh5kM7Xloq
- zWcq6JTJCyfMRNVmflVqnaiespLlYMiT4GXX
- FJP/ez1r7IysSRT1C8PivlByxChC5aLFl3YS
- x5uyFEIlPPcPuiCvcyoiA57nk38= )
- 3600 RRSIG A 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- rOAEIcQSCNINZl8ZapXg/GH71TeivQ2tec4/
- Bf8XzyDAtCJoETdRJ/2vA/Gh9mc0/f78x5Er
- uY9gnqr7l+z7veBZHbqn2NAQxEXd5xjg/QcZ
- MLUNpytyCb1XltUwAoh8ZmC1xWdTcM01fU+8
- 2EAQT3cWEEULps0yfSaeb9onx3E= )
- 3600 RRSIG A 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- ChMtph8oxYQNNllIadTWvtwq7HBt8msgZ5tm
- t+Wi/RriVxGOA51KKMAj3QSHo8bG98bvQoqP
- 2o2naWkDrKxUkw/iApwNwnfWYQWTGVx6e7pk
- FVZtv2z2NFXjoVPHQZ/gkdYBx1EqumJdnzAP
- C5dmH1WnQC9ixns647lcvJUExDw= )
-0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- msfUzi1BkrU6AubIJlsPXUNyH8frCK6xT5BQ
- thUm0ftrYIkm7mt6wWw1SsoeWNZYMXGmv9Eg
- 0tayicAHodB0cAI7AUMR6p09hUC/2Lq5sC2Q
- xjxpTwEsyhE50CmUW6L4Ro01IKKaKLKFYYo8
- 23upUqDBGBLaXvZxmWn00HYd4m4= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- D8hb2ltU3bDzA4qIkxOGMHnntavQZ2QXsmoT
- k9rhzdRdnpjnNKkywKaP4++hJnECwhaqDZmn
- blkLpWKC71MhChw9JyB+3Fm1Rc6DHKfSNrO0
- oOREh2GWNcdnzuLilM3KLR0ByEdXRpRf8bt9
- wpt3pDqU4j5gSbYCtlG1McPX+DM= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- aLq8mvv55dUsGek/v/zxmWvZfHHYKaPvwJZ5
- zKP4s/kDNj9EJ2R59/kMx5pjCDacodDwAjJu
- C41TqInL2B31FggghHNFCrX7tnQBnr5fkbHo
- sPPDYEfc4hKVXosfwaCTKmtLkk2pFGEVSqgc
- HKFBcOT277dHShmPNpzjSe1W1UU= )
-1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- qAioq4Gv8IaKHCGcrWLqa9+aISIZYW8ivD7s
- lvZJ9TgfD8wvh8s1Rq1xcUeufxpM21PLqm9d
- ZQkoalelTlGix5CJi53TYKy4lBuR7OL9Y5Mv
- hnGcGlBNP+0yv5f7CYx37H2hGBxzVLBslU9s
- 82eclo2SveXTxIHZ19Gs7rXQ354= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- Wcpxl+9CEHpE1jWrkhPt/mMuUTHVMMjVlS3j
- Ni6e5ubILs6Ff2+DFBUQiCDo71Q8JJ+ABmq1
- kl6XHtFDceOg0GWbzvsRqVhsGI5fM0TF9XZz
- zySY9drMrba/ImpC5qUFUGCwCS0sSK8fzWhy
- 3w6i1xO5+jJfHmBD7w/eFBhX3UQ= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- X1QSQnz9t1pebXLpbqu9/+SRrw1LX9Ser/X3
- oI/z3I2pDuUwsH/MaJkzUHQd+z19xFnJPw25
- 1RpuwbC5U/7s6em1tyqJ+O1Op+1PQV3hZbz9
- CrrCYw5tJ2Lw1P5dHb/vV4y3176/XzBjNMuk
- ktyP9HEUbxP+fXohM5KILAKlBlk= )
-3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 572T84KRFBMQUC5O8I2V5BNLNHA8CBQN SRV RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- P/VgOsq/A9doxdcX59USly5uimiWExYdSQzj
- IQgibgt5GP0Jn7tkAWNfCHCX16xS2/eFTBiX
- 7faMXf7xdG75yCuH6SHyospG4Sck/S4BymhF
- ilBv3xfEj/upwjBOX4rO53OpUu/eSVDc4UeR
- UMJ4oIZ+MxEd3vveb2zi9TZUVOk= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- nRVgUIw6/jJS8FV3OUd7JGBgTAbeQQshwSIt
- MRqLl8bHewPGHUTYDjNpvVkPhQAzdqeN1Imo
- eG5TSCcSKDS1/i9PTyCVtcEKFWRRGoqJ4pXf
- TZDyPuB4tqcu2tfkmZtGOeDnrmV6a4DulKRW
- 4JDz5X065H5ZI8OOK8IoFqtME6w= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- IjycBX276kZZ/qW/ix4icZ9VNiD3p5noUp1q
- 4ff05DVPq6alRP84zGqbLZ3w5vMe/drNiDtu
- 55xk4F/9kgvk6YM62lk9OzJGPOLJUvWwz9i8
- trp3lOCuEx7FzPKTnpi5YGvHt852vrAacczD
- dZDcRJWuaLEGmj8CocwvOhNrVkA= )
-wwwtest.example.com. 3600 IN CNAME www.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- T/WgP1/hiPDfDym10VMEQ6nGdD9Tbf9G48ZC
- Wz//5BEJPZ/dUQ/RGY6T5oKPUO9UEv3v9tcr
- 6N1vROBkgu7/hnbi/yGkDR0eZC6XZGR6zBJ+
- X09QDYNDddvWCSO015QQ976IF3Z+p6woAP6a
- HnT73bx67YGI3snBdayTq6TYhDs= )
- 3600 RRSIG CNAME 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- hzNM/Vf21K93xVBJjEVluisjz8uscyidcoXd
- EeFWTcMe1y4JIm9/HUv4qCjAcwQa2WKxQy+x
- C/N3IgIHNbw4qoHrOEqkBi9YE+cMnDb4fvuN
- hwxLVp+TObsv0pdD2TUsb7igX/YBTinSAeWE
- fd6Krlc4MfHHcL9e19SroL83JNo= )
- 3600 RRSIG CNAME 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- fHA/W3JKDua3rz25CZdY9MRD/IR+DIK/qs5Q
- QjPIdvxqLGsuuF7Kxze29Hckkm4ph5P+nRZ/
- 1D5cB58DSVutrEAhegF4UMZpfJjj0vCHoYT9
- +a7c3y2JJFTzlYmLeNSiDfNgEs/W7aCEf6Mw
- KEquRC0ZaJqezda2Fmceoz7y4BY= )
-6K06BSDDT661B33QPG6F6EB14TIAJ42D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9CGLSFKECUFG8QODUCMQPMVH0JP35440 A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- FnLE422keDCUcjy4rWNTF+KHGGbdiI+FITwc
- ecyC3+meN0HFb+OhlI/Nrr8IwdUIqQTVIOTR
- a3/oZZDtne0XbR6bXw1/AKl+aRXLBsFWVyAK
- ESLIWQvxaVwWG5fcB9MO1wOsjWpRxG544Ev0
- 5EDnA2qcdtDW8x+kSdylKgyDcoE= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- sxzypr5kURXb4lYRjOwhNW+ryDpFxd/bggBL
- 7pEW36NILvCO+1PHdr644gCVMYbqXslsWlQE
- JCBXeU3VTaDtWrtyl67AxKq+ZtguZVb7hCeO
- AVCUnGW2A/99N179vOO/1PVPNkIqT0LmZ7MC
- ugGWTJeOsuPqfDtK++SL8+LtqDA= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- lGQ31blQWd74cSH+4djKZc+bzpz5QH5ESFvU
- HIuW5NGBUS0qnrIi8lLWyjAarvR8DsiVsyfN
- jWRlIfviI++o/cq03nWjWNqMqL88l8ka3EYV
- 6m2yyRJHlJkpcZ8UxwXoksrcJ+9LXmCAl448
- HpGct8DIFtIojJKhDkTkXRWQg7U= )
-572T84KRFBMQUC5O8I2V5BNLNHA8CBQN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 58KH92475K4K07K5NV8KAHO2UOHLGA5N A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- ZFhKIc1AZKczgkkSDC1KotilNcZZI8MG0E9s
- DIFiEMpZopagIvo/Mt33m0Qc1zs2c8zH6sAH
- BBHvFO2GpxQRdQDJ06BZ29QqUJqo4ekA9v8g
- i3mPFB0UQMYIxXjEQ/u2tucgA1RbRD2Zhr4G
- bUB7vXOF6z5C53CE7j2dQ0CcKEs= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- A52sfF+O7caf0soRM9e8v1LMTlguJzqFfGcj
- pq5LfXHMnM/dpVGivmiTypCYhF4th+jtXzCS
- DyYid6ycFsCHEI2UX/GH46zY9/PV3Qg5YpMH
- bB5U3Fkm+hJZbOhElIE9VzwdDUUQg0h3lr36
- uTDrFId9s/eOdvkmg3kIOplsZNQ= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- Vz5KSak6VR2xAasrITcxaYG2cixKpF2e2zhE
- 4fOKeKs8cA1iJGQPCw1+TCafKdvhcXrGmToI
- w0Gx9JHq9+JDcSjAsmTwvPwGn0QybHGP/OXz
- 8MkExF6d9Tt/YX9PQ8kwYgrf2kOewAo5C5la
- RVoIqvgqSWuBx9Nh1tzUhdb3/Gg= )
-58KH92475K4K07K5NV8KAHO2UOHLGA5N.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 600RRJ34OTBFOQCRPSG5J4F19RM76IOE A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- Xabi8Xuq+lzefpWqbWWQfTKRyIlr9uAPKpUt
- Ot4mR+80gUrth6Kk+EU03KJU7hlTeRWISvf8
- CLrmS+QCg22NjeIK4Zf9V1X5oeLR7qTli4Y7
- XzTyRQ/bZ6sl4azfAfwL7Ipkvj7T5VQ/wYmg
- SLYH25fdL9dMELM/mgp0h0di4g0= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- kc0m5pUs/yHxe16FVmR2jrLw2hCPtOyumRsX
- MmjO0V+hSlToKJ3YgsDADN96qC5siTG09yQY
- XLrQ9aSifIgtw9igbGXj3BabINA7zGY5hnH2
- byKDackMIliitU0LXM1PMzN8nf9EW01CTezy
- Ck+MK3AwF93Qq+KxJ+212hDy8cg= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- b2zUsnj7rDfmr43Qwa2XSV+2Z7elsmFHyJ4Z
- 6LJUKESn/01La7Qdtl8sF489gHpZR+8unp6O
- QfHO5Agyp/OFt026FhfCbV9DOYgm3lgSFH8C
- EVOsBN+v03ufrIIWiVX2bMQTJNrXBU4wZZnR
- ZqWD6xnzTIAzxudmRahS1Cp203w= )
-600RRJ34OTBFOQCRPSG5J4F19RM76IOE.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 6K06BSDDT661B33QPG6F6EB14TIAJ42D SRV RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- L86fCGixazBOgs5RmRerniPJNXjeE5O/LzHE
- 7e6B3mfMqehojAMudK0ZHy8zTsBQ5af0a77C
- x62bEbbHi56fDpKfck5r+bFrnJeburjCdJ1T
- arke2yK5SJJvSAhhsPGwgYluKu2doxXfSGZJ
- IqLRmX+tghnSBFPwvwckXJRtUGM= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- 1gkarvb7+atyK0MX+o25E0OS9guVXLkoptMv
- 6axx9r1GTKTmXubDc+m4FzsUyCtPj766yU/G
- w4SorsdRhRWBoL/50GL3W0Svjywv20WX8mNK
- TcDVIvWy4ovcUq/UmZhJDF4k66n4NsrGl0m+
- 1H/NoOMfxsvQeLTSxUUusYVRdwM= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- O/1ebTLAAO89Jwq3iesQziZ5CaFeLUOUMoxL
- WrHF7zGEkOmRqTp0nhUwL+1mr7aWxkgugF2j
- 5BEHAtq25Kq2QxGl99voqlGG8x50koS7bpVX
- g5wdVq+l0TA3NVcd1VKu7ZRUExBIF4zYxtvc
- 0nHHfHLxzo0WoHfa6WQSEv0FuCg= )
-AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- ICDZ/5MqmxF+9zgSIQFOX1BNjzhpAbl44LMQ
- heaVXzkTfXs/x+JYuUIbhtYIlK9xw9CvR29z
- D08IK2rdqdGMhf7YsmxXGkA5EwGSuDbvEo0D
- FyU/T6rcadaZM8WjPSJX6WxzFryDOcpNvezx
- HQmJlM1ElTwduh1K6AWp4NunWVs= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- KiCqHwkebsPsgcfR+8TF7p1HW7xW8yApXKQp
- dAxuMVge7UrIpKCM9ZxjV/O2lsppN++gphdV
- 8jarDyqNfGz+QLeZqJG1BHEsvHzLvL1KxxsB
- j2J/mVdp3PgceLC856psxsc3cnXX3pO34I/y
- Dy6+5cOxEXSHLqMYUoDyQ/KuCq8= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- T8914GSwUmxdWI9h2rK3vq94xx1ehRX973Io
- LZKiO4HnSNQFohAg16LcuoOEHqdfIxoLOuRi
- IddfITRjfGnJNhUZnQmRpVDlmiogxsC/uYJc
- mq3kUibdBZTluN6OLw9RA3mkXhYsN/xrkuIv
- xUrllJ6K83/3WHIBxfFb7KulZ1E= )
-BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- GPJRQ4SXLTbIgyZpqNndW+K8K504KtHZ2Hb1
- VuEri1H4FhnCJKzRTtw10yEV4V+VS6XWsWIn
- S/Xs12hsL0Gx7rnFYMtH7tFrxTt34u6pNulB
- JAKpYFkrsTaaxLUOMHL6GGKXUaUq5XmYCOvC
- rK2wBs+0qSEKKFwhBfUfaGefyEQ= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- tmdL9xAC78cwTimpNO/TpSafGcGyT+nIu979
- /bKF658ognw5ZHBZ2XIvAO+nVo49qacKDweA
- m5F6Huo7ANEbF/7DS9m1aSu6EzJze6v4ynKV
- yHyqytEQWM/2zaunvPaOR1jQPqwCUyd4E1mA
- RxYUxvCzhkRCn1nLa64fPtvZgs0= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- TUPU8dQqli/nfKyZw2agkdM+ZfiLjUL5L4eg
- N07XR/V47M2ERuHts7kxo10JK0k3/6EK8Oj5
- SEAkqrNxAkpOGy0S8AXX6pjo0fzfrdveVeKr
- Sg9YFbMm9qLcsaiPTM3G/UTuLjfyoRtL2FQB
- i+xAX1B4LWuZJFoA7vE3UaPXY/s= )
-9CGLSFKECUFG8QODUCMQPMVH0JP35440.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- gmFVIEEb3J1pRZnOYUgn/wlBeQ61YfZ5P8Dj
- HJlN+SgUOAKLwmA7y6JDIdhG3jTOC8qlC+74
- Yzy4czwapCMtp8U5W25Hoj32sCiS+CMNzZD4
- 3hVBdm7NQI1PaAZzqL4nAdzZHhUoei2wflb4
- AiZTVHNyJ6wOXqj3xxAPMKgZIoU= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- ozGyuT+NVqxRINgvFl6u67dl2rMyXEDWEWv+
- CFGbuMfgfx+fAkcRj/g0r1RxeJ+SG0SY3IzU
- TSUtTMTavkToBq1oR8uMhZhmeeGD8VsYdbP0
- 7b+E9XaUuvQ8nyhfxuV9fO0dtK6Vamjof1mG
- fP2IGH5vvBZwZFkcWf44lys7s7w= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- RU3+Zw8pEKULu2rnCK8bwn78TB24uWynOa9g
- UbOOqGqLRwtENxVk0KlLLYicN/IOS+2MHou1
- tzRCrIxa7QoxTKxhJeSbv75m7K3njQT5GlQ1
- A28P+CbCU93pPzvvOwwfGMwVOcEAkbsnFJLs
- 2VANXPRhlDMz0sxxtjUjfj5on1Q= )
-9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V.example.com. 3600 IN NSEC3 1 0 10 AD3302FF AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- OFyGfq+fIlz7QWr3/oPOBzDexpQiSxXlxFH8
- teLqjyVT+wyAQ0m38KcGJzpBkmG516MbCFLS
- TNiMcdVFqVsXOs8Y/1dGB590C2cfb9lKF6JR
- n0ARolZ1sToaXYjAMtxZhqTWNa51NwkV115C
- CkDKUQNqxX8fuCnEweN1el+xIKk= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- YzaeqS7VcDuSSeq63+GFgQnqCzrn6Zw5NIyM
- m6qRAJozcYAb92BxHsKYv4as8uj9qV8A4J8j
- w3koisCsueEhgmtDkOU7bBf+CmDVjNEwE2YR
- WWME52NqHQ/tkaz1wcBrMYlkgv7SmdoikQjr
- 1HG1mkPe9SCFF3r7N97rhNlrNnc= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- sCJs4XcYOWK5JRscEFfHXnV15HwkzujcCG6E
- m8GPYBK+SUNEFcmaMc/12afHVZA689tfIH6k
- BdyCBQBcnbS/L7q0SEF978sGdL8gcwWzVlzQ
- scpXokXgY8l2WX3mv9ar+18fJwVkfcCXM8cU
- uBAhCk32+GaG5tbsw98n5wbLcZE= )
-D2S5TIC04S7ORKP09MAEOFV1GN1IQORK.example.com. 3600 IN NSEC3 1 0 10 AD3302FF DV0IMRDKSGUBTBMM94HHURG2QOPJS33D CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- JZW2lYvpmO8BrYK4z9CEGdO/gbOCt8DRZERP
- h+bqs2qUkP/SBawWQmshPI9gi+XtIh/+w4fH
- 3IccRojiByz3m1TptDwkR5ay1Us4oRns1S5F
- U/AYkBvZXwvoYZQkY0QHRwPAvE77jjJRt2BY
- ffpHEMo31Zv2MB6y1H+UkcYRZ34= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- m2c/CE62AzrReXZ+PI+y4k1JkgydR95TxKQS
- McC1MFhldTfSBcjh6c2bMco4P6Cx7iixw+ja
- CaOfHkTqo2NvU7wtBzOZluVguqdmW3SR6l2Z
- WMG0IIvhc446ybgH0WI9X+4CjFMwa7FMxB1j
- 1um+Aq1DQNsCpHchLN4e2Kn+ry4= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- pLamZh+7VkIwYqVhZ94/AzVgzgjFqNyq3tSg
- 2Ncxm3UYxpMPGRlZYrfldUXpD4vfUJgUEmK8
- 6I1UosgxqeeDk9ZWSBqfD5Wh9/ngCqAQgPRw
- oTP3WTaxEb6N7ub8pCozHHJiVn8aZInW9Nbm
- kZQ3xvoOin9mRe7ovFysaKM4ecw= )
-BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV.example.com. 3600 IN NSEC3 1 0 10 AD3302FF CITG8IDONU692P92JJHS57P0ADNMB59S A NS SOA MX RRSIG DNSKEY NSEC3PARAM
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- BnP6ytht0Oic613DxIN3F4JFZu4QB7elZtiQ
- VXQQ7hpNw6P/jx2KJ+FU+ksqIYAl+cadZzBW
- GxRgLAKP5r8m00GKfn1WfVrHkBtwne6s9FAt
- u7B1cKN7Y9J6Tvj19W8uPEAkxy++g5BUrBLF
- kX5GObd5kuCGBqB4SgwYsN7+GSs= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- yi5W3IGmzvS3Eu4w4ONnywCpL2UhDzr3/9u7
- Vf2ascqFbmDAaZv6nD6lc4M5l9Crd9BuoApL
- QVqhLFMbb+OVr2RIQibYf2yElkG6uotMM1vx
- s1osq4qzwYOReEes1p3cqP4CDv5jrD0QJFky
- 1abOXlRUj0xRCHhmQSQdqEL5qy8= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- dd4PChhqHEJ+28qWmXrAvm9oirdHD3UkMlbi
- Q6way4XdItktmp836y505XETzKfjaS4QQDEl
- Amf76VTH9tDCCPaEoAx2FAp3mEwR8/X51+/q
- UqyI6Zs4dxQ6R+jZpa6XV2gE3dp+dtgWjy6T
- cPFKgBMCViayDO30S9lWpkvWgEs= )
-DV0IMRDKSGUBTBMM94HHURG2QOPJS33D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI SRV RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- gEi3yTE7HRiArjBVOT9i2RdNfiYo5H+52Oi2
- ic7xMQ6ZGoJYn76NQOwU/IIK6ss+9NRC+M/B
- 6U3gEvFJeb9pYd1Pt5U3KrlZflbS4XVWBPWM
- rMYgxmXSI+9Pv7mhzdVxqY0C2ABjtFies6je
- zYFDQCM0KZ2CSzl+1MbLwgAeXKM= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- O8H2yYOYWWp10jANk1KEjxrBUdV1PyqdjWfl
- MJk5LfP6Z5YkCSZapRQ+B4er8RQDslucao8N
- lRd48+M+0dtLjBO7U01T95g+lwW+gCQz0vhN
- 4HDoZuEYpewsj2NGdsVRQ+XlQEDK3ULRgdGz
- upbpaoSo5ZiKU56emBvf+Ii/mG8= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- OfTv4bNbctSlcHF/yzFzqfPbubU8v8CUqOG7
- e11r5PlFEJbjYmpM0c+OOgIqDYhk3uUSY8vK
- sKkMf17EnVPGSxHKYu3DRR3SmX+Jrgv9PbGx
- P1QOc8NvIEO4tm9I/AJ7DdZD/JzsCrV+HnwG
- CHjQG0uSUmtcyo8VO0YuaBj7QOk= )
-CITG8IDONU692P92JJHS57P0ADNMB59S.example.com. 3600 IN NSEC3 1 0 10 AD3302FF D2S5TIC04S7ORKP09MAEOFV1GN1IQORK A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- laygNP/hV2kb+vMhexrqbecVRLImwX5+soSq
- CDo0PQBFV0ohHgJBpYElV9tbril3iicjwLOs
- YEco448dUSovQjdb210Za3PAdNVw46PCXj6H
- iPH4sFcLmSSSMZ47Mm8Jh8J4+ERjmwize3/d
- 3UvVj4WILaEiqDjCw1yBoIB6tdE= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- Bf2RUMaj/YvIaZBEtpEIR84I2t6sWwQJY5fp
- 4bju8q0fmCr8K69ycMtFDNrmzcwK+HLmDHjm
- SurPdU6/p5F1H7e03Rw7UhSJHDhhF8kZvY8p
- Uc6geNfrWBw0N53AGVTI6JocCVb1ptEtXyOy
- Jl8+aSVqh+k3G13u0lyxeNqDAzA= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- oBGvU4Co5tEM4KdWrP96N1P/ZDHDt8yI0HTm
- z8bmaBcaSy1IS92xVT6orNyl6m7rWn0EC4UV
- TZVHslzk2pQCkNZnuBIUkrlShcv7clHAInLk
- wVFVk4yiCd2833NRc5WcanNrCKyeg5sC2U2N
- 6WBYspJUQGfqvBgoNSkE4JW37Xw= )
-EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I.example.com. 3600 IN NSEC3 1 0 10 AD3302FF G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8 CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- IGhCvWz93eZHWlqsMNNbTb4NjEad3g8TL15Q
- yAJ1J/1Dw2fxGV5gJ0dCov6r10BH+WM8JDjH
- VQAV7ncI2UXiZKJk3+zTDkL7Wg9nmESUMmgS
- wXwEgObKsQ2iJGdJCEiItTaiWqUCi3EnhGA2
- 0qngKtz8C/foDNT3eLVbeCseyos= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- zRd9YpFH3JFNlImV7Yu+hpzdwZ/sR6UQ6wiW
- FWf5N7ZGLva7fTjdhg3wdq5XDNba7wPc5dlG
- Zq+F7hkAE2xC/VplomblmhDh+40b4QCDGQtO
- im6BoWF6iE66C0AgbiLs8EfNcnuWNsEDW0qm
- MIORJAiSfvihWD/jbQxwFCb8+gE= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- IMOZIwFNLDAGeHDKLMCdChQeICgHE5PF95/E
- okpS42Yu8YrMJPvE3bx92igVCMBkctD5jPXu
- ZEHE19ZPRDFwE6akGF2I5ffFcENuOILHtOwG
- eO+aFLKDoIRd64QMeSPyyOphg44Oc/mL74BW
- gFwtNK3fke+69QQmoA/gf0+BxZY= )
-EAO0AESHP4M49Q5F332G7SOK1JH53NT4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- X/QUrNWKc2lEWDRDrhOzACOmcxNYbKv3yuuX
- iV5Cl7mRJwqELi38+Cp6r3Hux5utyQD/8As7
- CIfuB30FE+gkFnwQJQ6SnN/0cTmfA+DXQr0K
- KmP9VgAjcdjqNg0Ii+6PouhMLV0lb1qR7eok
- cdhShP3OTn3HL7V8TBI+WG4i/i4= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- 0+IhHYExtbNG79aZuYhlTMkPA0XE5cUq2Ept
- G6AwlriXydcKw64MJtw0FfRBljjeLsCV6vsS
- ArrNSTRBnptpy5ChXK82Z93IV+NOzXGrhFU9
- t5vBmk+JJvKeUV/tRl/CC8S9m6JXeVGidUm/
- y0WLQ3RNjtCzKPoLlPghh19VgBY= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- CngXdsTmCn9HvyyeMrblrHxWyh9Y8D3/n9Q1
- JhVzB7jwf2itfRUEqnHGd8FGAR/hhV5XboYP
- p+3uUmykoTF2yp0JjikZwLHgq7R1Fm9Ctcy1
- yehmNpa1Sp/UH4x8BmJ2wa40rq7SZyWKkhL6
- F1Y93Dfqyd9EkHfzbXE8vy6a5zE= )
-E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EAO0AESHP4M49Q5F332G7SOK1JH53NT4 NS
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- KsOrVaAXuBLHZKbWufX6ToCwS7PPjrEdrAoo
- Vw5DBfCKKYRRJfEurtljqmoYoZTxXUKvnDyt
- j1HX3K3PMWUCeSruJ6dnT2WgxFDOC/pMatX3
- flSHbVObEwIDQ0Eiz/ynydDFUVycy1bjDg44
- tfXqPQuzGvOHL2peey/41/wr+Yg= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- 0512KQdUDl9nLYut0pZ4b823mOo+fPe1TstY
- 36ruxDUg42vrh3gffP0rTmV5405H9eM9T38j
- BvGiRtcKC4P/IKLZKz0Q2OrPKaRoPFw5KaPh
- BVWzrit1vs7+IWGso8Ka9i0eGLOT4HgqM1x/
- GB0StyEIepOwjbdqHCsHO7FbsMI= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- DB6n09AUERJMJIOWSa9jLXKmgd5q8jqJ4fZJ
- m3FqEUZIhtBziboYDgvzICIowowCjX3o4HnE
- i9LGuUgvWwQDbda95TmAVqSrJJCNc24hpUoM
- zcX9fWPjCJPHWxZ2ChOjvN+3cp6eSM8lUAoJ
- ahasAbf5BUO6pE1gyNo9b+TsSDo= )
-G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GC9S3VD2NHESSRL256KS0805PL0KAI2T DNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- k+wgT3opBCjyZBY5oJduYiTjnjiNwikz3Ybv
- Y+i4td/QakMa7bfzKVg8RqFlwj+8l4x8hGhQ
- kAEgkyFB9i08F4x7ZXYwODSfqFSebvzmKyl8
- eqJIHSOU/V6F6lUyaBo/9RPVZycjsUzHU1Ci
- +dHXkad7d2+TMi3Tr6aplQYsqlo= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- K8gxRNkW3QTJscsf1pMBv0qNcBqi4pb+ARcn
- ASCH1ykdMR9Pvhpx+9G+u9qo1QjE8EzfkLmH
- Skz3YxMm6Az8zZxXbsWWlscz8aeXp4B6isk+
- HcP0EQFjFcbLc2LZRfJxTABi7MOwEgyeLIcy
- 2SjANfi6PxWOp3cHHBn24z06CpY= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- W22o4fdbyQ50Z/Jndnd8ffhYSpzbgw+vHsRF
- 1sJLXUwYn4GraEm1XnbZyatFGVcFVxe9Q3PQ
- UMsw7XlHkbGMEm1oyfGCkT3PsPLB2m/jknhr
- hGi3KAG6+UonCXkK0WGaHRbJHUOdYz0Qzdzd
- VKV45Zgdx9cKbHvgsaR7hEUYO60= )
-IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC.example.com. 3600 IN NSEC3 1 0 10 AD3302FF J7A75JJN87L9PTVO6HBKH8IPI78IPUO4 A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- FMXWpl6oQPZphacag5FOYqBCUY8Y+zwHjGzM
- zq8GQZrnhV9Pq4/ENE2Slxl6GBoxP7hqz7fC
- k69+s7H9hlP1gp0IyzLSWqqTs2UI6VZaA9SJ
- OBTeRBoGbzDT8uRgCmLuQIp6iVQjgp/xzgAP
- o+O6Ra4Je6bTTp0LvnRLLWRD+cU= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- FLzncovwrynHUcZAelmmRyTyNf1LVfJFa+Bz
- CtwTM6s9a/rpkBRPocWF9925KL8ovp/fav/v
- hHibW1qub6BBVnnluChdUOuFYAuWStqh64+u
- XuKWJjD6i8Orn3chwmYZJt5sIuEdBRYyxOIy
- 3IJjfHra3AAbFy0B4f0j8ccKXZE= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- aepONihWE12b97aLYduH1C+IOhn8Ef31gXvt
- zZ45L0pVsLaAsUoEa3e1x1HsBj0xBK3aYvVu
- K8gmwqB83pJZ4BPtsi6jsTH86fdHuCQlYTFT
- EtGPrC0NyzDu45YeUkwDoh9DsS+JtaNz/n1d
- p1KMYWLGc03LVlKybDZ3z7exw5o= )
-GC9S3VD2NHESSRL256KS0805PL0KAI2T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF H01743IKEGI4JJOMSNCP0VG5S6IPGPIF A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- mbK8uuWhXaxyjYT05jkLfHVgkhG7olI1yfPw
- pWB5WIFgZnaJiman9+WmM4LV24wmCP0ftdmz
- pO6gSKQU57J6kks5hguFfkMbPL9uvLwUDSLe
- mnPKaxAtp+cA4/Zvfo305CvcQFvjmj547S1W
- RO6NUTlA3/GlfH8Ip8czkcMZfvU= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- zP72CxHDH5bnIlPZNTLSp+rl3SgUW//pWdwt
- vcH8Jvfm28ACA7uWxT0n5QcDt1cSC+mIvj5G
- Mdop5eBQsFS6nm4i8vsAlxgLKKpF+Bq+UZ7d
- Ivpvr6Rycg2wlaBptnPqqhQ0rBDZR0PfK7CC
- GJctdwwWCF9tN9QnINTwS6CTq7Y= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- QEKHEQJDM9QgRzbe0D9jjttXE4XgIO8Ykpv/
- UByZYirJRPYrVYTKSPSEUAV52qxBTu+A8P0o
- 6ZULZaUy3fyh+d61E1xA2+lYfa9/k4mYD/4e
- jaFEKni//39awT94AlBTzFxJ0j3KpHGJ5XWB
- murC5SrnLxKZZkbIwulz9G+uJ5w= )
-J7A75JJN87L9PTVO6HBKH8IPI78IPUO4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF KI1L4Q2S3IFEG634FE6DN6E3FGEGV956 A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- aEl0050jrFVhHPlyE/xn0CO4kk0Zq7P/9gts
- iWn4+s8qaHQYrEqfdyKtQge8YCT5eBvpZOS/
- qKE3Fp2DFZAbp/OfAJRoGEwgWICB9KpjCf6W
- FVQHT+Z78xv8PJHvN/uEvL+hq3gaHSYBd2rf
- mZ6y/baxU3bT+zy+LDlDW2MpQ4M= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- djuhZzKM27N7b6ZsGNvcLYX8QpkNyWcFaBdb
- fyxJa5Yhn77RfgQJaehHWHX+by5fw4DdpJcq
- +rTSM5AyhiXVeA8pa/VVrKcH/Im1n798TNYt
- ut8wJTE88P3gvZyxAWNdXhPxCwe+O73uoNVV
- nqdIqikvqeuQUopYaY8zrWfNh0s= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- Z7snzL1A+r8TsTzY76d2JPCFSKk6KYhfkTXV
- tC/qEYHzAZsn4lzk9cLKcEiUMc8UJNo9KO6M
- vTVef5TE9jZWXy1OhbAtgjCzFfaHpHiMG7oI
- LsfzMDCiwLNhFSlDE1oybZrng15/0TzeMQ+D
- M6gHODGA8r++0faiFgw3oTfIi9s= )
-H01743IKEGI4JJOMSNCP0VG5S6IPGPIF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- oRhWX0gctcbRADsspHmDpVzEkEGoe/7Q3D9T
- L81bwvQpDKfe0Xa/ksLfHdElnj44GzK6CiDg
- 6b05S4yKuKUjd5bbx3wyA8Wl/hMphhdDn679
- zCmi/+CFHYMTTXZEk/BTa5GrMF1Ra+6axytU
- AXzHYRSF8u21f/8mx1M8Scn3n9E= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- RMVgjtaxet7goMfOdZlovbwoobRwOjABu1Zd
- HhAsygqytWXgrvb4GSBa4OgjU6wnZdP4uFpt
- LeWINpZpaEdLsrw+Ee4hsm+ws886QDEvUZOH
- lvIaRro7gJe/cXHydjFpXNDvVN4r8PwV9ZP5
- PL8eshnUrhaDKYWygR/A7Ahe3Hk= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- VVHm6YcQyfozsGT/Im3xLGvRTy8tBpvhXtRP
- 9qsI8U1QRURciaMa7NH3D8umdxpWAMjTv7A7
- mxr8PPMjCTZlVMIdacWlSMTW7YfYmMjnbeX/
- tRVK2RGKOgXmDP8sY+TuQrVq3w7UQbTmpWzE
- Id2tmEhSb4FCAUe1hAw+jmQs/bc= )
-LMQIHH5MDDR9PTGEHOHA5ND49685RR01.example.com. 3600 IN NSEC3 1 0 10 AD3302FF MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- TTRWTk11fEIZt67lQ2esQ73vETMljLS7T9EJ
- R9IdbaZwtCfyALht+LIw3UKAzuvEahO9m9c7
- yJA+2WalAv+2KXu3L3iqcVKF4CPRR+7Z+Nxw
- +D09T5h+mEzPec73tTpTSG20hK65jpRd8QZn
- t0qsAgYGKGBpYG1pYiesuWbH01g= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- XY2wBbFHrXJ5B+Kd3o4AevusyoEUvK3ZUlG8
- L7WYDcuopoGIMv2BuaIbjYON2PjTc3DH9iRx
- gMoiKxhpm+fH0dCvH4NVrxh+j1xqgGSjteNq
- zUOyxXSmhmNOoDBiONzxWqKzveVF8mHRCEPr
- EGx+LKO4gApI9HnE1xzqOxsNjNg= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- hmqTo+lS7OX5KUG8mQGbYz1bUE4xleqVYOq1
- mJRjHAwWcLX7u7/oHDDCPlqmBWTEyLB8RwBU
- p+QPPnJPuN0AQhUF8SWivdDQ4H5uzoOd3xIv
- +IraKdp/S3qR1DDo8rCb9KFuLIhTd0EDkk9i
- iF/ov3pQAEpEDeXgLeXMw73COqU= )
-KI1L4Q2S3IFEG634FE6DN6E3FGEGV956.example.com. 3600 IN NSEC3 1 0 10 AD3302FF LMQIHH5MDDR9PTGEHOHA5ND49685RR01 DNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- X4P4YY1MsXI7TQsjxNvVSxbPuHBOnAanBu7n
- 59EYn88vehSsSfk5KnFurXxLrVF9w2friu4v
- QMA97HwAezAq/JmDWRctDSAZTNO9zuLkeKfb
- Ux5jAmZWN8c25FQc3DqbbN4Flp7e56aTMzCA
- PzXj9E5E/T6Fn5nqWVt9QPrFTpw= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- qGLIB3Cbnq987NgFVE3mTjWQVDrrWgDVDKCT
- umklyY/pwr6zooXROYhu0hazTs1iLqKvYfgS
- khfNyU+ulLjsbDQ1lnzMd4z8n97mgG2QzhwY
- apx3e5LUcpx3oTvXPC9H+jA0anMG1/VwPnwU
- qehhhR8WZRyCnzVO8Eje1/9bonE= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- N85zcB7Q4vImuCyq2MSxd2E+iwOzHCuuJ7f/
- LUid0XIfBtG4vRFN3yfj1JDmxPvuYuYhsrOF
- CAgCKWFmqtKDuRU7QZOH0RBGn3XeDzNBmFgj
- Ep62rh/ppPpnRZ2KmGn3wA8R1wZ0At/NtHfU
- X5VyBUZkhMg8/+DjmC+rTNsRfQY= )
-MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OIKQOJ12077E6HOP6HHST9DHAMGPED5T
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- ngYCZ4ptY2sAOs3nNWekbB90cbhxXuQ8Kpdj
- 9oUlzVnYyqD/fZ82l+wXiOAbIH+lKxdN2Q2D
- NjJYaimQpv4UoOL5zTfcxTfVoAmJ8S5v7Eln
- Bk0KZyGuSvU+pfXkLZM+9P82XmdI3maa9MZh
- IhnDZi2xXuXIYsqXk1n3/wucf4k= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- YBVuPeXL+OY96fwlXYPYrc+KRXubunNndwpM
- UE9SkaL/RhurQ0xpXjPBpeThcJo0gKGZa2dl
- f55acakc5VL4i5MQJx0uGP1XFiqJkx2TVund
- sljAffBm7Mgkonumg0CcM4qmx7LT9SrH3J/w
- tvhqbjvF9Czqb13usaqiurU/2Lw= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- Obo0lj3v+eAEe8Xk4aSow3GYTMnK5IAtKBMo
- Cc/5nlij7T3pIPt+q6EbWcFpRHDBHEJp/nm4
- Ic2WjTbmlHf2o/3w7TC/TcV2qIxeZ8wj2cmZ
- +TrfxRSON7ybKqrBfAP2ZBlLcg2Ik0fbX0qe
- H2L2UCR40CE40YpnCvuOdoiGZ+4= )
-OIKQOJ12077E6HOP6HHST9DHAMGPED5T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OTMDSI120AJGM768VIKPLND04FDSUQSJ CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- GvZZoTVd15j1afy/UoqeYgXsqoO7+P0agD+h
- Jc/osBG+9u0FtrFvcgmWPVWVfYSiGgtcai41
- D9sJf3bikuLMdn4HYkZGehVuEM2Z7PXFRVVk
- NklUUxxXquDo4GyHOAP/44/l73u1sCF3urof
- VrrkQ0CS+OmEko/vwl1URkl28p0= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- HWdQqAItWDdlnydvAw9wZFrcSnzgrPRBlMIC
- SkRHWe03X0VQWksprbk6lAJH/DIcQ3g9TSKV
- W/v+ye6AmhRMKGmebMTabvTxeBqQ7YIQETso
- SBUR+a//TleRx2wAS0XI0RQOyAflCjZ4J/Us
- E4Ma9Y64AYNo9RUX+wg//d8RBzo= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- pIRWEqeSijTmMo2pM993IPbzynp/hg5Dtwqt
- 0RzOslJ0k7KP7EX5ImvlB8igRjnmNkWJ+7jT
- oAdQXmwxN7NZgs+R/e+/312YYm6WYWzoM8Zu
- tq/PFwPggDeWRlE5dv/i880SvB6V8X+GfPd5
- Kv6fxWPuVo7HuphHEfV40thmYyA= )
-OTMDSI120AJGM768VIKPLND04FDSUQSJ.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- jZfAumkz7cHAi7LCOwA5WfvxSbgYbnwvKpoJ
- 5pEwKN7fjIgT6EGrrQ5PgQNqPnzGGS61cc82
- zMj2ExiYJR84Brc/l43dCkq+IikN3sf/EmNU
- cwmF+qYSsbwUWV7uEXd+d8deYAhxO559Rrra
- +11OeNNlPsaBjaS3cRIJRM8S+Zc= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- HRl88fXi1YI/C6e9cQZLWBDm20OSqTqyjuLC
- 1zdvUES0bo+KnTnvwfrQohJbldezjNyJTihl
- KZYKTdxxoZpBY76YQIn2fjIz95o1r4VuBkQX
- /QEXTlSStnSDe/N1xhqvigglQb6CmVOHSJXQ
- bB17NNReYLDhph23URS68YxYJcs= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- aF3kJqcbs2+3CeHCxGhYy0PNHb5reqKrI1SS
- FpJWjE7z3bPq/shRoDaJhTZzryS9Z79ZsNlA
- m8CJeu3gEdZPIa0iaeBtR0Vk+1LQhRhfmaJk
- y4fELM/Vpm3C+6A8mHCNL4K+kK1wxdIRzL1M
- 7MvZXmlLERS3pU1XrznboQGN150= )
-P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7 CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- HFoa13mfo+lRQcY6Y/9iM9k05dj0UxOgmVlk
- o2p8eLh8gVZBcEX3vZYEVx6e5RRqdfxANC01
- EivLSMDAY/y3Lj7ZSoUX6TztjKiQ+SRdkEa7
- 5RPgvRBbOdfZm/R7gsOnUOXKgFne1wCPzI6+
- mEQ7JgTzZUazy5ggC6F3DPkDf6I= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- 2Crtwc7SjuABVPbfojQhXFzhV+dbHIfoxmHP
- puFDUHszttyhGBSgZ3zwJ/J9+TXqq4M/jP4B
- 2m4bx9eoCXQtUdkxAmPCiJkbkvyYTsE77lWI
- t7z18GH6BriPYUot/6EeYlToocyZnEoeDPDT
- +f9nRM4qL8Jlw8KnXXG38gSvkg4= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- DZe6ordphHAB6ReqwVAp7V0c1XYd1l3UZdkN
- uXNg3JM7iYmoh1MJu9a0Dj6FSu5OyWjoTu6Y
- kNx2m0XXFRvfXiEH7xk7ke6Pf/eQ+xIjynJO
- uhZL4W4D0ZnBpIaXh2jVilexNJms21GyiUZ4
- Q3rODRmym/KG6wsC5SlQSm26k9M= )
-P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- a7ZImTzIoztA8Smg0vvQAZ3vC14Y/nb/60/4
- eHKKjBK1VH/nDzuVvnpsCEBLJWm1nLuvHqDg
- 6C63qxZbnclOwssnfow8aIV5rbiKBk1HHoge
- tzxJQYe7a2hotY7OTA5s+ncJdyUuS8w7VUIP
- JIrF+tE015qUTaunILXfLydQgO8= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- 2X+O3SnOGNuLp5HXNpiuUHCspLQUCagtU5uQ
- 1qxuLLrsx053wNIJ9vC/BNXssgdZggxYpXqp
- 1nzpzk5dK4nIwmOYGhJO86/FNZu4zgt47yQb
- HEfXI30hanTyuG16kNVGycpbPMyzqKEAJN1+
- 0Jv30Wd/CFjnBTto6Tbq7fEkBbM= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- bQ+F/eJYMogZ3b1SbvotL2/Aoh+UI5/McQIF
- G9BB+1bQs6tqLszPx7P8PjvxJDxt8Q493M4l
- INvgZDQQIaFNqMMEh0Eus17OAx1EqLhDK69C
- klX1sXbZGhQqNbBWvTeaF74T0tFRVLMgtIFx
- /Np2gCA42NGQskIsBGN4r3N0tqg= )
-PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PSMSPPC19D8OAICCQ64C7MQ387MTVGC1 NS
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- krM4mSHU0B3KtQQVoFCBpdAecqSj/7Oo4cyd
- YQNuF1CvChDTHFGs5BjpMzKxrBlrNH7wXk6C
- Z3kREpgK+uNRU/G3XPhYqG42lO/WHHIRiWBT
- iEcUXhpLYLto8ro0UWopUPRRItotcjXFhSNJ
- BzWcWphP5+fa23odDEPCO8ZRyR0= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- KPEs6aIATlvmzk+gl45yXM0VDYMI3fE2uHAR
- GSLPehUZDXT4IYdERA1eQuiAfMkadomjWoQ2
- D4VvfBf3Ho7ilGmsms590NvE+W1UZTF51CjD
- fyQW2+34UdgsNmNm1dIKv1sq6llQSHSL8kzF
- Aum9ohDU3CS4jsbj8/4LTZ5+R0I= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- K41ckswo80M0l8+Cz3SVDqrFBbXfToKS8Gzx
- pr1HycM3GblmriCBdIgxOAX/AuZZrDitxkzK
- D1hNeKqAmW+76zPw0vxocX/tdnjYgHodi+FA
- dVzOaMlbAT2gAOUp8BeQOgaE+k4ysTqYt2M3
- RxOB0zDtwXum5/e4ZYYWNmjBBcU= )
-PSMSPPC19D8OAICCQ64C7MQ387MTVGC1.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RQK67K3ON1JGJ60JNO4883D1JVIOIG2D
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- VsNIjTrZUt/0Kyw+WYP0P1F2Xq0BgyZxiUBT
- jwFp5etUAx/fx6thM2L1mLadUpb9m4R+JxXB
- b3/fn9H3E+oqvlzr2p/LGcqASohdiqmCADdb
- dzcqqYaKbqjUDsNsJuhGz2iWSccjOTepg4kn
- gFdp5em/jmqYr5X5xZuv/ZsPWRE= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- Ouj1pNttVU3EPD7qDicNu5W3CyECZjojxusF
- cibOFBQwLkK4a7RnsTbB3EFuW06pMpo0JJ13
- 2FIvwOusess7AgKC2ATyAgTY3lO+Ja7GgK8y
- Q20oxMw/wiADKJqVNoROUPVacdSkU+CkBC8o
- CvNXyPrro0g5LOzSgleeHCNSV4g= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- DY0n5eh2Y4XcNTCWQmDez4EtkbIcRLLXSDai
- iPEnk+JITGaaghxMhnvdSAyl7OtQbWielh5i
- L/toRRJfWA0RcmWvzzNpNZm7EP/+I86KTdCw
- fUPt9hU0XTzyP32FYcw+NosauxrMD7prhE0H
- lyXzYwT2m4cnsSqvrAIfZYrlFB4= )
-RQK67K3ON1JGJ60JNO4883D1JVIOIG2D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- bWfMW3+ct/fNIr14DZxhQSdC2xqTFfSTFzch
- k2+zrsoXFL4JyD8VC5dUmuvE0JHMLRBQs2SD
- T+H0L63SV4PZzyijo4lLSmz0PzdAEaCagktl
- pwD5as8jXb3+uUx1qlrpVht2QuwHjRm9AMTi
- YZmX6wYEyUTTC69L5BC4VvEkVvg= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- zyN8D+2X2PEvIo16h6sok8m3M3MCVqiT6P0O
- sqSKVKoQ4+xzxpIYPOUPfRH3RWZ4D03II1n7
- 2gtMCc1kk8Y81D8I5L0r67WmAAj6QNtL7jpd
- jghl4uyHcp3yKy8GDaKreugWgqZ6ew05vXVf
- AbeSJSXFX4+j8TfF3z4M5xnWpwQ= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- Mdfdwoh4OlXhe61DmYTzQouDjcvfMLmAQihD
- bLy2ZDMsPm6cv3GykhvrVPMVn0P19kcD9hqd
- LIKPQlVcrpP+H+WCgDI4Dz7UjHtmxUM2s6KQ
- +GzgkD4ttn07cjY0xSrT8lhpPbDiwK4V+RT4
- pme25SYDQFbcGog6IgQycgrWGeA= )
-RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G NS
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- JRrCvpMfhrk2JClELV805D/pt2a2YhBRROOt
- 6dUZ18ZVQtXPOzvI5TEOuhFEFaBTPC2PrDfX
- YBcM1pf7mwD5gTnFhrD7vXwsR9FUDw3sUx63
- H5Lkp/zZSqt16eBUmwYcuSHceJ3qRrvmgfi2
- GYP2c6kft5O7DHXFoXKcUBVsuMQ= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- hwNx2shB/t2gB/uc18S8Aaw3SXjkJq7txozP
- az1JyD14ha9CpzhWMEv0qzENQAFezTapBA2t
- T1FVUaSb3BaUC64w60N3bjmOQk5hycQ59YdU
- Nuo46i9o3tWgr/1Vk1ZTMBw9nmXMY09AzLYa
- qUxrgVo7IDp7HoE8UFl6IR+QqrI= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- JdX++j+SKyIpuad/KA89T1aVWR5927xQLK8M
- 9WRe/JJEaoJoi7UKboTlAQ21AuGvGwu6wB8l
- T66ZA49z5LVU4aq/TLI6u7OzIEdldmypbtjB
- +xTvlLApJ1Z+CouMLzswIjdrOzBU8Zl2i21P
- Gm2Je720L0Sgg3WCqL9rQAEErvY= )
-S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS NS
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- Tu+XjkIiVrDubGLnKLgIwiP0V1dQvKXVQySM
- A/qOj0L4Eh38P90bjoVsD0Y5Xt9TEhbyShgX
- bTJ1K4qhLX5iMejg8XHkgxPM1SckGy8xgDNq
- /udOmIzHSjh6Ac9xHZv6ADvahqAQLNiuso2z
- 8P99fqfqQVIrdBD9c2BEKs0Hdao= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- JWLrARNVKUnnwK2DX9Y0BBaDWMuVlNs5EN6c
- EAnPmwVF4lXcD5WNkWSEmj8c5c3R9VQJAx6H
- PhpWuw2olxwPV91CPeHOO7Mw8y5wCXcA4Zoo
- sXbw/WfpjLYAPdZ4JSF26t4NEjQ7Zn7UNZXT
- TCBJjHxdFTEGmc6852z1n47lDwg= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- cLPQugaP1G96bBA/u90h07bXtzgK+rnNmdOM
- /g517Rb+0GwPrJFPNXKN5okoL3iJabyNk5DI
- BxlkXL3rdXy6KnTBJA4yIFaoR3YAl0QtpuJi
- vcpCizL6aEiQKwq8yTgIIY8CFt1DL74Oy4XS
- s0lUYlhApluMNBGzE1LP6OIKuMc= )
-SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF UB8IU759M5EE63CQBISIRM9C0V2RU1RT CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- GacQYyh2UTMay2+CD8d9tADE4LWcflUwUc07
- 6tWksDvwyj/Rp9gR6p074kvghPhRS2h5F3Ik
- HCxzNY61If8aCaOlB6lrv3YMfiuJoITFisqo
- vQCNEtIriEENdFOfGEMZonw8WMKP9fnw9Zbq
- LiE9/zcKCcxN89FVxSz2PlX0vEo= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- p+xzV4l5PxxSyvwiu5IykFbYxKnXgSRtHgYz
- 2+bCOMBGyv7Snt/VTkZNulTqBNxEXWDZRnfP
- oo+2ingu/gyInx0cWLcVxVvHGdPntjUb0gbS
- Y+dlOh8NvjhkdEpahZHMMQDPPdkFS2EcOUiV
- T8WlOKz61Qj8C+a4dwpW8hdJNn0= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- GHtvMmQUXC33TVgtFdqaiK5jVJCL1WX0LSW+
- WBmiAejPji/26k2uD9Bc2jysowrHD0eUOPYa
- yhwcsn+SUBWN1QoTcJvyyx/vtXiM5xgqsoyo
- bgZxtO33SkqoLUEG61NvKJKz9vXuJtpjZAXF
- bFX2l4czAEXwmdLW+IlhtMwAbvg= )
-URIDB302IVQCE7DQSKELLE9LEFOHV0LT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- bJWx87h9mPriMU0pNbZoM4ejR0P57hiZ4GTU
- CGvFlO4TZZ/4i/iPYDN8J46rA7diCaEaOhIg
- m9SeRvUrIiUw3WdI+7sWNI6atXlaNM+LY9un
- OGueiKtabYt029SlZegkWdCqNyC70vACtBbe
- 06d5J1HO15wTrtCFNP3N4MGAuME= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- qu6bqA2HCxnxvtQ5ECzMh3gm42tZsWGzC+66
- s8t97N+HXM3vv6qLQ8xjDwF633vtMY7Uuieg
- 4XONpJoU3UxyFJ//900TuQ8WPHzzwSm3ORYM
- 8BiKOn/eg9dtIxpYTelleOSzmen3979NAelQ
- yjmyx+nNzvvrj8ZEBmB7OfB8oAw= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- WyR0ilIZAADX3HLXYuyvlhK9yRAbPFv3vtOs
- DIlg8Dj2F5hgXUv9V6AbuK5nEz19S4og3E72
- JN/Z6QINx9MhZkCnzYFOHlS6GS+zqayPk6kp
- 3BGzDZ/jYJ0KsUGrTIE9ritV4lfs9Ns5jSS0
- 0Hg89y8AK8KoMpvnTuzTXt/iIQ0= )
-UB8IU759M5EE63CQBISIRM9C0V2RU1RT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF URIDB302IVQCE7DQSKELLE9LEFOHV0LT A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- BKqTnlAxyPcDJbWH7r2o2GS0wipIPD2fj40A
- MWIF8hOtF/NwN5WAbdVjoyVGI31G6CTDGdD6
- TPllaiCCFi7yEKm3/vBZfoX5uZhy96ln4G/0
- SbRdD6Ooy351L6HPlfwJLmb5a7CBBkBmTYQs
- ig1o3XoicFPRQG3clgX9v1UQrIc= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- qWWyZ2Rh83GyNUcw6ftZSDCGrYvsB7E4dHat
- 3+reQZrNjmAY5GaIvUq+v1/Bp0EpRlbx64C+
- H1MrNDv3ZQ7L4O/Mc9YnOpWpEDs1g88ONmVK
- lsZ2vBeT5PdEVsM8VwxRaTLHzZ+2ddn9/zQW
- fjb7woheUAr4U5ga4h4XAcHh6qk= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- E6d/cFSl+89rhmjn5OXRaN4OcHmdtAgqaDQQ
- gOk9EwrQq54XKgzYa6zT0VBzznQZlbsOW87X
- jp3C/RBdWR7VOV77btuko3jWYYSVvA7UDseG
- pr7TNEZSck0bJuih5Z/axsGioLNiUKW95XwB
- 63n4EGBC8iIoekIDVi4b78OCK1E= )
-V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7 CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311113926 (
- 20120210113926 13760 example.com.
- PUxRemQkIzsdDafT73oeBF6U8M8iFHdL2ACJ
- h/Kw8TtZfZpulj2XxxeU83BqAICpZdkeqbZi
- YGJuqIN3AattGV73O7nv5rjIhlhgDl0UgOFu
- 5cIC1My6qYuqMEosQHAkokq40ZhIcWEFOy7P
- S/Fd2r+ERPkLNDUGFyIbQzYEpyA= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114013 (
- 20120210114013 59507 example.com.
- lNMX0meB0th1kePzZAWX3NYUAEGNJbCJmeUA
- DsQmct5CmPObBaUjUQF1Y+XFLlme8BQJVUnj
- GfthFJJhPmrW4AvDNMMRbXo0wo4hIWn6tlJF
- xkTDcFB1BRz0w3Dz8cuXTxH2gpUbtbOq5FcG
- 5ZmYDo9akGuBdw9okfRuZ7S8xm4= )
- 3600 RRSIG NSEC3 7 3 3600 20120311114036 (
- 20120210114036 58574 example.com.
- YI/o1LESLnn3xIcJIBJ5ibKs2ajwjml70lMS
- 53nM+EMe6lKZdCmdB9BRR26PzhKNngWLakI1
- 1XarAJD4gM6hJf6DMqSWbrOpfVpuePFTiVH7
- zkJfa12Qcjx4CFviV0cCdnQRVAsv2X7ajLcZ
- 6QszvmkzIwR+HdsY9WeFBZ9yZ7I= )
diff --git a/samples/example.com.zone.signed.nsec3 b/samples/example.com.zone.signed.nsec3
deleted file mode 100644
index 88a28fc..0000000
--- a/samples/example.com.zone.signed.nsec3
+++ /dev/null
@@ -1,690 +0,0 @@
-; File written on Fri Feb 10 13:41:08 2012
-; dnssec_signzone version 9.7.3
-example.com. 3600 IN SOA ns.example.com. username.example.com. (
- 2007120713 ; serial
- 10 ; refresh (10 seconds)
- 30 ; retry (30 seconds)
- 2419200 ; expire (4 weeks)
- 3600 ; minimum (1 hour)
- )
- 3600 RRSIG SOA 7 2 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Ez84tPNF+mHlVMRW2qXS4yLcaKHtlqAm7bmn
- DR3jI17pwqUyJ+aFlZcuWLbGf8ipWfEFN/zh
- +sn3lAafUlbuPseAgqOnaWt1OEMxPK/Fj4d+
- DodZfmCXru7Fm/baTXFB4GH94PeC5H5mqCPI
- oD3m0/c7OLDIF2t66xs6XHb0YB4= )
- 3600 NS c.a.example.com.
- 3600 NS ns.example.com.
- 3600 NS ns.somewhere.com.
- 3600 NS ns2.example.com.
- 3600 RRSIG NS 7 2 3600 20120311114108 (
- 20120210114108 60914 example.com.
- BauFYgGnXIOYPg8vx45JwlTJg/ZGrefAC/cH
- uOpCgezjutVKsYAwKjTdUu2/YnliLPl7qTHV
- wMEandEUUBhtMmaMcEqssw1fjp6hDTnPzjKh
- WTaZMObi8oJzwTg9rrtlaqh9ruWlLvwmX90y
- /WlIDQBob+YcrkhtmtRSadojRAA= )
- 3600 A 10.0.0.1
- 3600 RRSIG A 7 2 3600 20120311114108 (
- 20120210114108 60914 example.com.
- uOArtqyKZB7f5iYvzRkyp4B1doREoJ4Mnh+P
- dSmpRn4kklovuAB74kNJCy/eb9Jajtg1Gvf1
- ryNFdyRjsL5KYG0D3O9CljV1/9RAGpocp5HI
- BWOgjOXPT+qpKkaV8+XP5c3uXsgsc8x0Xbd0
- EUqH4MF8mCh32m/TWqR0xhW2bvw= )
- 3600 MX 10 mail.example.com.
- 3600 MX 20 mail2.example.com.
- 3600 MX 50 mail3.example.com.
- 3600 RRSIG MX 7 2 3600 20120311114108 (
- 20120210114108 60914 example.com.
- B8uDHsHFw8ArmcuLU8oh7LppxtvDSGQE7hgA
- VTwiOuGIv46xKoxTcZUpZhGMrqvFiXmgYS2j
- Qq4DWCYjpDtXnfruZV0pXmcJY4AB1Blp5g5i
- XK//ZIcX/gyHs2JA4KhQWtg3KfQmJcUJkO6q
- YduW9eMycJ61lZUVCb1jwQE98+w= )
- 3600 DNSKEY 256 3 7 (
- AwEAAcKiv8JVo/nwOl7snGkyU8TXRXfRYuKx
- QpA42gttcSGG00PhRTCWrhlC1amY0fmgabvO
- YVdkM2aK+NRTz0KLitWbvkfM7BAn4QUUR262
- lxCeDXFX19pOPdV9G5hD/4X7EkilsusiAGwx
- ni0lJkLVhmrEtvLSm4r0smcr/Te7o8nT
- ) ; key id = 60914
- 3600 DNSKEY 257 3 7 (
- AwEAAdjJ0gueZiGl8beGI/a/D2B3svXKQbg9
- uh2J/Amfc/IgrjjzCWiBoajADo2D1A4MyTWS
- BtOGk31LCyOumJFTNr4/vMHSMGS7dXX7wCMo
- sJjBgMBDnv33uiE0D6RFgw3X3Xg9ftoucRrs
- lG9MMZpKcFc6v3ajLckgGj0vHFmf/g3mHwXr
- 7htSg1cRVzhVnC098bHRqLQgcckzOxDQZgUs
- UVQEmNEPGXyURPjqVoMaWZPSWB34XJrd8q1S
- qshANW/Cz550xhXEp3de4y2bBrRIgJdrcQnA
- GqVb/hxn51i6bj0R5qRtcIY+OWydV8DCEOmA
- I0E+ioifx6nEgw1iHEdFU70=
- ) ; key id = 41955
- 3600 RRSIG DNSKEY 7 2 3600 20120311114108 (
- 20120210114108 41955 example.com.
- rcZlhmkMpb+ZUt6xdOZq7RI/7p3zqLEJzMwu
- 5Nce2Yo7fQHjQGWI18+HA2US8TKZKwR2L/MU
- MJ8cMx7ElaoEmFnebjq1cnMcLt4EHkKNMSM1
- LcJAGowmC9q270R7vwAzpyCCToT2YDN+WO69
- 0G2lRSGjaGJR2RY8o2+zQYNU1jm3R8NiXlen
- VKywg9jlrkdQ1Z6MnYQKuywTZjDb/mhjbMqF
- ANKf5zgDdvZI9y3tb4EKkGHL8sE0xKDTf+tT
- GdSiLXQi5FTD6eaCclDB7qd0WGPf3bkTAq8H
- FofDcE+CRi+9DGReKiAFR3w5Ujq3LXkQ5swi
- xyHTyYUlWvfGg+hZsg== )
- 3600 RRSIG DNSKEY 7 2 3600 20120311114108 (
- 20120210114108 60914 example.com.
- PtLvtaPNUKfcRbrQKM53Qo60zimxVlNP8uPV
- 257uSmxbDnmkOa38O6xXISdgq24SW6mRPqW+
- YZvXu0C7w4aZkbCgfYBmFeplAXE6iBVXd4Q+
- s6aOiqaukTn0o918nrCOCbEC/bXlPRcpRZJg
- 65jQuQdRWdqK83yRzy1J/bSN/fA= )
- 0 NSEC3PARAM 1 0 10 AD3302FF
- 0 RRSIG NSEC3PARAM 7 2 0 20120311114108 (
- 20120210114108 60914 example.com.
- WuKOUKwmvXyM/sIVaz1AlzgazTkoCNKgS2jE
- hxhzqKNHbNMMzvd5rH4lwg1z1NMDBcwvfhpd
- 8qpt+Q2NklIEUC8Db0DoKdD9HT+zt6k/erhQ
- JJXuSfoypnPhrwk4rs7n1U4X/xXbmOctTp2r
- SFY7FAbXNtjQwE7WB0wMkpfoJTg= )
-_foobar._tcp.example.com. 3600 IN SRV 0 1 9 old-slow-box.example.com.
- 3600 IN SRV 0 3 9 new-fast-box.example.com.
- 3600 IN SRV 1 0 9 server.example.com.
- 3600 IN SRV 1 0 9 sysadmins-box.example.com.
- 3600 RRSIG SRV 7 4 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Kava/zmrJ9xXbNDSuq8qPwTrp8H8VkPWuKLz
- pmY8Test9DbhbX17OVwOrRvb5npkiD5pjTMV
- gPzUc7g3UpRzORTlf4LW2j2P5UWB3IfCBKJX
- zJXhW+ScR+jRX8T7ZQTE1Xg8Qc2lvPsycZiJ
- i+BL+1uIsyrXK2/T0oAeLhF4O30= )
-*._tcp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- jCxrJOjdRJNyCqPsuPlFYo1cYXn3xACjWcUQ
- a+SY2h91wgtwOwy3hzPvx5G9UbynqtvbAplW
- d1q/pJwyfeXf4k3BemKJiPVYl/S6CiWk5Otf
- FSdiTsKsYgKiyG8cUNcXOLteRbYt0s9Y51nU
- zhEfhBdRFXG8vy4sle1XA6wkqSE= )
-a.example.com. 3600 IN A 10.0.0.4
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- YzA/6SJLjNJmYZ1BYjS3hgiebRQLlcjvn8IV
- jU4c2FCGW+H43IIejzaIwlvuWUaXv6hpYYBL
- cBudB3Zw7t4IfgT4XMkbEVcCfv+Gu3TLXn8a
- qAblKbMxRHbWaqPi0KYHMptYqm3xmChqRqHs
- h11uOi2YbA2cD9SqXhMwupIH4g8= )
-c.example.com. 3600 IN CNAME c.a.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- qaA91r8RUIfGg7QXqviyFKQEb0P3lU552mX2
- 0tzo2PbdEWbnQBLNtACmhiG+nk57RYkFAPaY
- TaexFiDwPXYViG0OGUiZUXJtVxXCg+vgW+34
- ZRH2eEhTOPbrBKc/bHJ1Mo/1O2oOYLPF23PT
- 03IF9ywBmwXnhJBwqzHJPitJ0LA= )
-*.a.example.com. 3600 IN A 10.0.0.5
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- JTXlbeNQRnhkGUrBRb9kY9NNzPRIV8oymIha
- ZGWwQFB4WjjSHSnrNB9bu7pXrYL5V4fwy4og
- IJexjAqteTlDfiBsVCTs4m6V/5XMWBGA1tet
- 7FT0bwPYnYrV5ij79KYogYVXbIje3g26yAT2
- TtHxp0VqpkUOHLIsPP/dJwOIi8Y= )
-*._udp.example.com. 3600 IN SRV 0 0 0 .
- 3600 RRSIG SRV 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- GXRBT3HhPySbPhlnRIi3y+de7Ptesf4JDhNA
- wTUoOkanLhnsE27u51OoineUchRI8AEKtejs
- J1J8Q/iaFTn+nIEk1yVBZTz12NENRgJwX3Vd
- XWQHWnANx7/3u3bXuHICv3q4NPJXO20j3a43
- 26hlFkZt2YviMJq9l4FIeVbXqfQ= )
-f.example.com. 3600 IN CNAME e.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- aLrdCDbjTkJ21rRaCn0O95ch85kIVQtcpLWq
- pNwZdEkFG6nanUsgqFwAewl4n/PYxsHhqFlP
- bNO/rL5v3Aq7CyyLZ3NM9ZSt3wermKBpseyp
- jaBIrcekZeq7qUJXEJi/ZlffnBGGFjJtAXpL
- ZyP6I00MYcV1FP9VYkPYi7wzFig= )
-e.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Bh6S2as2/EjwihXV5FM8hC9urhLMcXCyhXwX
- l+/cRM/8Rd0hKZEcoMVN5U8f163hZQgueRA8
- J2n8kPSQ3tdEURCkaYdvgU332pJgBpaibWYu
- KrkvyPhK/4YkMYkAj245ioHOln8G0wkf6oTW
- 8dpM5JsAvSAckJ2tK0fBIreM07M= )
-f.g.example.com. 3600 IN A 10.0.0.20
- 3600 RRSIG A 7 4 3600 20120311114108 (
- 20120210114108 60914 example.com.
- TwU34N2AwNYPmwOy4J9LlaOgGmX5Sozmk/Re
- pjrkEmRTtCbxmYNJli6LobKFyAxwrF1tan5o
- z8x/kX4zOR3iBr6dR2fqJkC3VmW9fYLPYshY
- SHKsbD9U6903QpxYFGhmI+a5A6/0HY+pZyO6
- 4JFmQATfvRin31c2SHkPckqgatU= )
-d.example.com. 3600 IN CNAME non-existing.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- dLQ+FGitt6BvKZY1/TCEpH7soI+V31wPb2lJ
- AX/MevBQsfVIk9BZW5eeqEcf6YqvHi4pBo++
- 1pD0NDnuDJ3UAwLH674CQnJEUKZNFCyM0z/A
- rZNl3HIszRNf6tJG0flMtQczmWlMOejmuvqL
- vcYPTl/0ON6vuDeB0HA8G5NQgmI= )
-h.i.j.k.example.com. 3600 IN A 10.0.0.21
- 3600 RRSIG A 7 6 3600 20120311114108 (
- 20120210114108 60914 example.com.
- qvwrNdbdE3tyfN4OUZqNmtdMLLavwbwGc+06
- un4SM2DL3G2CWfxun3nHnJOwdgatWnlmMMEL
- kllvuQhtNURgkP3WOwBhXJDzWCvaLT4E/Gvo
- Ni23Znh8jO5Ef8RndKQY/cnIJOdh5JcTOl54
- z64rLoW71qfxhVAAZy0f08LHKis= )
-*.j.k.example.com. 3600 IN A 10.0.0.22
- 3600 RRSIG A 7 4 3600 20120311114108 (
- 20120210114108 60914 example.com.
- sw2Hlu7zcahxgTCNiMBGdK/svV0FH1sy8a/h
- ixywRiCYgtrRyDWjgxFMNP1wpw2I6d9QiiDr
- uha/I10eA8Ku4J78YY1HpWz3Lus2UqLeXKrf
- q7I5xa8Pu+SJYIomZ086yp63ZH5z/dVOcMhh
- rKrUiISXfFL9mvACTLTzOWwo5Pk= )
-g.example.com. 3600 IN CNAME www.bogus25.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Yc1t4U4yV0PZkfxAth2PtdqDOZKXJuYmOWuN
- ni6g0REAaCNmuvCbHj+4YkOWKAq9NOEL5oqI
- ALNA+XUeauaTYdibdVWoFbuL3q/oKqMFHvnU
- eaTcM1xi+tCzo2lHvqxkc4Rcn7DjpZjFfR1H
- H4YH4msXP9VPdoMMljFUvLsKwQI= )
-mail.example.com. 3600 IN A 10.0.0.3
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- MiSjUJWxYuMkwoQ2XGzdciruLO2jlKWCzyAK
- BduPRMuIpx+l6cbhFdas59jKfcQGxQ7q/7h/
- JcZS99LijXSRABW/AQDQzHIJkHh3lnhRdxg6
- 7tkJExh1aLHsClLElteICS4cD0Ep7ESfPgkx
- 6a9V/RB/DBGXJufxfKrTgaMJTuw= )
-new-fast-box.example.com. 3600 IN A 172.30.79.13
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- IbRvf4mFyUSm7gzpiDcmaAjasrJKWgJ2aohc
- h9IowzJLiEn2+m3kII1qwC1NgMYuBzqyx5M8
- nf+DYX/Vv4+uc6wVHRQjB+m8YS/7XB5hO8Mk
- 4Wi9D5zk2Pzm/nJqmaVv0z4b6GS8w46Q/V7W
- DG13RKprePL7oN+5fX0wWi/hGZA= )
-ns.example.com. 3600 IN A 10.0.0.2
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- HB4CX3PPLe8XMSUkABN5huUyYJ61q+hk8R6x
- 1OMBMK1g2c6L9OcLY36Jxi1fyk1UDbk7wbIV
- PGObOU98gF3Rz6hYrRLO1R1yDSA0YpkDL9Q2
- fu8qGwoFdKjqE6JJiaYcH86bbEX/xaTPIwr2
- kWnMZSF1F/inw3NWxekU532xycg= )
-o.example.com. 3600 IN CNAME a.e.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- ti7Cw/aVjpeDKuRmEJrQwLOIYZCpt7YWFVn8
- XvChoxuv8OjEdhjtjZm6s5YWT7m6+NWpadZ4
- 2YxjWkbi1JfmPVB8NdR+cLse2cFdr6StTeFn
- 3TZei5zLsjje7XHJ78Ezsm91nJsT7YANBCwV
- bp6exprqVvWSZIjmwzndP/6ldKQ= )
-*.l.example.com. 3600 IN CNAME c.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- N8JgT0V4xI4q2HsOZ996VWSc+RvT9dIlH7zf
- dpvVB9GVYcMo+CC/vz53rLM/WCPkjcYVZxqH
- xyRlAktjY7mMGFy/3ATlgBW/5fUjvCAPe3n+
- WQf/lTO2p75SPgnz4yHzXRWFBgatTk4zxp5/
- 34GoV+sE0rrVgOPKm5IkBp8lN08= )
-old-slow-box.example.com. 3600 IN A 172.30.79.11
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- mRqdT1LUhXB1+jzeRmtlysRlZvQ/wVa3RYez
- 0ED3YAUpbhWPulW3SLiYWdQNSCs2kL1gbix0
- 6z1gIrNUdwA9ndR9vIO4Ji1jeZIqfPtGLL2/
- FI7PhcbjGGUuR/X60G0RxKvboNIDV42zZ34z
- pMJU0U5kx+ibGUKdoTI/ZUIIaMU= )
-*.n.example.com. 3600 IN DNAME bogus25.com.
- 3600 RRSIG DNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- LYfL+QODtn6ImPCadS9DYp3hDWFyooI0Sdug
- kG4ENfOrFco31LlGs98CRsWM2cuIdAbh3a0M
- FOtuRFl0dgvw8SOR7QV5x4S/pI4Xj9OIL4T8
- xsw23Y6gVJ7oPOha7RBHRZFwniJgRyGsZc6L
- 6ZTQzkOY4iGc2QEmV7kVwo0Fwdo= )
-r.example.com. 3600 IN CNAME a.l.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- NLSNK8cAEnGcIBX+oJm9VVVYxzUml/rQjNxH
- pu9L+WROH0z4mgXiC9qaN6jiNHSY68aPxfph
- xdnhfuaPQziKYezh5roXS036IBYdU/GzXyQE
- KDmxBmM8Yevtp9xJs2/BrS5ny+bmoAf/2suv
- kDfKD80tF16036x8JJFMPeyIKtI= )
-ns2.example.com. 3600 IN A 10.0.0.6
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- fijL4QoqM0u9E7eOA+Tjf3RIFGxCNGQp9Sp5
- YTiEcv4vHSNI+4Y6tp93C9C9yeUp8YQ7VW9d
- zagyF/jHKfODDpn6Sm2tcWzCxX2KZTuXGSNz
- i7o16HJj4jRyg+uqdXIrp7ArPjudCc3mzd1K
- LxTv7Zb3KVwWYyt4r1YbARFvvOs= )
-*.s.example.com. 3600 IN CNAME s.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- vfGi8BkLoPlB2ZAORnwG3ZlmhtOtrs/0z3wb
- pY29MTNGNVBHJROXg1L7ANHTBglkbzrKExHz
- +M9c9YmFgtOKqDne00R79KWpC9XB/zsdQPhV
- TRGR2Fc00KY74ZrQZ0by2/xW34MqDPpgbmur
- b+EeKV7UnnwZ9y84HIC3U12wQGk= )
-s.example.com. 3600 IN A 10.1.1.1
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- kpS37lgrK97OEG606nym1tYyovXp97xkG0y6
- rteGws46zMYYrsW9L819ibzRO1DUAjOd4zkO
- BI7hu9CI+Mgrk12wb4vKS/ERIDZkiZ5AadJE
- nodcYYZBNwRMwE+frFgPxORS8rUtmtrkdqXR
- Vjhs3llHqtJbJr1ve/nZvfgX/I8= )
-sub2.example.com. 3600 IN NS ns.sub2.example.com.
-*.sub2.example.com. 3600 IN A 10.2.0.1
-sub3.example.com. 3600 IN NS ns.sub2.example.com.
-sub4.example.com. 3600 IN NS ns.example.com.
-p.example.com. 3600 IN CNAME a.sub.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Cyvn5zf20vG8RHpIZ+oIvPV8nZnG9kROIIpC
- pCXPx8RG0CY0+IhOpUdgGwvcfMkPSE4aMYw1
- 7Dgbykszd0MrCt0Lel9iCF6sroeZNLCuriUl
- 8hiYli602XJCamDB/9INSzvGtfRtiN4QGuRV
- mbeuXLHP8ecv0Ib9GOt32dMTuwk= )
-ns.sub.example.com. 3600 IN A 10.1.0.1
- 3600 RRSIG A 7 4 3600 20120311114108 (
- 20120210114108 60914 example.com.
- YuQAVe8hfw48Ily9RdN8maHLcIUDWKuDgcdd
- W/5T/yBsf1ezILAh2zugDtc86A1HRxjH6jro
- xqBlSkJ4bWSwA4OtaU6krsMODlV19gCXUNvW
- SV/2TkCp0F0qSj88A6ZelUhbnMHTKw22z0K9
- UdkdLB1ohRSw2I9xtSCek0DwLDA= )
-sysadmins-box.example.com. 3600 IN A 172.30.79.12
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- n+Pe+pQjCO8NJZq06uemhm/QuMRtbsuRYnrE
- 85aJ65IGKfFdwn1bFYcW58Gc2HS/+nWE1gIy
- DtvVxz/FZ5PK6acW8aQeji/sPBMvb7XfgXRl
- 458lhlw1hkuxXRguqkKIDk1qL7GCBPHegNUV
- 8xzGJLaxjQ0hMGVLPrPIH1udGwo= )
-www.example.com. 3600 IN CNAME ns.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- NnCpNpsZIV0U2qOsuuj7819OEubIY9XsoH6k
- IY8fFCds7SRckoeGS+bM+LGRbQWJj4RRx4Xs
- geWZB5xF/UXu5OCRSQSx3B2V+u7drfeqya/+
- kpQaECsIxGljej92QHn5ABgJgY6eaWDI+cDO
- KhhUkCoSrsvU7aYQLNmSacf+fPM= )
-0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- hdoNfv4A1PpOTW8EuR5fcwzvYoLT1Q7znxkJ
- +0vEJ6z6nhdCCwUua0IsE0J79vQfy2Nmyofc
- Q2OpLjz2tnvalX9dPX40SYPPV0NTAARs1Lms
- tCueg1uRT8MMrkIRChSAW5aGHL1ObZNVqFuD
- ulvfm+W7/3sHEBXuuAJW1QYaJU0= )
-server.example.com. 3600 IN A 172.30.79.10
- 3600 RRSIG A 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- uEav81+vz3eDo/TkNMaKMf3IpMIsuVg7NV+3
- oN7akjotlRzGkeWT1LHM/tZz2XGG+Tlw3LI7
- +L3h6N0QQMlJJ4d6atOL4CShNWyYC27JNZ7t
- WJLxZNLfZJaRBgmOqWP60g8ZicCerFasxR1o
- +JDf5nNL6FH1KStC0ZuJfMLQVbk= )
-sub5.example.com. 3600 IN CNAME sub3.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Z2PhwJKkA3pgLFRgZCNytK+f6gNX/5sfo/Y6
- 7SYp0VJHbWndhMwX4sxSRjY2F23QKrzo0PdK
- cAHYrzBb8lVSaxdLqDKKGazhLE7sMwNZzTBe
- f3rokNWjz+y+1GP0/WFcVW5WLh2REaR7yR62
- 3QemcT3e2uB5FV/IIIUPCR85zwU= )
-1DN7NM4DOV8TAMT2O42J0T9M8B91CEB9.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- to+Oi5Ls4ea8RiwCikG5CMLG3poJ6EOCn51p
- Fe6c6hY532DNi64z2jBWithM9YxIfAwt3j3Y
- e3gIftTZvsMzP23Cdh11PUnThMX0180E8Vnc
- waYAgLB2rG9HBc+0zrgYjA6s7xOCEEoYbVLW
- mjPFLlpE9iVVtGuPf823SBilzro= )
-wwwtest.example.com. 3600 IN CNAME www.example.com.
- 3600 RRSIG CNAME 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- khglR0/LGoeaAsSYFAf+YXmUAVOzFeE/eY2M
- HuI8HliMuHl1jlo27I88OahsCY7c36+3z3j1
- lIh3G5gpKbPB60KZ/5nWqR0os1ASm863L4Jk
- L+Q5vfxiMeO6yZ2ywUjm7bUEPH6DXo9IoiXC
- I6AedcGz25t1nzutks/gad6dNUg= )
-3LVPU5M9BF6R0F9L1UB36HDOI6SNPA1K.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 572T84KRFBMQUC5O8I2V5BNLNHA8CBQN SRV RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- leFMlSPZk2RQXikgAkH49rf51b1Bdz0PXGrD
- FrIQ3BhVy6AWN36MkD0DppqDk5838a9J2Qo3
- 8MCR85WM061J3lGm8DhwR0az22+Ot2erzO0s
- PL/21G1iaOF1OP3b5EN2jfoZdZ9F1T96dSjW
- 5iA4PbB97IqgzAnFlrOBrWsBJf4= )
-572T84KRFBMQUC5O8I2V5BNLNHA8CBQN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 58KH92475K4K07K5NV8KAHO2UOHLGA5N A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Pr8qo3SOSxkKhW0VW+0Fk4Y/p/NMF/Ys1Rt5
- 2Ux60M/5jbIY6yIAZBeJvBAeWG0a0lO6G/+t
- XL81AV6dX2XVJsgYxEhyBzIiz2Y4gJT2QS1L
- VEW4b26+7MH5JL7dKaKNJx8AUNS6X7xb9RJY
- wzstiifxrHTYNBwoCZPlCmYrFJ8= )
-58KH92475K4K07K5NV8KAHO2UOHLGA5N.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 600RRJ34OTBFOQCRPSG5J4F19RM76IOE A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- TJLCuX3rB9xIBaffuYRAzR1CFkJ6ReAp9AXu
- j4QFsmoo7IfU8stwYscWB/NQUUDR3zA6rych
- KetLhIwHG96GPiI4ERiQ2y1O0cND9j47rnkC
- 2tAy7o9Ou8InmUJuKT6rV0NrVEiXmSaNMxuh
- eLhcIcRmFulkAaCv7yfja91fsSU= )
-9CGLSFKECUFG8QODUCMQPMVH0JP35440.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- KuqCuiNXU84Zv+R7/tFeoc4+n0jybD2v3jFQ
- r7UyHwYkbgJjT4EjCkIywm56DnrZZ0J8Klz5
- dF4/fWaa/uha+q8j9zbNwYFnzUOmX08rAhAA
- CTGyoq6Gq7vBLxh7IyaCTi6phDdGajAywODG
- B08oWuYgyl+BaV6HUMXxjoC8v0E= )
-9OEBI5IG2AOVVIECGRSF2P0DVT6VFJ3V.example.com. 3600 IN NSEC3 1 0 10 AD3302FF AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- nt2Hz0NSjX67Wv9HrpzglnFtDwHB3SE1LiNm
- xZeTx0hKk/4b8DGTB69/YglwCiVzd0h001A5
- 9N0KLQH/cFfV1N6GWcyH382t1e31UtYzVWbm
- o4SXfj+xex9Zgnr6DpuefOCzMNSkrB8hVBR7
- jIVafVPz8H2a+EEnFrf3NII8HTY= )
-6K06BSDDT661B33QPG6F6EB14TIAJ42D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 9CGLSFKECUFG8QODUCMQPMVH0JP35440 A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- lo+UMe/OHfBIQYxkbggwETXfy7FShVTIk51E
- NBHD3TzNvUdjimVammEbkmbMI79Ic3wdnKrj
- sk0IbF5DU4owVTF0Ze2EMikNpWndTIw4F03I
- IbRd6cI38RtKGzxTUd3N+H0Dv+x1HK06TZsp
- ildUHnYomQ3OMzdIuLOO70GGse0= )
-600RRJ34OTBFOQCRPSG5J4F19RM76IOE.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 6K06BSDDT661B33QPG6F6EB14TIAJ42D SRV RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Gx41Q8P2L1LIMqEJ++6DDIwWOIarnKH9+APX
- a0ydl7+BMEa3uYtpEMRN822szoWNro96N1km
- ih6lQesDaVFqkksrnJ+2dnyuCqQFV2FxnLJu
- D6w3KxzXs8HDh4jDUBo2Je7grdNXdiHT5FqY
- xCYcHtvbXqPDUBUVoka0YQYq2DY= )
-AQCNF4KN2I1N0LNG51GONIIGCH7JRLBN.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- pAm1NJoUtgrh1nZZOa+BOLe+sqxBYDRmy43+
- Qsn9/xK+5nFP4uMewpJ399W+lYRXTVHj551W
- SFSaPQViD30s3f/GRhux2Thkc9qUYO4XfQhl
- cFM6ZBo6mjMc7coEeE2i/SA31tYvx1aL402a
- HqdzfPGLGtVvrv1ebZngBva6Wdg= )
-CITG8IDONU692P92JJHS57P0ADNMB59S.example.com. 3600 IN NSEC3 1 0 10 AD3302FF D2S5TIC04S7ORKP09MAEOFV1GN1IQORK A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- FK+huH4wLnBWZ7dtydX3lYj1pB9rP6WS+Nqq
- 3+3y3HlrrVM3dfJ/CdN8VjhrE6J7UWNl0hrG
- nmZix1zLXZUWLusY/hPE6cyKh+yGmjtZit/0
- qJfxPMr9GQLY6pa64kFejhX74Dr5Tch0rvIS
- cCdqrgS1hppQkVC+NuJfXDiWSfc= )
-BMSTOMQ8U0QNBNODBRAAEPTFKDBLGOGS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- FhTgIqqS6DUxaSLZd7RO7uWMi7rJjRfzkcj2
- D0SP4iBPwBmntadfMSbJ7LQhqmF/RSlZJ9e3
- ijiAzMcLQspiFeV/WJAivlNLLG9wESYcSoNH
- GiEhtVbQDmhsCTeywoLWL2Ttf2En4l3SonKr
- EceztaBYd4VSZb9eQ6mRWdF+nwA= )
-BUKTJEVN7M7HJ26RT7O3EEK96L94VGVV.example.com. 3600 IN NSEC3 1 0 10 AD3302FF CITG8IDONU692P92JJHS57P0ADNMB59S A NS SOA MX RRSIG DNSKEY NSEC3PARAM
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- k7y2B2ZDxLVV/dGu52n2kaHU42UiLExA2RWe
- pC8DuqezyFotFMwAxRT7jozgzLAYuWV6hnR4
- 4eZQ2IIoqKUTXpnNh7p+xidNACwEGY1ZD4Fb
- SjVbhKKRc9HQzVcBoKsS91OmJnH3Wxl/Zr1v
- fkyAORJESGw0TMVHKYiE38HKuZo= )
-E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EAO0AESHP4M49Q5F332G7SOK1JH53NT4 NS
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- eeYNlR+7RF/WnR2Xfpi5BrwYmJsMKVtVGXBe
- 3NzeQrZcqdDwnXwhwmpYZSYoBnQ46XrniGdx
- BTIRHEqkj55uQxQ+xRCK+P/B7Q2VZWsiSsq5
- UAJSnCuErfJze6tRe3xTw7Jk27HBQD//nG8o
- ZH9xoMdkzC9H9y8QiMJabDAG6Pk= )
-DV0IMRDKSGUBTBMM94HHURG2QOPJS33D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF E7P2NFQQEAFD7JGEK6TDOE99B16J6KCI SRV RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- rEfdvZaXj4lmZJWz+o4ZOotWHlYbjFhoXUCk
- JsRilkouAzzZkq6XDgTWW+n6KAHfB2t9mjex
- UH7JK6/AQrSF9SolAzPZorVMVPFnoT1gQnQM
- sklwqGHkwhHO+ZFumXGPjsKKDwsxfGSnchyh
- 5X+jNJbtkEG45Pz0vcAgJVL7zDU= )
-D2S5TIC04S7ORKP09MAEOFV1GN1IQORK.example.com. 3600 IN NSEC3 1 0 10 AD3302FF DSSTL51IUQBKDPULIFJHGJP40C3NK2EA CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- SfsbWl8rpuCStr+LeCdKGL/2PDVI4XmqWbo/
- WvEMXcidKxw3S+MIPctFRMBQfMxaiidpjdF6
- MxTPJkQIIkuHxz0m0KCHxjkzQCGq4E9aSINJ
- 58XBq9Lvq2891pymq18FogRpYaDnZUQDoezk
- qaDLBJIQ7+j+wmD+gRxrIp9Co/I= )
-DSSTL51IUQBKDPULIFJHGJP40C3NK2EA.example.com. 3600 IN NSEC3 1 0 10 AD3302FF DV0IMRDKSGUBTBMM94HHURG2QOPJS33D CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Ip7RkE1QMBk6TVbD7BckwtJpEM/bZR7CdCh2
- mYwDCH/VvE/4SHxu8ZaKZUxxe5jo4fdgbUml
- tlwraOROKEY1pO3eD/x1xu5GI1NcB31Cq3Oh
- 9anWbEglye9wYr2AqqWZ6/Dvf+P1gTYbEK9+
- V9Fj1xm9vnHubnEwsCOfKDdXZ/I= )
-G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GC9S3VD2NHESSRL256KS0805PL0KAI2T DNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- cfmuSLlgtjXs7nlbqAXXSXa6A/yR6txfYWxS
- MLx4KkI2La949SiV4GlcqypKlZ5EL32xdqk3
- 8qDMhBBpzxSSmrsQRi4XiAG8f0/lGEBVSy+D
- 0PlXeZHuCOfND8DtxsIttkxHOEop7vj7GuTA
- 1V7I6TKxdFDPYaOtp/iz8wrCIOQ= )
-GC9S3VD2NHESSRL256KS0805PL0KAI2T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GGR966KJ5J300229Q7154AMB4EVVLLMG A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- uMUt9rYgxn4+VutPJ2B2in3lt8QmiV+cUwE5
- TryjJsqFyWeKbhZpmh5fVbQLLZAjMAuQfQtY
- CJb1gMeO7CIxlk4uLcjZSsMdDcKtwstU41T+
- 9b4rHh42mgQBo7LrRXP8NUtXOZyvqge3AHmV
- FKSJdhvmQdtLKgJUXRWPJQk2kIA= )
-EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I.example.com. 3600 IN NSEC3 1 0 10 AD3302FF G8QQP950BTQH4E0JDQTK2RCT5MI6A7B8 CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- B937ph6NFfdD4bBEBEK4NVup+k7C4+vDKZVF
- Wy9tzJAEqjoFTWqxrrfs1pmpxsvB4LzawVXm
- XIxjqBuve6tNOk/LWjjrMigtx0gdJ8m3fCiU
- Uk7t7xiDy5AgS8vkzYiQSr4EXb00v3dcSlUQ
- nqjabZhgTx58KhbqF3O4c/oViY8= )
-EAO0AESHP4M49Q5F332G7SOK1JH53NT4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF EM46BUMIU4I93E5FQSDJSIO6TG9OJ35I
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- rN/OU0sPJ9P28hEhDUlvMvPnQSBbyRwnMN3h
- YipF2VX2r7Ij3qdD0k3PKx/Emzsbl+ImbGNm
- mfhDQ0O72m6sT664Q8yO32Pve8i/fxQIVKTF
- HalkrM2xonf7Bg+wzI4CnQHmWD8hcq4L7Mj1
- bFI0H+PRWz75h0BB4hJYIs6sCuQ= )
-GGR966KJ5J300229Q7154AMB4EVVLLMG.example.com. 3600 IN NSEC3 1 0 10 AD3302FF GJRT9TI4T3VSP9D26OC04EQ88SOFVRON A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- Bg8bWWuR/Gw8xKCrFjEHQRBhbBPKu0AL2DGT
- QChgHqSaAj7hcaMHLStaCH7NRy/EQL07ryU1
- Xh7EPFZn191xKJPrwFq2bIsgpYYoQ5Knwt1w
- P3EdQEV6jANOx0k9IHsXC+9oGbMipe0iGYV1
- 4XG295g5Kk47sfEcl9leOgH9xNQ= )
-H01743IKEGI4JJOMSNCP0VG5S6IPGPIF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- SS6rDyoEGhD/SkKu87gA4GNlKoAxyXnfVZ7K
- iEdXMSrSdAu1dkHWCNqHvGuws9VDjwdZ2VKM
- R0H09jMFs9Uur2u2A8RYv9RTwk3i2VKY9TPW
- V5cp35ukOK2zQWWM8hSxIjIudiMhSdp/dluU
- hGGMxb/Vl6TWMBff961lBqmQe0k= )
-IV7VKFB1OLT6DRIGHT0U4O0L6PU6KMBC.example.com. 3600 IN NSEC3 1 0 10 AD3302FF J7A75JJN87L9PTVO6HBKH8IPI78IPUO4 A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- BsmFOWVyvp6T+lYJq9iI7N72LFces0lgUzgE
- mi5hgj5j+/ak7Jbh5HMA9clnA4x2gVIbl4tB
- n64PqfOoDeotG3KUS40aJMLtD5kLQ2lS8Jje
- nj5ZGTvkkyDq03nzuCbO4WTVGs3Lv8nuKhPL
- 0JchxWeMS4yya/7ZDAexOcaas5k= )
-GJRT9TI4T3VSP9D26OC04EQ88SOFVRON.example.com. 3600 IN NSEC3 1 0 10 AD3302FF H01743IKEGI4JJOMSNCP0VG5S6IPGPIF CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- atmcjXLJAop3xdnjTYTLDu1ooa/VrFPISBAl
- 3yvMJmOBEtxO9I+wQUkSv59nDC59my/Pfye0
- +tEo8iUanThfoNFZehA7HAl+scL7eiizyzpV
- iemaGcqA8blGZmvGegBfgnHClw/s+J0lyxPO
- +R6C1Ht53+5RL5havJgeiyDhrF0= )
-J7A75JJN87L9PTVO6HBKH8IPI78IPUO4.example.com. 3600 IN NSEC3 1 0 10 AD3302FF KI1L4Q2S3IFEG634FE6DN6E3FGEGV956 A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- nejtB8Eb1URet62fXj1vdJ3FNJ+yIBFF5Kiw
- 0trO8jpxEXZbop3Ls55eMRBO4uyxnXAQzOqd
- iawmpOXkuhJkUC5dHg//l4bu7NnD1Delyfv0
- t7VXAFjH8sV82HNsk/g8ngn4gekexXZU3QTJ
- GcpAIGxpza48oI9qYf1jU7SOGuE= )
-KI1L4Q2S3IFEG634FE6DN6E3FGEGV956.example.com. 3600 IN NSEC3 1 0 10 AD3302FF LMQIHH5MDDR9PTGEHOHA5ND49685RR01 DNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- eoSPJ3B1MdvFBppmzqQ6+VY3ojgFuJdAqLIZ
- Rac7CTMKqOILvQVEwwV9rU+vX3WpkiJ+RaiZ
- +TUICV13KE3PJW6sEar7VenLHJyBLb9L2gRO
- CaVf8IZy/PKwS1zdrasidKW2URRFhJdVcnuu
- kdwRXfEmZYA4qEafclF+PDj49v0= )
-OIKQOJ12077E6HOP6HHST9DHAMGPED5T.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OTMDSI120AJGM768VIKPLND04FDSUQSJ CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- H8h+djCAspCVBuSd5QyWe1Z3rIQcRJSCYtky
- XRqfUN4gkcrMFEduIM5Ic5AJD25AxM2CnTBL
- yVOGlcEJdpMivzZwJF+5mavO3hJ36LFEZkay
- hmqUx39zqNC60a6bHDK9QTkvouQ5EuM26nMf
- 9o6HytksqjvsYxkBJCJfR7oiTok= )
-MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO.example.com. 3600 IN NSEC3 1 0 10 AD3302FF OIKQOJ12077E6HOP6HHST9DHAMGPED5T
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- ZLiscKNOltWTqqwxDvjZmwTqhqAfjiDA68le
- vmvY4mYzoPEHASd19gEhddNvR+KK/JVGYvEr
- hB2jpgOSZCs1wsW90UpL0boenluMPppLFDUD
- xLUD2jvzA9a6lBjl55jzUr6mLyyr2hHIPmk0
- CmrSFITGT6qEzEWq/CLA6TvtBsY= )
-LMQIHH5MDDR9PTGEHOHA5ND49685RR01.example.com. 3600 IN NSEC3 1 0 10 AD3302FF MEVBVIJUVOB0D9J7BQ6AONI153T8P6EO CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- da0fy8qWaZtO26BoIvbr56jBrrucndmMJ/0h
- /Y5BE2ib8X65KVjkNVt5Mg5YKpTvaeOZN6CQ
- Dls5bxnUkqmu0kgaUjIB/rhiMhpPqkKF7dSP
- SI85zqJXIgCInMsgfTiBp5uZwrBKtse89LwH
- y6BC682kK/uX7ikjG4+BapL6ivQ= )
-OTMDSI120AJGM768VIKPLND04FDSUQSJ.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- jWagz+ntj/MtfWB6xUJlkfihEkwrj84g1CbX
- F6yKKVk4WToETt2ApHMHd8tn4wbHYLfojavI
- TbsIVBfWxyMFsCshMoBASML7T8I9X3jjEYKS
- W877XhA2yxuFcMaTjh3jDm7wfLHIvEgqhanr
- 6JO2qGWTKSlNWK+bYg4y89YJOOA= )
-PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PO8BSJPMDN4514A8JA8QNK1C79EJIF7E NS
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- qA/sA5sV/eRmtgb+HBzbENLI2jy7xEkiDd4H
- d/REG2hCp3rlIlo1FK2y7q1sZDr3sZ0/5vrQ
- jxOHpZx+akeHi7hT3R1KhQLFb/+veEOBXNVG
- HMtB3+Uc7Ttq1bGdVQIDhrVpNVhKS44nEG6O
- UwOKgK7aT2q2mnUA3c6foWI0sM8= )
-P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PFRQA6T0EUQ6MUU9LPM9M3GP8GQ1CQ1G A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- VoYUgMVgFe4QXN5ggAzleOYWGKatee//AXnv
- CeFRHn4lKcGKWGRxbaMaHHGkTX+UjN2DnGcD
- nCU/LQo15nKk8m8EYoUYywaHYiZ+aJ5eoagB
- hka9G8YRM4goHxyKr4asFtfjHcfGdW82y3kv
- BJYH/MN82GAhMfsdCA9z9zp88zo= )
-PO8BSJPMDN4514A8JA8QNK1C79EJIF7E.example.com. 3600 IN NSEC3 1 0 10 AD3302FF PSMSPPC19D8OAICCQ64C7MQ387MTVGC1 A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- QtJhRcGQl3Fi9tGK6xD0Dr5s740QqsOhvaJN
- ofLjQVTa4zDEoC6txlgTO4czRl7KPFWa8T48
- W+jCqEysIamuUMmUOypCj7Airg4lDdS2VBUJ
- BC2npTHBKnx+J1h8p58p0KDhozYoMNtYUUFF
- gBp99sWEsORnDxyiW+KFFTTW0xU= )
-P3RBJILTM87MQELBIM9TNBJ4ETMSH0PA.example.com. 3600 IN NSEC3 1 0 10 AD3302FF P98NSUFJ2IPUSG2OOPH9CPGHBNC9RRR7 CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- sBdCg4Y3vGxry/Z1zV/Xg6bdpYjKiTXTSDm8
- 9D1WZ8WAW5vbSJHxTnXq4IxwAJr2fpI4fUiT
- cAS0uFqd+Ft8XpSQjaNPGuwzS08DCLn++Hrm
- lbCngUeApxrgCfxo+cf4ibRPfef3UPcUxDOD
- meqoGFw51+5DpB1Ygf5+yEPhAX0= )
-PSMSPPC19D8OAICCQ64C7MQ387MTVGC1.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RQK67K3ON1JGJ60JNO4883D1JVIOIG2D
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- DMO3YD4aOFqjkxmw+SDajMoQ+3TylCrk6yyr
- ZQiV7yrfP5SIwY40EKCVG+6d0jSNQd7LrbJz
- uyXiGpGEpKRTmAJZYSrpiPyfbbfw1XrOW9BX
- 7qVZCvK8iZrkaNT6yQ4W/Q4gwSIyRpUqE1j1
- 2SgEv934CIWBew/cjGfVzdIMHCo= )
-RQK67K3ON1JGJ60JNO4883D1JVIOIG2D.example.com. 3600 IN NSEC3 1 0 10 AD3302FF RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- fVTi0gRo2WwgEu51Fx1iH5Ke8eh8m8l94luf
- yx5K6gCqywv9Sbk7YhyKmW5/94r0VwyNqgPS
- 5DF6+RXBlM/t+35g+K04eBortmy89dbzFSZD
- YPqfk2Q7v98jMnB0OzLoqGg5LqxTBPHftKm4
- O0tsGJ7AC8bto6+iBEOEjX3ky54= )
-SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS.example.com. 3600 IN NSEC3 1 0 10 AD3302FF UB8IU759M5EE63CQBISIRM9C0V2RU1RT CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- ASL7wTfcNyORVN8g+BjK3CSP5NXsWoqF9imO
- E93NzOn4EvgOI1K7jDZ+urgCaaaw3rqt/yUS
- 4/nU7wHUDjuNsvP9B+lWm93l8I1n9nhkOy5D
- J17XjWE+8AqBidwX7O5clx+yAMSCnL7X4Rp5
- luSPK6oZeRX2A5wSHbrvHeQkI78= )
-UB8IU759M5EE63CQBISIRM9C0V2RU1RT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF URIDB302IVQCE7DQSKELLE9LEFOHV0LT A RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- uZPu1mukjnAj+p7IKGe5tQV4yMBEytV4ab5W
- nWNZeChWwQfooNwaOK+ZBkFvWs/bxyKtwL7b
- 24xAbU+4+TzD5Ier9xNYDNfLXUkJ9hKuBrvg
- RDYN8W/rRN++aL4xR0o/jOwzVnkww/VtIkvK
- 7FPE0F2YpEw16H/ZIWnL6htRb5w= )
-RSSD7AU1NQEBI2UF3B58G8JKBD0CDURF.example.com. 3600 IN NSEC3 1 0 10 AD3302FF S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- sIaGgFypdpWWLFqcWGI0PzitwaIZI6irA8uw
- Y/E4etgI+l5aKbHPeum0+qzktYWc/wFxte44
- 0T3dRujlVbMOhDAhE3QJFjZWEZo8ZZH7ARxC
- bn5pTkzmKjWqKjKhol2U0Y7ve74oJpi5H5o5
- D7nqiEmr1Ou8xkqbK281PGSti+s= )
-S4A8QO8DEA53D05JQA0RE3H3R6UC7V1G.example.com. 3600 IN NSEC3 1 0 10 AD3302FF SH86DKIJAGTUEUO2F2PPQ0RJEFJCKGKS NS
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- bDbE5EuKlVnpyavKronRh+FiK5wB0Ecw+ubc
- HiVRrQfJvnayxRVOiE0OvUrK0n0FyQwuXk6w
- /EysxVkcDK8wwX3SsXW71qEE1qG6GmFHUUOJ
- gksxkjkVTMug0Xnmm+UGO9va5VhekMJLiNzF
- Nl+vhTphDLLTgql8pyoA44PDARM= )
-URIDB302IVQCE7DQSKELLE9LEFOHV0LT.example.com. 3600 IN NSEC3 1 0 10 AD3302FF V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- JuCoPMHnJZXXo+/2ACPorEF6zHtGylp4ybXe
- eN2VC5jmj7NMj+8EFkHa2hRoy2yL4hA5+dOo
- PDzaQtHJ9wO2gYgU9qz2eGNRfFM655ig4Uq+
- yfpQjUq5hAyuxTehlhH51jElOo1B9rC+qpbY
- eQIfqyK318Xp7JswLblUn8IHzUE= )
-V34U1QKHVIL4EOR63PIVLI0NBDMAQLL0.example.com. 3600 IN NSEC3 1 0 10 AD3302FF 0R5AV1LGTS4HLPNB8UK2DTLCSO65OBJ7 CNAME RRSIG
- 3600 RRSIG NSEC3 7 3 3600 20120311114108 (
- 20120210114108 60914 example.com.
- q5cTrHk3CXT3nACoB0sexMUuit+ze5mj+PX3
- Xvv9XPMm30q9CGdVYQG9N5f4TiYiQJU6Lf99
- Pt7t+zWhB/YVfFrcCB3k5zWA/QfmwQYLrEyK
- QiTxMEGvRU5QhbXwdiltAjQIpiO/fqa9wwr3
- l9/TaVniVaOM0XXV2A8xzNUHuYM= )
diff --git a/samples/knot.full.conf b/samples/knot.full.conf
index 705c965..3628978 100644
--- a/samples/knot.full.conf
+++ b/samples/knot.full.conf
@@ -7,31 +7,35 @@
# This is a comment.
#
-# There are 5 main sections of this config file:
-# system, zones, interfaces, control and log
+# There are 7 main sections of this config file:
+# system, interfaces, remotes, groups, zones, control and log
#
# Section 'system' contains general options for the server
system {
- # Identity of the server (see RFC 4892). Not used yet.
+ # Identity of the server (see RFC 4892).
identity "I have no mouth and must scream";
- # Version of the server (see RFC 4892). Not used yet.
- version "1.2";
+ # Version of the server (see RFC 4892).
+ version "1.3";
- # Server identifier
+ # Host name of the server (see RFC 4892).
+ hostname "myserver0.ns.example.com";
+
+ # Server identifier
# Use string format "text"
# Or hexstring 0x01ab00
nsid "myserver0";
# Working directory of the server
# Used to store compiled zones and PID file
- storage "/tmp/knot-sample";
+ # default: ${sharedstatedir}/knot, configured with --with-storage
+ storage "/var/lib/knot";
- # Custom pidfile path
- # default: pidfile is created in 'storage'.
- pidfile "/tmp/knot.pid";
+ # Directory for storing run-time data
+ # default: ${localstatedir}/run/knot, configured with --with-rundir
+ rundir "/var/run/knot";
# Number of workers per interface
# This option is used to force number of threads used per interface
@@ -61,56 +65,68 @@ system {
# Default: 10s
max-conn-reply 10s;
+ # Number of parallel transfers
+ # This number also includes pending SOA queries
+ # Minimal value is number of CPUs
+ # Default: 10
+ transfers 10;
+
# Rate limit
# in queries / second
# Default: off (=0)
rate-limit 0;
-
+
# Rate limit bucket size
# Number of hashtable buckets, set to reasonable value as default.
# We chose a reasonably large prime number as it's used for hashtable size,
# it is recommended to do so as well due to better distribution.
- # Rule of thumb is to set it to about 1.2 * (maximum_qps)
+ # Rule of thumb is to set it to about 1.2 * (maximum_qps)
# Memory cost is approx. 32B per bucket
- # Default: 393241
+ # Default: 393241
rate-limit-size 393241;
- # Rate limit SLIP
+ # Rate limit SLIP
# Each Nth blocked response will be sent as truncated, this is a way to allow
- # legitimate requests to get a chance to reconnect using TCP
+ # legitimate requests to get a chance to reconnect using TCP
# Default: 2
rate-limit-slip 2;
}
-# Section 'keys' contains list of TSIG keys
-keys {
+# Includes can be placed anywhere at any level in the configuration file. The
+# file name can be relative to current file or absolute.
+#
+# This include includes keys which are commented out in next section.
+include "knot.keys.conf";
- # TSIG key
- #
- # format: name key-type "<key>";
- # where key-type may be one of the following:
- # hmac-md5
- # hmac-sha1
- # hmac-sha224
- # hmac-sha256
- # hmac-sha384
- # hmac-sha512
- # and <key> is the private key
- key0.server0 hmac-md5 "Wg==";
-
- # TSIG key for zone
- key0.example.com hmac-md5 "==gW";
-}
+# Section 'keys' contains list of TSIG keys
+#keys {
+#
+# # TSIG key
+# #
+# # format: name key-type "<key>";
+# # where key-type may be one of the following:
+# # hmac-md5
+# # hmac-sha1
+# # hmac-sha224
+# # hmac-sha256
+# # hmac-sha384
+# # hmac-sha512
+# # and <key> is the private key
+# key0.server0 hmac-md5 "Wg==";
+#
+# # TSIG key for zone
+# key0.example.com hmac-md5 "==gW";
+#}
# Section 'interfaces' contains definitions of listening interfaces.
interfaces {
# Interface entry
- #
+ #
# Format 1: <name> { address <address>; [port <port>;] }
ipv4 { # <name> is an arbitrary symbolic name
address 127.0.0.1; # <address> may be ither IPv4 or IPv6 address
- port 53531; # port is required for XFR/IN and NOTIFY/OUT
+ port 53531; # port is required for XFR/IN and NOTIFY/OUT
}
# Format 2: <name> { address <address>@<port>; }
@@ -150,21 +166,35 @@ remotes {
server1 {
address 127.0.0.1@53001;
}
+
+ admin-alice {
+ address 192.168.100.1;
+ }
+
+ admin-bob {
+ address 192.168.100.2;
+ }
+}
+
+groups {
+ admins { admin-alice, admin-bob }
}
# Section 'control' specifies on which interface to listen for RC commands
control {
# Specifies interface, syntax is exactly the same as in 'interfaces' section
- # Note: as of now, it is possible replay commands in a short time frame
- # with MitM type attacks, so you should keep the interface on localnet.
- # Default port is: 5553
- listen-on { address 127.0.0.1@5553; }
-
+ # Default: $(run_dir)/knot.sock
+ listen-on "knot.sock";
+
+ # As an alternative, you can use an IPv4/v6 address and port
+ # listen-on { address 127.0.0.1@5533; }
+
# Specifies ACL list for remote control
# Same syntax as for ACLs in zones
- # List of remotes delimited by comma
- allow server0;
+ # List of remotes or groups delimited by comma
+ # Notice: keep in mind that ACLs bear no effect with UNIX sockets
+ # allow server0, admins;
}
# Section 'zones' contains information about zones to be served.
@@ -182,7 +212,7 @@ zones {
# Possible values: on|off
# Default value: off
semantic-checks off;
-
+
# Disable ANY type queries for authoritative answers (if 'on')
# Possible values: on|off
# Default value: off
@@ -220,7 +250,7 @@ zones {
# it is considered relative to the current directory from which the server
# was started.
file "samples/example.com.zone";
-
+
# Build differences from zone file changes
# Possible values: on|off
# Default value: off
@@ -253,34 +283,34 @@ zones {
# f.e. 1s = 1 second, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
zonefile-sync 1h;
- # XFR master server
+ # XFR master server
xfr-in server0;
# ACL list of XFR slaves
xfr-out server0, server1;
- # ACL list of servers allowed to send NOTIFY queries
+ # ACL list of servers allowed to send NOTIFY queries
notify-in server0;
- # List of servers to send NOTIFY to
+ # List of servers to send NOTIFY to
notify-out server0, server1;
# List of servers to allow UPDATE queries
- update-in server0;
+ update-in server0, admins;
}
}
# Section 'log' configures logging of server messages.
#
-# Logging recognizes 3 symbolic names of log devices:
+# Logging recognizes 3 symbolic names of log devices:
# stdout - Standard output
# stderr - Standard error output
# syslog - Syslog
-#
+#
# In addition, arbitrary number of log files may be specified (see below).
#
# Log messages are characterized by severity and category.
-# Supported severities:
+# Supported severities:
# debug - Debug messages. Must be turned on at compile time.
# info - Informational messages.
# notice - Notices and hints.
@@ -299,8 +329,8 @@ zones {
# any - All categories
#
# More severities (separated by commas) may be listed for each category.
-# All applicable severities must be listed.
-# (I.e. specifying 'error' severity does mean: 'log error messages',
+# All applicable severities must be listed.
+# (I.e. specifying 'error' severity does mean: 'log error messages',
# and NOT 'log all messages of severity error and above'.)
#
# Default settings (in case there are no entries in 'log' section or the section
@@ -312,14 +342,14 @@ log {
# Log entry
#
- # Format 1:
- # <log> {
- # <category1> <severity1> [, <severity2> ...];
+ # Format 1:
+ # <log> {
+ # <category1> <severity1> [, <severity2> ...];
# <category2> <severity1> [, <severity2> ...];
# ...
- # }
+ # }
syslog { # <log> is a symbolic name of a log device (see above)
- # log errors of any category
+ # log errors of any category
any error; # for <category> and <severity> see above
# log also warnings and notices from category 'zone'
zone warning, notice;
diff --git a/samples/knot.keys.conf b/samples/knot.keys.conf
new file mode 100644
index 0000000..5911a08
--- /dev/null
+++ b/samples/knot.keys.conf
@@ -0,0 +1,10 @@
+#
+# knot.keys.conf
+#
+# This is a sample configuration file which is included from 'knot.full.conf'.
+#
+
+keys {
+ key0.server0 hmac-md5 "Wg==";
+ key0.example.com hmac-md5 "==gW";
+}
diff --git a/samples/knot.min.conf b/samples/knot.min.conf
deleted file mode 100644
index 6b7c1af..0000000
--- a/samples/knot.min.conf
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# knot.min.conf
-#
-# This is a sample of a minimal configuration file for Knot DNS.
-#
-# For exhaustive list of all options see samples/knot.full.conf
-# in the source directory or refer to user manual.
-#
-
-system {
- identity "Knot DNS minimal configuration";
- storage "/tmp/knot-minimal";
-}
-
-interfaces {
- ipv4 { address 127.0.0.1@53533; }
-}
-
-zones {
- example.com {
- file "samples/example.com.zone";
- }
-}
-
-log {
- stdout { any info, notice; }
- stderr { any debug, warning, error; }
- syslog {}
- file "/tmp/knot-minimal/knotd.log" { any all; }
-}
diff --git a/samples/knot.sample.conf.in b/samples/knot.sample.conf.in
index 09da2a8..5ef43bc 100644
--- a/samples/knot.sample.conf.in
+++ b/samples/knot.sample.conf.in
@@ -1,10 +1,16 @@
+#
+# This is a sample of a minimal configuration file for Knot DNS.
+#
+# For exhaustive list of all options see samples/knot.full.conf
+# in the source directory or refer to user manual.
+#
+
system {
identity "@package@ @version@";
- storage "@localstatedir@/@package@";
}
interfaces {
- my-iface { address 127.0.0.1@5353; }
+ my-iface { address 127.0.0.1@53533; }
}
zones {
diff --git a/scripts/parse_dump.py b/scripts/parse_dump.py
deleted file mode 100755
index d9cc44b..0000000
--- a/scripts/parse_dump.py
+++ /dev/null
@@ -1,145 +0,0 @@
-#!/usr/bin/python
-from scapy.all import *
-from binascii import *
-import base64
-import sys
-import dns.rdata
-import dns.rrset
-from struct import *
-
-fr = open(sys.argv[1] + ".raw_data", 'wb')
-fp = open(sys.argv[1] + ".parsed_data", 'wb')
-
-def chop_and_write_rr_query(rr):
- name = dns.name.from_text(rr.qname)
-# print rr.qname
-
- wire = name.to_wire()
- fp.write(pack('B', len(wire)))
-# print len(wire)
- fp.write(wire)
- fp.write(pack('H', rr.qtype))
- fp.write(pack('H', rr.qclass))
-
-def chop_and_write_rr_response(rr):
- name = dns.name.from_text(rr.rrname)
-# print rr.rrname
-
- wire = name.to_wire()
- fp.write(pack('B', len(wire)))
- fp.write(wire)
- fp.write(pack('H', rr.type))
- fp.write(pack('H', rr.rclass))
- fp.write(pack('L', rr.ttl))
-
- try:
- rdata = dns.rdata.from_wire(rr.rclass, rr.type, rr.rdata, 0, len(rr.rdata))
- fp.write(pack('H', len(rr.rdata)))
-# print "type ", rr.type, "length ", len(rr.rdata)
-# OPT has length 0 - it should have no rdata
- rdata.to_wire(fp)
- except:
-
- try:
-# if rr.rdata[0] != '\#':
- rdata = dns.rdata.from_text(rr.rclass, rr.type, rr.rdata)
- try:
- fp.write(pack('H', len(rdata)))
- except:
- # no length - no way to know wire length
- try:
-# print "unknown length for type", rr.type
-# if rr.type == 2:
-# fp.seek(1, 1)
-# old = fp.tell()
-# rdata.to_wire(fp)
-# size = fp.tell() - old
-# fp.seek(-(size + 1), 1)
-# fp.write(pack('B', size))
-# fp.seek(0, 2)
-# else:
- rdata.to_wire(fp)
- except Exception as e:
- print 'Error, exiting: ', e
- sys.exit(-1)
- except Exception as e:
- print 'Error,', e
- print 'could not parse rdata type: ', rr.type
- print 'dumping directly (hopefully it is SOA)'
-# i need to do some kind of rollback here...
- fp.write(pack('H', len(rr.rdata)))
- fp.write(rr.rdata)
-
-
- if rr.type == 50:
- f = open('nsec3debug', 'wb')
- rdata.to_wire(f)
- f.close()
-
-def chop_and_write_section_response(section):
- if section == None:
- return
- i = 0
- rr = section.getlayer(i);
- while rr != None:
- chop_and_write_rr_response(rr)
- i += 1
- rr = section.getlayer(i)
-
-def chop_and_write_section_query(section):
- if section == None:
- return
- i = 0
- rr = section.getlayer(i);
- while rr != None:
- chop_and_write_rr_query(rr)
- i += 1
- rr = section.getlayer(i)
-
-def chop_and_write_packet(packet):
- fp.write(pack('H', packet.id))
-# fp.write(pack('H', packet.qr))
-# fp.write(pack('H', packet.opcode))
-# fp.write(pack('H', packet.aa)) #TODO these are not uint16_t
-# fp.write(pack('H', packet.rcode))
- fp.write(pack('H', packet.qdcount))
- fp.write(pack('H', packet.ancount))
- fp.write(pack('H', packet.nscount))
- fp.write(pack('H', packet.arcount))
-
-#write query flag
- fp.write(pack('H', packet.qr))
-
- chop_and_write_section_query(packet.qd)
- chop_and_write_section_response(packet.an)
- chop_and_write_section_response(packet.ns)
- chop_and_write_section_response(packet.ar)
-
-packets = rdpcap(sys.argv[1])
-
-total_length = len(packets)
-
-fr.write(pack('L', total_length))
-fp.write(pack('L', total_length))
-
-for packet in packets:
- try:
- data = a2b_hex(str(packet['DNS']).encode('hex'))
- fr.write(pack('H', packet.qr))
- fr.write(pack('H', len(data)))
- fr.write(data)
- chop_and_write_packet(packet['DNS'])
- except IndexError:
- print 'non-DNS packet'
- total_length -= 1
-
-fr.seek(0)
-fp.seek(0)
-
-fr.write(pack('L', total_length))
-fp.write(pack('L', total_length))
-
-print 'written ', total_length, 'packets'
-
-fr.close()
-fp.close()
diff --git a/scripts/pcap2dnsp.py b/scripts/pcap2dnsp.py
deleted file mode 100755
index 305f8bb..0000000
--- a/scripts/pcap2dnsp.py
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/python
-from scapy.all import *
-import sys
-
-nstypes = { 0:"ANY", 255:"ALL",1:"A", 2:"NS", 3:"MD", 4:"MD", 5:"CNAME", 6:"SOA", 7: "MB", 8:"MG", 9:"MR",10:"NULL",11:"WKS",12:"PTR",13:"HINFO",14:"MINFO",15:"MX",16:"TXT", 17:"RP",18:"AFSDB",28:"AAAA", 33:"SRV",38:"A6",39:"DNAME"}
-
-a=rdpcap(sys.argv[1]);
-
-f=open(sys.argv[2], 'w');
-
-for i in a:
- try:
- f.write(i[3].qname+' '+nstypes[i[3].qtype]+'\n')
- except:
- continue
-
-f.close()
diff --git a/scripts/urcu-tls-compat.patch b/scripts/urcu-tls-compat.patch
deleted file mode 100644
index cd5ff25..0000000
--- a/scripts/urcu-tls-compat.patch
+++ /dev/null
@@ -1,1495 +0,0 @@
-From 998d005870782ed52ba0fe66a99589dc8b7eb20e Mon Sep 17 00:00:00 2001
-From: Marek Vavrusa <marek@vavrusa.com>
-Date: Mon, 30 Jan 2012 16:40:12 +0100
-Subject: [PATCH] Compatibility for compilers without TLS support.
-
-If TLS is detected on configure, it is used as before.
-If not, it is emulated using pthread_setspecific()/pthread_getspecific()
-and set of macros.
-
-For usage info, see urcu/tls-compat.h
----
- .gitignore | 1 -
- configure.ac | 3 +
- m4/ax_tls.m4 | 76 ++++++++++++++++++++++++++++++++
- tests/test_mutex.c | 8 +++-
- tests/test_perthreadlock.c | 8 +++-
- tests/test_rwlock.c | 8 +++-
- tests/test_urcu.c | 8 +++-
- tests/test_urcu_assign.c | 8 +++-
- tests/test_urcu_bp.c | 8 +++-
- tests/test_urcu_defer.c | 8 +++-
- tests/test_urcu_gc.c | 8 +++-
- tests/test_urcu_lfq.c | 14 ++++--
- tests/test_urcu_lfs.c | 14 ++++--
- tests/test_urcu_qsbr.c | 8 +++-
- tests/test_urcu_qsbr_gc.c | 8 +++-
- tests/test_urcu_wfq.c | 14 ++++--
- tests/test_urcu_wfs.c | 14 ++++--
- urcu-bp.c | 10 +++--
- urcu-call-rcu-impl.h | 26 +++++++++++-
- urcu-defer-impl.h | 49 +++++++++++---------
- urcu-qsbr.c | 18 ++++---
- urcu.c | 22 +++++----
- urcu/map/urcu-bp.h | 2 +
- urcu/map/urcu-qsbr.h | 2 +
- urcu/map/urcu.h | 4 ++
- urcu/static/urcu-bp.h | 18 +++++---
- urcu/static/urcu-qsbr.h | 22 ++++++----
- urcu/static/urcu.h | 21 ++++++---
- urcu/tls-compat.h | 104 ++++++++++++++++++++++++++++++++++++++++++++
- 29 files changed, 408 insertions(+), 106 deletions(-)
- create mode 100644 m4/ax_tls.m4
- create mode 100644 urcu/tls-compat.h
-
-diff --git a/.gitignore b/.gitignore
-index 6eeb2a1..7af5609 100644
---- a/.gitignore
-+++ b/.gitignore
-@@ -71,7 +71,6 @@ tests/*.log
- .libs/
- Makefile.in
- Makefile
--*.m4
- *.la
- *.bz2
- *.o
-diff --git a/configure.ac b/configure.ac
-index 5a90008..1953a8a 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -14,6 +14,9 @@ AC_CANONICAL_HOST
- AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip])
- m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-
-+AC_CONFIG_MACRO_DIR([m4])
-+m4_include([m4/ax_tls.m4])
-+
- AC_CONFIG_SRCDIR([urcu.h])
- AM_PROG_MKDIR_P
-
-diff --git a/m4/ax_tls.m4 b/m4/ax_tls.m4
-new file mode 100644
-index 0000000..033e3b1
---- /dev/null
-+++ b/m4/ax_tls.m4
-@@ -0,0 +1,76 @@
-+# ===========================================================================
-+# http://www.gnu.org/software/autoconf-archive/ax_tls.html
-+# ===========================================================================
-+#
-+# SYNOPSIS
-+#
-+# AX_TLS([action-if-found], [action-if-not-found])
-+#
-+# DESCRIPTION
-+#
-+# Provides a test for the compiler support of thread local storage (TLS)
-+# extensions. Defines TLS if it is found. Currently knows about GCC/ICC
-+# and MSVC. I think SunPro uses the same as GCC, and Borland apparently
-+# supports either.
-+#
-+# LICENSE
-+#
-+# Copyright (c) 2008 Alan Woodland <ajw05@aber.ac.uk>
-+# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
-+#
-+# 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/>.
-+#
-+# As a special exception, the respective Autoconf Macro's copyright owner
-+# gives unlimited permission to copy, distribute and modify the configure
-+# scripts that are the output of Autoconf when processing the Macro. You
-+# need not follow the terms of the GNU General Public License when using
-+# or distributing such scripts, even though portions of the text of the
-+# Macro appear in them. The GNU General Public License (GPL) does govern
-+# all other use of the material that constitutes the Autoconf Macro.
-+#
-+# This special exception to the GPL applies to versions of the Autoconf
-+# Macro released by the Autoconf Archive. When you make and distribute a
-+# modified version of the Autoconf Macro, you may extend this special
-+# exception to the GPL to apply to your modified version as well.
-+
-+#serial 10
-+
-+AC_DEFUN([AX_TLS], [
-+ AC_MSG_CHECKING(for thread local storage (TLS) class)
-+ AC_CACHE_VAL(ac_cv_tls, [
-+ ax_tls_keywords="__thread __declspec(thread) none"
-+ for ax_tls_keyword in $ax_tls_keywords; do
-+ AS_CASE([$ax_tls_keyword],
-+ [none], [ac_cv_tls=none ; break],
-+ [AC_TRY_COMPILE(
-+ [#include <stdlib.h>
-+ static void
-+ foo(void) {
-+ static ] $ax_tls_keyword [ int bar;
-+ exit(1);
-+ }],
-+ [],
-+ [ac_cv_tls=$ax_tls_keyword ; break],
-+ ac_cv_tls=none
-+ )])
-+ done
-+ ])
-+ AC_MSG_RESULT($ac_cv_tls)
-+
-+ AS_IF([test "$ac_cv_tls" != "none"],
-+ AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here])
-+ m4_ifnblank([$1], [$1]),
-+ m4_ifnblank([$2], [$2])
-+ )
-+])
-diff --git a/tests/test_mutex.c b/tests/test_mutex.c
-index 3f84bbf..bb73f1c 100644
---- a/tests/test_mutex.c
-+++ b/tests/test_mutex.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -155,8 +157,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static
- unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
-diff --git a/tests/test_perthreadlock.c b/tests/test_perthreadlock.c
-index fa9c89a..14362cf 100644
---- a/tests/test_perthreadlock.c
-+++ b/tests/test_perthreadlock.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -159,8 +161,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static
- unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
-diff --git a/tests/test_rwlock.c b/tests/test_rwlock.c
-index 34d8c07..087ff58 100644
---- a/tests/test_rwlock.c
-+++ b/tests/test_rwlock.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -156,8 +158,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static unsigned int nr_readers;
- static unsigned int nr_writers;
-diff --git a/tests/test_urcu.c b/tests/test_urcu.c
-index 870f133..cf8e12e 100644
---- a/tests/test_urcu.c
-+++ b/tests/test_urcu.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -154,8 +156,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static unsigned int nr_readers;
- static unsigned int nr_writers;
-diff --git a/tests/test_urcu_assign.c b/tests/test_urcu_assign.c
-index 42d70c2..55eab0c 100644
---- a/tests/test_urcu_assign.c
-+++ b/tests/test_urcu_assign.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -154,8 +156,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static unsigned int nr_readers;
- static unsigned int nr_writers;
-diff --git a/tests/test_urcu_bp.c b/tests/test_urcu_bp.c
-index 857913f..08170b6 100644
---- a/tests/test_urcu_bp.c
-+++ b/tests/test_urcu_bp.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -154,8 +156,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static unsigned int nr_readers;
- static unsigned int nr_writers;
-diff --git a/tests/test_urcu_defer.c b/tests/test_urcu_defer.c
-index 1575e9c..c5aeeb4 100644
---- a/tests/test_urcu_defer.c
-+++ b/tests/test_urcu_defer.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program (with automatic reclamation)
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -155,8 +157,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static
- unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
-diff --git a/tests/test_urcu_gc.c b/tests/test_urcu_gc.c
-index 21c5d56..31d3e65 100644
---- a/tests/test_urcu_gc.c
-+++ b/tests/test_urcu_gc.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program (with baatch reclamation)
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -163,8 +165,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static
- unsigned long long __attribute__((aligned(CAA_CACHE_LINE_SIZE))) *tot_nr_writes;
-diff --git a/tests/test_urcu_lfq.c b/tests/test_urcu_lfq.c
-index 11e7eb3..83db5d1 100644
---- a/tests/test_urcu_lfq.c
-+++ b/tests/test_urcu_lfq.c
-@@ -5,6 +5,7 @@
- *
- * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -38,6 +39,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -148,11 +150,15 @@ static int test_duration_enqueue(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_dequeues;
--static unsigned long long __thread nr_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
-+#define nr_dequeues (*_nr_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
-+#define nr_enqueues (*_nr_enqueues())
-
--static unsigned long long __thread nr_successful_dequeues;
--static unsigned long long __thread nr_successful_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
-+#define nr_successful_dequeues (*_nr_successful_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
-+#define nr_successful_enqueues (*_nr_successful_enqueues())
-
- static unsigned int nr_enqueuers;
- static unsigned int nr_dequeuers;
-diff --git a/tests/test_urcu_lfs.c b/tests/test_urcu_lfs.c
-index 883fd0c..79a1ceb 100644
---- a/tests/test_urcu_lfs.c
-+++ b/tests/test_urcu_lfs.c
-@@ -5,6 +5,7 @@
- *
- * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -38,6 +39,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -148,11 +150,15 @@ static int test_duration_enqueue(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_dequeues;
--static unsigned long long __thread nr_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
-+#define nr_dequeues (*_nr_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
-+#define nr_enqueues (*_nr_enqueues())
-
--static unsigned long long __thread nr_successful_dequeues;
--static unsigned long long __thread nr_successful_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
-+#define nr_successful_dequeues (*_nr_successful_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
-+#define nr_successful_enqueues (*_nr_successful_enqueues())
-
- static unsigned int nr_enqueuers;
- static unsigned int nr_dequeuers;
-diff --git a/tests/test_urcu_qsbr.c b/tests/test_urcu_qsbr.c
-index b986fd8..eaa4a67 100644
---- a/tests/test_urcu_qsbr.c
-+++ b/tests/test_urcu_qsbr.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -153,8 +155,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static unsigned int nr_readers;
- static unsigned int nr_writers;
-diff --git a/tests/test_urcu_qsbr_gc.c b/tests/test_urcu_qsbr_gc.c
-index 9deb0aa..e65503a 100644
---- a/tests/test_urcu_qsbr_gc.c
-+++ b/tests/test_urcu_qsbr_gc.c
-@@ -4,6 +4,7 @@
- * Userspace RCU library - test program (with baatch reclamation)
- *
- * Copyright February 2009 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -35,6 +36,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -159,8 +161,10 @@ static int test_duration_read(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_writes;
--static unsigned long long __thread nr_reads;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_writes, _tls_nr_writes);
-+#define nr_writes (*_nr_writes())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_reads, _tls_nr_reads);
-+#define nr_reads (*_nr_reads())
-
- static unsigned int nr_readers;
- static unsigned int nr_writers;
-diff --git a/tests/test_urcu_wfq.c b/tests/test_urcu_wfq.c
-index 83ec635..32156dc 100644
---- a/tests/test_urcu_wfq.c
-+++ b/tests/test_urcu_wfq.c
-@@ -5,6 +5,7 @@
- *
- * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -38,6 +39,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -147,11 +149,15 @@ static int test_duration_enqueue(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_dequeues;
--static unsigned long long __thread nr_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
-+#define nr_dequeues (*_nr_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
-+#define nr_enqueues (*_nr_enqueues())
-
--static unsigned long long __thread nr_successful_dequeues;
--static unsigned long long __thread nr_successful_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
-+#define nr_successful_dequeues (*_nr_successful_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
-+#define nr_successful_enqueues (*_nr_successful_enqueues())
-
- static unsigned int nr_enqueuers;
- static unsigned int nr_dequeuers;
-diff --git a/tests/test_urcu_wfs.c b/tests/test_urcu_wfs.c
-index 7746a1d..1e78211 100644
---- a/tests/test_urcu_wfs.c
-+++ b/tests/test_urcu_wfs.c
-@@ -5,6 +5,7 @@
- *
- * Copyright February 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright February 2010 - Paolo Bonzini <pbonzini@redhat.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * 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
-@@ -38,6 +39,7 @@
- #include <errno.h>
-
- #include <urcu/arch.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __linux__
- #include <syscall.h>
-@@ -147,11 +149,15 @@ static int test_duration_enqueue(void)
- return !test_stop;
- }
-
--static unsigned long long __thread nr_dequeues;
--static unsigned long long __thread nr_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_dequeues, _tls_nr_dequeues);
-+#define nr_dequeues (*_nr_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_enqueues, _tls_nr_enqueues);
-+#define nr_enqueues (*_nr_enqueues())
-
--static unsigned long long __thread nr_successful_dequeues;
--static unsigned long long __thread nr_successful_enqueues;
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_dequeues, _tls_nr_successful_dequeues);
-+#define nr_successful_dequeues (*_nr_successful_dequeues())
-+TLS_DEFINE_SIMPLE(unsigned long long, _nr_successful_enqueues, _tls_nr_successful_enqueues);
-+#define nr_successful_enqueues (*_nr_successful_enqueues())
-
- static unsigned int nr_enqueuers;
- static unsigned int nr_dequeuers;
-diff --git a/urcu-bp.c b/urcu-bp.c
-index f3249b4..1b38097 100644
---- a/urcu-bp.c
-+++ b/urcu-bp.c
-@@ -5,6 +5,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -35,6 +36,7 @@
- #include <poll.h>
- #include <unistd.h>
- #include <sys/mman.h>
-+#include <config.h>
-
- #include "urcu/wfqueue.h"
- #include "urcu/map/urcu-bp.h"
-@@ -94,7 +96,7 @@ static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
-
- #ifdef DEBUG_YIELD
- unsigned int yield_active;
--unsigned int __thread rand_yield;
-+TLS_DEFINE(unsigned int, get_rand_yield, _rand_yield);
- #endif
-
- /*
-@@ -109,7 +111,7 @@ long rcu_gp_ctr = RCU_GP_COUNT;
- * Pointer to registry elements. Written to only by each individual reader. Read
- * by both the reader and the writers.
- */
--struct rcu_reader __thread *rcu_reader;
-+TLS_DEFINE(struct rcu_reader*, rcu_reader, _rcu_reader);
-
- static CDS_LIST_HEAD(registry);
-
-@@ -322,7 +324,7 @@ static void add_thread(void)
- rcu_reader_reg->tid = pthread_self();
- assert(rcu_reader_reg->ctr == 0);
- cds_list_add(&rcu_reader_reg->node, &registry);
-- rcu_reader = rcu_reader_reg;
-+ *rcu_reader() = rcu_reader_reg;
- }
-
- /* Called with signals off and mutex locked */
-@@ -363,7 +365,7 @@ void rcu_bp_register(void)
- /*
- * Check if a signal concurrently registered our thread since
- * the check in rcu_read_lock(). */
-- if (rcu_reader)
-+ if (*rcu_reader())
- goto end;
-
- mutex_lock(&rcu_gp_lock);
-diff --git a/urcu-call-rcu-impl.h b/urcu-call-rcu-impl.h
-index 36e3cf4..27cb1ac 100644
---- a/urcu-call-rcu-impl.h
-+++ b/urcu-call-rcu-impl.h
-@@ -4,6 +4,7 @@
- * Userspace RCU library - batch memory reclamation with kernel API
- *
- * Copyright (c) 2010 Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -61,8 +62,31 @@ struct call_rcu_data {
- CDS_LIST_HEAD(call_rcu_data_list);
-
- /* Link a thread using call_rcu() to its call_rcu thread. */
--
-+#ifdef TLS
- static __thread struct call_rcu_data *thread_call_rcu_data;
-+#else
-+static pthread_key_t tls_tcrd_key;
-+static pthread_once_t tls_tcrd_once = PTHREAD_ONCE_INIT;
-+static void tls_tcrd_deinit() {
-+ void *p = pthread_getspecific(tls_tcrd_key);
-+ free(p);
-+}
-+static void tls_tcrd_init() {
-+ (void)pthread_key_create(&tls_tcrd_key, tls_tcrd_deinit);
-+ atexit(tls_tcrd_deinit);
-+}
-+static struct call_rcu_data **tls_thread_call_rcu_data() {
-+ (void)pthread_once(&tls_tcrd_once, tls_tcrd_init);
-+ struct call_rcu_data **r = pthread_getspecific(tls_tcrd_key);
-+ if (r == NULL) {
-+ r = malloc(sizeof(struct call_rcu_data *));
-+ *r = NULL;
-+ (void)pthread_setspecific(tls_tcrd_key, r);
-+ }
-+ return r;
-+}
-+#define thread_call_rcu_data (*tls_thread_call_rcu_data())
-+#endif
-
- /* Guard call_rcu thread creation. */
-
-diff --git a/urcu-defer-impl.h b/urcu-defer-impl.h
-index 4d1ca5e..21c337d 100644
---- a/urcu-defer-impl.h
-+++ b/urcu-defer-impl.h
-@@ -11,6 +11,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -40,6 +41,7 @@
- #include <sys/time.h>
- #include <unistd.h>
- #include <stdint.h>
-+#include <config.h>
-
- #include "urcu/futex.h"
-
-@@ -48,6 +50,7 @@
- #include <urcu/uatomic.h>
- #include <urcu/list.h>
- #include <urcu/system.h>
-+#include <urcu/tls-compat.h>
-
- /*
- * Number of entries in the per-thread defer queue. Must be power of 2.
-@@ -130,7 +133,9 @@ static int32_t defer_thread_stop;
- * Written to only by each individual deferer. Read by both the deferer and
- * the reclamation tread.
- */
--static struct defer_queue __thread defer_queue;
-+TLS_DEFINE_SIMPLE(struct defer_queue, get_defer_queue, defer_queue);
-+#define _defer_queue (*get_defer_queue())
-+
- static CDS_LIST_HEAD(registry_defer);
- static pthread_t tid_defer;
-
-@@ -245,12 +250,12 @@ static void _rcu_defer_barrier_thread(void)
- {
- unsigned long head, num_items;
-
-- head = defer_queue.head;
-- num_items = head - defer_queue.tail;
-+ head = _defer_queue.head;
-+ num_items = head - _defer_queue.tail;
- if (caa_unlikely(!num_items))
- return;
- synchronize_rcu();
-- rcu_defer_barrier_queue(&defer_queue, head);
-+ rcu_defer_barrier_queue(&_defer_queue, head);
- }
-
- void rcu_defer_barrier_thread(void)
-@@ -311,8 +316,8 @@ void _defer_rcu(void (*fct)(void *p), void *p)
- * Head is only modified by ourself. Tail can be modified by reclamation
- * thread.
- */
-- head = defer_queue.head;
-- tail = CMM_LOAD_SHARED(defer_queue.tail);
-+ head = _defer_queue.head;
-+ tail = CMM_LOAD_SHARED(_defer_queue.tail);
-
- /*
- * If queue is full, or reached threshold. Empty queue ourself.
-@@ -321,7 +326,7 @@ void _defer_rcu(void (*fct)(void *p), void *p)
- if (caa_unlikely(head - tail >= DEFER_QUEUE_SIZE - 2)) {
- assert(head - tail <= DEFER_QUEUE_SIZE);
- rcu_defer_barrier_thread();
-- assert(head - CMM_LOAD_SHARED(defer_queue.tail) == 0);
-+ assert(head - CMM_LOAD_SHARED(_defer_queue.tail) == 0);
- }
-
- /*
-@@ -340,25 +345,25 @@ void _defer_rcu(void (*fct)(void *p), void *p)
- * Decode: see the comments before 'struct defer_queue'
- * or the code in rcu_defer_barrier_queue().
- */
-- if (caa_unlikely(defer_queue.last_fct_in != fct
-+ if (caa_unlikely(_defer_queue.last_fct_in != fct
- || DQ_IS_FCT_BIT(p)
- || p == DQ_FCT_MARK)) {
-- defer_queue.last_fct_in = fct;
-+ _defer_queue.last_fct_in = fct;
- if (caa_unlikely(DQ_IS_FCT_BIT(fct) || fct == DQ_FCT_MARK)) {
-- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK],
-+ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK],
- DQ_FCT_MARK);
-- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK],
-+ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK],
- fct);
- } else {
- DQ_SET_FCT_BIT(fct);
-- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK],
-+ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK],
- fct);
- }
- }
-- _CMM_STORE_SHARED(defer_queue.q[head++ & DEFER_QUEUE_MASK], p);
-+ _CMM_STORE_SHARED(_defer_queue.q[head++ & DEFER_QUEUE_MASK], p);
- cmm_smp_wmb(); /* Publish new pointer before head */
- /* Write q[] before head. */
-- CMM_STORE_SHARED(defer_queue.head, head);
-+ CMM_STORE_SHARED(_defer_queue.head, head);
- cmm_smp_mb(); /* Write queue head before read futex */
- /*
- * Wake-up any waiting defer thread.
-@@ -422,16 +427,16 @@ int rcu_defer_register_thread(void)
- {
- int was_empty;
-
-- assert(defer_queue.last_head == 0);
-- assert(defer_queue.q == NULL);
-- defer_queue.q = malloc(sizeof(void *) * DEFER_QUEUE_SIZE);
-- if (!defer_queue.q)
-+ assert(_defer_queue.last_head == 0);
-+ assert(_defer_queue.q == NULL);
-+ _defer_queue.q = malloc(sizeof(void *) * DEFER_QUEUE_SIZE);
-+ if (!_defer_queue.q)
- return -ENOMEM;
-
- mutex_lock_defer(&defer_thread_mutex);
- mutex_lock_defer(&rcu_defer_mutex);
- was_empty = cds_list_empty(&registry_defer);
-- cds_list_add(&defer_queue.list, &registry_defer);
-+ cds_list_add(&_defer_queue.list, &registry_defer);
- mutex_unlock(&rcu_defer_mutex);
-
- if (was_empty)
-@@ -446,10 +451,10 @@ void rcu_defer_unregister_thread(void)
-
- mutex_lock_defer(&defer_thread_mutex);
- mutex_lock_defer(&rcu_defer_mutex);
-- cds_list_del(&defer_queue.list);
-+ cds_list_del(&_defer_queue.list);
- _rcu_defer_barrier_thread();
-- free(defer_queue.q);
-- defer_queue.q = NULL;
-+ free(_defer_queue.q);
-+ _defer_queue.q = NULL;
- is_empty = cds_list_empty(&registry_defer);
- mutex_unlock(&rcu_defer_mutex);
-
-diff --git a/urcu-qsbr.c b/urcu-qsbr.c
-index 5530295..6eeb90c 100644
---- a/urcu-qsbr.c
-+++ b/urcu-qsbr.c
-@@ -5,6 +5,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -34,6 +35,7 @@
- #include <string.h>
- #include <errno.h>
- #include <poll.h>
-+#include <config.h>
-
- #include "urcu/wfqueue.h"
- #include "urcu/map/urcu-qsbr.h"
-@@ -66,11 +68,11 @@ unsigned long rcu_gp_ctr = RCU_GP_ONLINE;
- * Written to only by each individual reader. Read by both the reader and the
- * writers.
- */
--struct rcu_reader __thread rcu_reader;
-+TLS_DEFINE(struct rcu_reader, rcu_reader, _rcu_reader);
-
- #ifdef DEBUG_YIELD
- unsigned int yield_active;
--unsigned int __thread rand_yield;
-+TLS_DEFINE(unsigned int, get_rand_yield, _rand_yield);
- #endif
-
- static CDS_LIST_HEAD(registry);
-@@ -206,7 +208,7 @@ void synchronize_rcu(void)
- {
- unsigned long was_online;
-
-- was_online = rcu_reader.ctr;
-+ was_online = rcu_reader()->ctr;
-
- /* All threads should read qparity before accessing data structure
- * where new ptr points to. In the "then" case, rcu_thread_offline
-@@ -269,7 +271,7 @@ void synchronize_rcu(void)
- {
- unsigned long was_online;
-
-- was_online = rcu_reader.ctr;
-+ was_online = rcu_reader()->ctr;
-
- /*
- * Mark the writer thread offline to make sure we don't wait for
-@@ -326,11 +328,11 @@ void rcu_thread_online(void)
-
- void rcu_register_thread(void)
- {
-- rcu_reader.tid = pthread_self();
-- assert(rcu_reader.ctr == 0);
-+ rcu_reader()->tid = pthread_self();
-+ assert(rcu_reader()->ctr == 0);
-
- mutex_lock(&rcu_gp_lock);
-- cds_list_add(&rcu_reader.node, &registry);
-+ cds_list_add(&rcu_reader()->node, &registry);
- mutex_unlock(&rcu_gp_lock);
- _rcu_thread_online();
- }
-@@ -343,7 +345,7 @@ void rcu_unregister_thread(void)
- */
- _rcu_thread_offline();
- mutex_lock(&rcu_gp_lock);
-- cds_list_del(&rcu_reader.node);
-+ cds_list_del(&rcu_reader()->node);
- mutex_unlock(&rcu_gp_lock);
- }
-
-diff --git a/urcu.c b/urcu.c
-index ba013d9..69a8311 100644
---- a/urcu.c
-+++ b/urcu.c
-@@ -5,6 +5,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -35,6 +36,7 @@
- #include <string.h>
- #include <errno.h>
- #include <poll.h>
-+#include <config.h>
-
- #include "urcu/wfqueue.h"
- #include "urcu/map/urcu.h"
-@@ -94,11 +96,11 @@ unsigned long rcu_gp_ctr = RCU_GP_COUNT;
- * Written to only by each individual reader. Read by both the reader and the
- * writers.
- */
--struct rcu_reader __thread rcu_reader;
-+TLS_DEFINE(struct rcu_reader, rcu_reader, _rcu_reader);
-
- #ifdef DEBUG_YIELD
- unsigned int yield_active;
--unsigned int __thread rand_yield;
-+TLS_DEFINE(unsigned int, get_rand_yield, _rand_yield);
- #endif
-
- static CDS_LIST_HEAD(registry);
-@@ -120,9 +122,9 @@ static void mutex_lock(pthread_mutex_t *mutex)
- perror("Error in pthread mutex lock");
- exit(-1);
- }
-- if (CMM_LOAD_SHARED(rcu_reader.need_mb)) {
-+ if (CMM_LOAD_SHARED(rcu_reader()->need_mb)) {
- cmm_smp_mb();
-- _CMM_STORE_SHARED(rcu_reader.need_mb, 0);
-+ _CMM_STORE_SHARED(rcu_reader()->need_mb, 0);
- cmm_smp_mb();
- }
- poll(NULL,0,10);
-@@ -368,20 +370,20 @@ void rcu_read_unlock(void)
-
- void rcu_register_thread(void)
- {
-- rcu_reader.tid = pthread_self();
-- assert(rcu_reader.need_mb == 0);
-- assert(!(rcu_reader.ctr & RCU_GP_CTR_NEST_MASK));
-+ rcu_reader()->tid = pthread_self();
-+ assert(rcu_reader()->need_mb == 0);
-+ assert(!(rcu_reader()->ctr & RCU_GP_CTR_NEST_MASK));
-
- mutex_lock(&rcu_gp_lock);
- rcu_init(); /* In case gcc does not support constructor attribute */
-- cds_list_add(&rcu_reader.node, &registry);
-+ cds_list_add(&rcu_reader()->node, &registry);
- mutex_unlock(&rcu_gp_lock);
- }
-
- void rcu_unregister_thread(void)
- {
- mutex_lock(&rcu_gp_lock);
-- cds_list_del(&rcu_reader.node);
-+ cds_list_del(&rcu_reader()->node);
- mutex_unlock(&rcu_gp_lock);
- }
-
-@@ -405,7 +407,7 @@ static void sigrcu_handler(int signo, siginfo_t *siginfo, void *context)
- * executed on.
- */
- cmm_smp_mb();
-- _CMM_STORE_SHARED(rcu_reader.need_mb, 0);
-+ _CMM_STORE_SHARED(rcu_reader()->need_mb, 0);
- cmm_smp_mb();
- }
-
-diff --git a/urcu/map/urcu-bp.h b/urcu/map/urcu-bp.h
-index 4abe8dc..f269135 100644
---- a/urcu/map/urcu-bp.h
-+++ b/urcu/map/urcu-bp.h
-@@ -9,6 +9,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * LGPL-compatible code should include this header with :
- *
-@@ -44,6 +45,7 @@
- #define rcu_exit rcu_exit_bp
- #define synchronize_rcu synchronize_rcu_bp
- #define rcu_reader rcu_reader_bp
-+#define _rcu_reader _rcu_reader_bp
- #define rcu_gp_ctr rcu_gp_ctr_bp
-
- #define get_cpu_call_rcu_data get_cpu_call_rcu_data_bp
-diff --git a/urcu/map/urcu-qsbr.h b/urcu/map/urcu-qsbr.h
-index 0d88d83..f947791 100644
---- a/urcu/map/urcu-qsbr.h
-+++ b/urcu/map/urcu-qsbr.h
-@@ -9,6 +9,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * LGPL-compatible code should include this header with :
- *
-@@ -47,6 +48,7 @@
- #define rcu_exit rcu_exit_qsbr
- #define synchronize_rcu synchronize_rcu_qsbr
- #define rcu_reader rcu_reader_qsbr
-+#define _rcu_reader _rcu_reader_qsbr
- #define rcu_gp_ctr rcu_gp_ctr_qsbr
-
- #define get_cpu_call_rcu_data get_cpu_call_rcu_data_qsbr
-diff --git a/urcu/map/urcu.h b/urcu/map/urcu.h
-index 3f436a7..a6d5c37 100644
---- a/urcu/map/urcu.h
-+++ b/urcu/map/urcu.h
-@@ -9,6 +9,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * LGPL-compatible code should include this header with :
- *
-@@ -75,6 +76,7 @@
- #define rcu_exit rcu_exit_memb
- #define synchronize_rcu synchronize_rcu_memb
- #define rcu_reader rcu_reader_memb
-+#define _rcu_reader _rcu_reader_memb
- #define rcu_gp_ctr rcu_gp_ctr_memb
-
- #define get_cpu_call_rcu_data get_cpu_call_rcu_data_memb
-@@ -107,6 +109,7 @@
- #define rcu_exit rcu_exit_sig
- #define synchronize_rcu synchronize_rcu_sig
- #define rcu_reader rcu_reader_sig
-+#define _rcu_reader _rcu_reader_sig
- #define rcu_gp_ctr rcu_gp_ctr_sig
-
- #define get_cpu_call_rcu_data get_cpu_call_rcu_data_sig
-@@ -139,6 +142,7 @@
- #define rcu_exit rcu_exit_mb
- #define synchronize_rcu synchronize_rcu_mb
- #define rcu_reader rcu_reader_mb
-+#define _rcu_reader _rcu_reader_mb
- #define rcu_gp_ctr rcu_gp_ctr_mb
-
- #define get_cpu_call_rcu_data get_cpu_call_rcu_data_mb
-diff --git a/urcu/static/urcu-bp.h b/urcu/static/urcu-bp.h
-index 8d22163..42e4b6e 100644
---- a/urcu/static/urcu-bp.h
-+++ b/urcu/static/urcu-bp.h
-@@ -11,6 +11,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -38,6 +39,7 @@
- #include <urcu/system.h>
- #include <urcu/uatomic.h>
- #include <urcu/list.h>
-+#include <urcu/tls-compat.h>
-
- /*
- * This code section can only be included in LGPL 2.1 compatible source code.
-@@ -74,7 +76,9 @@ extern "C" {
- #define MAX_SLEEP 50
-
- extern unsigned int yield_active;
--extern unsigned int __thread rand_yield;
-+TLS_DECLARE(unsigned int, get_rand_yield, _rand_yield);
-+// Safe if rand_yield is not redefined
-+#define rand_yield (*get_rand_yield())
-
- static inline void debug_yield_read(void)
- {
-@@ -144,7 +148,7 @@ struct rcu_reader {
- * Adds a pointer dereference on the read-side, but won't require to unregister
- * the reader thread.
- */
--extern struct rcu_reader __thread *rcu_reader;
-+TLS_DECLARE(struct rcu_reader*, rcu_reader, _rcu_reader);
-
- static inline int rcu_old_gp_ongoing(long *value)
- {
-@@ -166,24 +170,24 @@ static inline void _rcu_read_lock(void)
- long tmp;
-
- /* Check if registered */
-- if (caa_unlikely(!rcu_reader))
-+ if (caa_unlikely(!*rcu_reader()))
- rcu_bp_register();
-
- cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
-- tmp = rcu_reader->ctr;
-+ tmp = (*rcu_reader())->ctr;
- /*
- * rcu_gp_ctr is
- * RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
- */
- if (caa_likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
-- _CMM_STORE_SHARED(rcu_reader->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
-+ _CMM_STORE_SHARED((*rcu_reader())->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
- /*
- * Set active readers count for outermost nesting level before
- * accessing the pointer.
- */
- cmm_smp_mb();
- } else {
-- _CMM_STORE_SHARED(rcu_reader->ctr, tmp + RCU_GP_COUNT);
-+ _CMM_STORE_SHARED((*rcu_reader())->ctr, tmp + RCU_GP_COUNT);
- }
- }
-
-@@ -193,7 +197,7 @@ static inline void _rcu_read_unlock(void)
- * Finish using rcu before decrementing the pointer.
- */
- cmm_smp_mb();
-- _CMM_STORE_SHARED(rcu_reader->ctr, rcu_reader->ctr - RCU_GP_COUNT);
-+ _CMM_STORE_SHARED((*rcu_reader())->ctr, (*rcu_reader())->ctr - RCU_GP_COUNT);
- cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
- }
-
-diff --git a/urcu/static/urcu-qsbr.h b/urcu/static/urcu-qsbr.h
-index 68bfc31..fac39a1 100644
---- a/urcu/static/urcu-qsbr.h
-+++ b/urcu/static/urcu-qsbr.h
-@@ -11,6 +11,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -42,6 +43,7 @@
- #include <urcu/uatomic.h>
- #include <urcu/list.h>
- #include <urcu/futex.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __cplusplus
- extern "C" {
-@@ -74,7 +76,9 @@ extern "C" {
- #define MAX_SLEEP 50
-
- extern unsigned int yield_active;
--extern unsigned int __thread rand_yield;
-+TLS_DECLARE(unsigned int, get_rand_yield, _rand_yield);
-+// Safe if rand_yield is not redefined
-+#define rand_yield (*get_rand_yield())
-
- static inline void debug_yield_read(void)
- {
-@@ -128,7 +132,7 @@ struct rcu_reader {
- pthread_t tid;
- };
-
--extern struct rcu_reader __thread rcu_reader;
-+TLS_DECLARE(struct rcu_reader, rcu_reader, _rcu_reader);
-
- extern int32_t gp_futex;
-
-@@ -137,8 +141,8 @@ extern int32_t gp_futex;
- */
- static inline void wake_up_gp(void)
- {
-- if (caa_unlikely(_CMM_LOAD_SHARED(rcu_reader.waiting))) {
-- _CMM_STORE_SHARED(rcu_reader.waiting, 0);
-+ if (caa_unlikely(_CMM_LOAD_SHARED(rcu_reader()->waiting))) {
-+ _CMM_STORE_SHARED(rcu_reader()->waiting, 0);
- cmm_smp_mb();
- if (uatomic_read(&gp_futex) != -1)
- return;
-@@ -158,7 +162,7 @@ static inline int rcu_gp_ongoing(unsigned long *ctr)
-
- static inline void _rcu_read_lock(void)
- {
-- rcu_assert(rcu_reader.ctr);
-+ rcu_assert(rcu_reader()->ctr);
- }
-
- static inline void _rcu_read_unlock(void)
-@@ -168,7 +172,7 @@ static inline void _rcu_read_unlock(void)
- static inline void _rcu_quiescent_state(void)
- {
- cmm_smp_mb();
-- _CMM_STORE_SHARED(rcu_reader.ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
-+ _CMM_STORE_SHARED(rcu_reader()->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
- cmm_smp_mb(); /* write rcu_reader.ctr before read futex */
- wake_up_gp();
- cmm_smp_mb();
-@@ -177,8 +181,8 @@ static inline void _rcu_quiescent_state(void)
- static inline void _rcu_thread_offline(void)
- {
- cmm_smp_mb();
-- CMM_STORE_SHARED(rcu_reader.ctr, 0);
-- cmm_smp_mb(); /* write rcu_reader.ctr before read futex */
-+ CMM_STORE_SHARED(rcu_reader()->ctr, 0);
-+ cmm_smp_mb(); /* write _rcu_reader.ctr before read futex */
- wake_up_gp();
- cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
- }
-@@ -186,7 +190,7 @@ static inline void _rcu_thread_offline(void)
- static inline void _rcu_thread_online(void)
- {
- cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
-- _CMM_STORE_SHARED(rcu_reader.ctr, CMM_LOAD_SHARED(rcu_gp_ctr));
-+ _CMM_STORE_SHARED(rcu_reader()->ctr, CMM_LOAD_SHARED(rcu_gp_ctr));
- cmm_smp_mb();
- }
-
-diff --git a/urcu/static/urcu.h b/urcu/static/urcu.h
-index 7ae0185..302404b 100644
---- a/urcu/static/urcu.h
-+++ b/urcu/static/urcu.h
-@@ -11,6 +11,7 @@
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
-+ * Copyright (C) 2012 Marek Vavrusa <marek.vavrusa@nic.cz>, CZ.NIC, z.s.p.o.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
-@@ -33,6 +34,7 @@
- #include <pthread.h>
- #include <unistd.h>
- #include <stdint.h>
-+#include <config.h>
-
- #include <urcu/compiler.h>
- #include <urcu/arch.h>
-@@ -40,6 +42,7 @@
- #include <urcu/uatomic.h>
- #include <urcu/list.h>
- #include <urcu/futex.h>
-+#include <urcu/tls-compat.h>
-
- #ifdef __cplusplus
- extern "C" {
-@@ -121,7 +124,9 @@ extern "C" {
- #endif
-
- extern unsigned int yield_active;
--extern unsigned int __thread rand_yield;
-+TLS_DECLARE(unsigned int, get_rand_yield, _rand_yield);
-+// Safe shortcut if rand_yield is not redefined
-+#define rand_yield (*get_rand_yield())
-
- static inline void debug_yield_read(void)
- {
-@@ -222,7 +227,7 @@ struct rcu_reader {
- pthread_t tid;
- };
-
--extern struct rcu_reader __thread rcu_reader;
-+TLS_DECLARE(struct rcu_reader, rcu_reader, _rcu_reader);
-
- extern int32_t gp_futex;
-
-@@ -256,20 +261,20 @@ static inline void _rcu_read_lock(void)
- unsigned long tmp;
-
- cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
-- tmp = rcu_reader.ctr;
-+ tmp = rcu_reader()->ctr;
- /*
- * rcu_gp_ctr is
- * RCU_GP_COUNT | (~RCU_GP_CTR_PHASE or RCU_GP_CTR_PHASE)
- */
- if (caa_likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
-- _CMM_STORE_SHARED(rcu_reader.ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
-+ _CMM_STORE_SHARED(rcu_reader()->ctr, _CMM_LOAD_SHARED(rcu_gp_ctr));
- /*
- * Set active readers count for outermost nesting level before
- * accessing the pointer. See smp_mb_master().
- */
- smp_mb_slave(RCU_MB_GROUP);
- } else {
-- _CMM_STORE_SHARED(rcu_reader.ctr, tmp + RCU_GP_COUNT);
-+ _CMM_STORE_SHARED(rcu_reader()->ctr, tmp + RCU_GP_COUNT);
- }
- }
-
-@@ -277,19 +282,19 @@ static inline void _rcu_read_unlock(void)
- {
- unsigned long tmp;
-
-- tmp = rcu_reader.ctr;
-+ tmp = rcu_reader()->ctr;
- /*
- * Finish using rcu before decrementing the pointer.
- * See smp_mb_master().
- */
- if (caa_likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) {
- smp_mb_slave(RCU_MB_GROUP);
-- _CMM_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT);
-+ _CMM_STORE_SHARED(rcu_reader()->ctr, rcu_reader()->ctr - RCU_GP_COUNT);
- /* write rcu_reader.ctr before read futex */
- smp_mb_slave(RCU_MB_GROUP);
- wake_up_gp();
- } else {
-- _CMM_STORE_SHARED(rcu_reader.ctr, rcu_reader.ctr - RCU_GP_COUNT);
-+ _CMM_STORE_SHARED(rcu_reader()->ctr, rcu_reader()->ctr - RCU_GP_COUNT);
- }
- cmm_barrier(); /* Ensure the compiler does not reorder us with mutex */
- }
-diff --git a/urcu/tls-compat.h b/urcu/tls-compat.h
-new file mode 100644
-index 0000000..d47e803
---- /dev/null
-+++ b/urcu/tls-compat.h
-@@ -0,0 +1,104 @@
-+/* Copyright (C) 2011 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/>.
-+ */
-+#ifndef _TLS_COMPAT_H
-+#define _TLS_COMPAT_H
-+#include <config.h>
-+
-+/* Conditional includes. */
-+#ifndef TLS
-+#include <pthread.h>
-+#endif
-+
-+/*!
-+ * \brief TLS variable declaration (requires TLS_DEFINITION in .c file)
-+ * \param T declared type.
-+ * \param name output function name.
-+ * \param vname internal variable name.
-+ *
-+ * Output: function "T* name()".
-+ *
-+ * Example:
-+ * TLS_DECLARE(int, a, _a);
-+ * TLS_DEFINE(int, a, _a);
-+ * *(a()) = 1
-+ */
-+#ifdef TLS
-+ #define TLS_DECLARE(T, name, vname) \
-+ extern TLS T vname; \
-+ static inline T *name() { \
-+ return &vname;\
-+ }
-+#else
-+ #define TLS_DECLARE(T, name, vname) \
-+ T *name()
-+#endif
-+
-+/*!
-+ * \brief TLS variable definition.
-+ * \param T declared type.
-+ * \param name output function name.
-+ * \param vname internal variable name.
-+ *
-+ * Output: function "T* name()" or TLS variable "vname".
-+ * Requires TLS_DECLARE for exported API.
-+ */
-+#ifdef TLS
-+#define TLS_DEFINE(T, name, vname) \
-+TLS T vname
-+#else
-+#define TLS_DEFINE(T, name, vname) \
-+static pthread_key_t tls_ ## name ## _key; \
-+static pthread_once_t tls_ ## name ## _once = PTHREAD_ONCE_INIT; \
-+static void tls_ ## name ## _deinit() { \
-+ free((void*)pthread_getspecific(tls_ ## name ## _key)); \
-+} \
-+static void tls_ ## name ## _init() { \
-+ (void)pthread_key_create(&tls_ ## name ## _key, tls_ ## name ## _deinit); \
-+ atexit(tls_ ## name ## _deinit); \
-+} \
-+T *name() { \
-+ (void)pthread_once(&tls_ ## name ## _once, tls_ ## name ## _init); \
-+ void *p = pthread_getspecific(tls_ ## name ## _key); \
-+ if (p == NULL) { \
-+ p = malloc(sizeof(T)); \
-+ memset(p, 0, sizeof(T)); \
-+ (void)pthread_setspecific(tls_ ## name ## _key, p); \
-+ } \
-+ return p; \
-+}
-+#endif
-+
-+/*!
-+ * \brief TLS variable declaration+definition.
-+ * \param T declared type.
-+ * \param name output function name.
-+ * \param vname internal variable name.
-+ *
-+ * Output: function "T* name()" or TLS variable "vname".
-+ * Requires TLS_DECLARE for exported API.
-+ */
-+#ifndef TLS
-+#define TLS_DEFINE_SIMPLE(T, name, vname) \
-+TLS_DEFINE(T, name, vname)
-+#else
-+#define TLS_DEFINE_SIMPLE(T, name, vname) \
-+TLS_DEFINE(T, name, vname); \
-+static inline T *name() { \
-+ return &vname;\
-+}
-+#endif
-+
-+#endif // _TLS_COMPAT_H
---
-1.7.7.1
-
diff --git a/src/Makefile.am b/src/Makefile.am
index 963364d..a542399 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,170 +1,121 @@
-ACLOCAL_AMFLAGS = -I ../m4
-libexec_PROGRAMS = knot-zcompile unittests unittests-zcompile unittests-libknot-realdata unittests-libknot unittests-xfr
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+SUBDIRS = . tests
+
sbin_PROGRAMS = knotc knotd
-dist_man_MANS = knot.conf.5 knotc.8 knotd.8
+bin_PROGRAMS = kdig khost knsupdate
+noinst_PROGRAMS = zscanner-tool
+noinst_LTLIBRARIES = libknot.la libknotd.la libknots.la libzscanner.la
# $(YACC) will generate header file
-AM_CFLAGS = -Wall -Ilibknot -DLIBEXECDIR='"$(libexecdir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DSBINDIR='"$(sbindir)"'
+AM_CPPFLAGS = -I$(top_srcdir)/src/libknot -DSYSCONFDIR='"$(sysconfdir)"' \
+ -DSBINDIR='"$(sbindir)"' -DSTORAGE_DIR='"${storage_dir}"' \
+ -DRUN_DIR='"${run_dir}"'
AM_YFLAGS = -d
libknotd_la_YFLAGS = -pcf_ -d
libknotd_la_LFLAGS = # TODO: reentrant parser, prefix
+EXTRA_DIST = \
+ zscanner/scanner.rl \
+ zscanner/scanner_body.rl \
+ zscanner/test/run_tests.sh \
+ zscanner/test/cases
+
BUILT_SOURCES = \
- tests/libknot/parsed_data.rc \
- tests/libknot/realdata/parsed_data.rc \
- tests/libknot/raw_data_queries.rc \
- tests/libknot/raw_data.rc \
- tests/libknot/realdata/raw_data.rc \
- tests/libknot/parsed_data_queries.rc \
- tests/sample_conf.rc \
- zparser.h \
- zparser.c \
- zlexer.c \
- libknotd_la-cf-lex.c \
- libknotd_la-cf-parse.c \
- libknotd_la-cf-parse.h
+ knot/conf/libknotd_la-cf-lex.c \
+ knot/conf/libknotd_la-cf-parse.c \
+ knot/conf/libknotd_la-cf-parse.h
CLEANFILES = \
- tests/libknot/parsed_data.rc \
- tests/libknot/realdata/parsed_data.rc \
- tests/libknot/raw_data_queries.rc \
- tests/libknot/raw_data.rc \
- tests/libknot/realdata/raw_data.rc \
- tests/libknot/parsed_data_queries.rc \
- tests/sample_conf.rc \
- zparser.h \
- zparser.c \
- zlexer.c \
- libknotd_la-cf-lex.c \
- libknotd_la-cf-parse.c \
- libknotd_la-cf-parse.h
-
-knotc_SOURCES = \
- knot/ctl/knotc_main.c
-
-knot_zcompile_SOURCES = \
- zcompile/zcompile_main.c \
- zcompile/zcompile-error.c \
- zcompile/parser-util.h \
- zcompile/parser-descriptor.h \
- zcompile/zparser.y \
- zcompile/zlexer.l \
- zcompile/zcompile.c \
- zcompile/parser-util.c \
- zcompile/parser-descriptor.c
+ knot/conf/libknotd_la-cf-lex.c \
+ knot/conf/libknotd_la-cf-parse.c \
+ knot/conf/libknotd_la-cf-parse.h
-unittests_SOURCES = \
- tests/common/acl_tests.c \
- tests/common/acl_tests.h \
- tests/common/base32hex_tests.c \
- tests/common/base32hex_tests.h \
- tests/common/base64_tests.c \
- tests/common/base64_tests.h \
- tests/common/events_tests.c \
- tests/common/events_tests.h \
- tests/common/skiplist_tests.c \
- tests/common/skiplist_tests.h \
- tests/common/slab_tests.c \
- tests/common/slab_tests.h \
- tests/common/fdset_tests.c \
- tests/common/fdset_tests.h \
- tests/knot/conf_tests.c \
- tests/knot/conf_tests.h \
- tests/knot/dthreads_tests.c \
- tests/knot/dthreads_tests.h \
- tests/knot/journal_tests.c \
- tests/knot/journal_tests.h \
- tests/knot/server_tests.c \
- tests/knot/server_tests.h \
- tests/knot/rrl_tests.c \
- tests/knot/rrl_tests.h \
- tests/unittests_main.c
+if HAVE_RAGEL
+BUILT_SOURCES += zscanner/scanner.c
+CLEANFILES += zscanner/scanner.c
-unittests_libknot_realdata_SOURCES = \
- tests/libknot/realdata/libknot/dname_tests_realdata.c \
- tests/libknot/realdata/libknot/response_tests_realdata.c \
- tests/libknot/realdata/libknot/edns_tests_realdata.c \
- tests/libknot/realdata/libknot/node_tests_realdata.c \
- tests/libknot/realdata/libknot/rdata_tests_realdata.c \
- tests/libknot/realdata/libknot/rrset_tests_realdata.c \
- tests/libknot/realdata/libknot/zone_tests_realdata.c \
- tests/libknot/realdata/libknot/zonedb_tests_realdata.c \
- tests/libknot/realdata/libknot/packet_tests_realdata.h \
- tests/libknot/realdata/libknot/packet_tests_realdata.c \
- tests/libknot/realdata/libknot_tests_loader_realdata.h \
- tests/libknot/realdata/libknot_tests_loader_realdata.c \
- tests/libknot/realdata/unittests_libknot_realdata.c
+zscanner/scanner.c: zscanner/scanner.rl zscanner/scanner_body.rl
+ $(RAGEL) $(FSM_TYPE) -s -o $@ $(srcdir)/zscanner/scanner.rl
-unittests_libknot_SOURCES = \
- tests/libknot/libknot/cuckoo_tests.c \
- tests/libknot/libknot/cuckoo_tests.h \
- tests/libknot/libknot/response_tests.h \
- tests/libknot/libknot/response_tests.c \
- tests/libknot/libknot/dname_tests.c \
- tests/libknot/libknot/dname_tests.h \
- tests/libknot/libknot/dname_table_tests.h \
- tests/libknot/libknot/dname_table_tests.c \
- tests/libknot/libknot/nsec3_tests.h \
- tests/libknot/libknot/nsec3_tests.c \
- tests/libknot/libknot/packet_tests.h \
- tests/libknot/libknot/packet_tests.c \
- tests/libknot/libknot/query_tests.h \
- tests/libknot/libknot/query_tests.c \
- tests/libknot/libknot/edns_tests.c \
- tests/libknot/libknot/edns_tests.h \
- tests/libknot/libknot/node_tests.c \
- tests/libknot/libknot/node_tests.h \
- tests/libknot/libknot/rdata_tests.c \
- tests/libknot/libknot/rdata_tests.h \
- tests/libknot/libknot/rrset_tests.c \
- tests/libknot/libknot/rrset_tests.h \
- tests/libknot/libknot/tsig_tests.c \
- tests/libknot/libknot/tsig_tests.h \
- tests/libknot/libknot/zone_tests.c \
- tests/libknot/libknot/zone_tests.h \
- tests/libknot/libknot/zone_tree_tests.h \
- tests/libknot/libknot/zone_tree_tests.c \
- tests/libknot/libknot/zonedb_tests.c \
- tests/libknot/libknot/zonedb_tests.h \
- tests/libknot/unittests_libknot.c
+endif
-unittests_zcompile_SOURCES = \
- zcompile/parser-util.h \
- zcompile/parser-descriptor.h \
- zcompile/zcompile-error.c \
- zcompile/zparser.y \
- zcompile/zlexer.l \
- zcompile/zcompile.c \
- zcompile/parser-util.c \
- zcompile/parser-descriptor.c \
- zcompile/tests/unittests_zp_main.c
-
-unittests_xfr_SOURCES = \
- tests/xfr_tests.c \
- tests/xfr_tests.h
-
-nodist_unittests_SOURCES = \
- tests/libknot/parsed_data.rc \
- tests/libknot/raw_data_queries.rc \
- tests/libknot/raw_data.rc \
- tests/libknot/parsed_data_queries.rc \
- tests/sample_conf.rc
+knotc_SOURCES = \
+ knot/ctl/knotc_main.c
knotd_SOURCES = \
knot/main.c
-noinst_LTLIBRARIES = libknot.la libknotd.la libknots.la
+kdig_SOURCES = \
+ utils/common/msg.h \
+ utils/common/msg.c \
+ utils/common/exec.c \
+ utils/common/exec.h \
+ utils/common/params.c \
+ utils/common/params.h \
+ utils/common/resolv.c \
+ utils/common/resolv.h \
+ utils/common/netio.c \
+ utils/common/netio.h \
+ utils/common/token.c \
+ utils/common/token.h \
+ utils/dig/dig_main.c \
+ utils/dig/dig_params.c \
+ utils/dig/dig_params.h \
+ utils/dig/dig_exec.c \
+ utils/dig/dig_exec.h
+
+khost_SOURCES = \
+ utils/common/msg.h \
+ utils/common/msg.c \
+ utils/common/exec.c \
+ utils/common/exec.h \
+ utils/common/params.c \
+ utils/common/params.h \
+ utils/common/resolv.c \
+ utils/common/resolv.h \
+ utils/common/netio.c \
+ utils/common/netio.h \
+ utils/common/token.c \
+ utils/common/token.h \
+ utils/host/host_main.c \
+ utils/dig/dig_params.c \
+ utils/dig/dig_params.h \
+ utils/host/host_params.c \
+ utils/host/host_params.h \
+ utils/dig/dig_exec.c \
+ utils/dig/dig_exec.h
+
+knsupdate_SOURCES = \
+ utils/common/msg.h \
+ utils/common/msg.c \
+ utils/common/params.c \
+ utils/common/params.h \
+ utils/common/resolv.c \
+ utils/common/resolv.h \
+ utils/common/netio.c \
+ utils/common/netio.h \
+ utils/common/token.c \
+ utils/common/token.h \
+ utils/common/exec.c \
+ utils/common/exec.h \
+ utils/nsupdate/nsupdate_main.c \
+ utils/nsupdate/nsupdate_params.h \
+ utils/nsupdate/nsupdate_params.c \
+ utils/nsupdate/nsupdate_exec.h \
+ utils/nsupdate/nsupdate_exec.c
libknot_la_SOURCES = \
+ libknot/common.h \
+ libknot/consts.h \
+ libknot/consts.c \
libknot/util/utils.c \
libknot/util/debug.c \
libknot/util/debug.h \
libknot/util/utils.h \
- libknot/util/descriptor.c \
libknot/util/tolower.h \
libknot/util/tolower.c \
- libknot/util/descriptor.h \
libknot/util/wire.h \
+ libknot/util/endian.h \
libknot/packet/query.c \
libknot/packet/response.c \
libknot/packet/packet.c \
@@ -181,51 +132,57 @@ libknot_la_SOURCES = \
libknot/zone/zonedb.c \
libknot/zone/zonedb.h \
libknot/zone/node.c \
- libknot/zone/dname-table.h \
- libknot/zone/dname-table.c \
libknot/zone/zone-diff.h \
libknot/zone/zone-diff.c \
- libknot/hash/hash-functions.c \
- libknot/hash/cuckoo-hash-table.c \
- libknot/hash/universal-system.c \
- libknot/hash/universal-system.h \
- libknot/hash/cuckoo-hash-table.h \
- libknot/hash/hash-functions.h \
libknot/nameserver/name-server.h \
libknot/nameserver/name-server.c \
+ libknot/nameserver/chaos.h \
+ libknot/nameserver/chaos.c \
libknot/updates/changesets.h \
libknot/updates/changesets.c \
libknot/updates/xfr-in.h \
libknot/updates/xfr-in.c \
libknot/updates/ddns.h \
libknot/updates/ddns.c \
- libknot/edns.c \
- libknot/rrset.c \
libknot/dname.c \
- libknot/rdata.c \
libknot/nsec3.c \
libknot/consts.h \
libknot/edns.h \
- libknot/rdata.h \
+ libknot/edns.c \
libknot/libknot.h \
libknot/dname.h \
libknot/rrset.h \
+ libknot/rrset.c \
libknot/nsec3.h \
+ libknot/rrset-dump.h \
+ libknot/rrset-dump.c \
libknot/tsig.h \
libknot/tsig.c \
libknot/tsig-op.h \
- libknot/tsig-op.c
+ libknot/tsig-op.c \
+ libknot/binary.h \
+ libknot/binary.c \
+ libknot/sign/key.h \
+ libknot/sign/key.c \
+ libknot/sign/bnutils.h \
+ libknot/sign/bnutils.c \
+ libknot/sign/dnssec.h \
+ libknot/sign/dnssec.c \
+ libknot/sign/sig0.h \
+ libknot/sign/sig0.c
libknots_la_SOURCES = \
- common/hattrie/murmurhash3.c \
- common/hattrie/murmurhash3.h \
common/slab/slab.c \
common/slab/slab.h \
+ common/slab/alloc-common.h \
common/libtap/tap.c \
common/libtap/tap.h \
common/libtap/tap_unit.h \
+ common/atomic.h \
common/mempattern.h \
common/mempattern.c \
+ common/descriptor.h \
+ common/descriptor.c \
common/lists.c \
common/base64.c \
common/base64.h \
@@ -237,9 +194,6 @@ libknots_la_SOURCES = \
common/skip-list.c \
common/base32hex.c \
common/skip-list.h \
- common/general-tree.h \
- common/general-tree.c \
- common/tree.h \
common/base32hex.h \
common/evqueue.h \
common/evqueue.c \
@@ -256,102 +210,111 @@ libknots_la_SOURCES = \
common/errors.c \
common/errcode.h \
common/errcode.c \
- common/dSFMT.h \
- common/dSFMT-params.h \
- common/dSFMT-params521.h \
- common/dSFMT.c \
- common/prng.h \
- common/prng.c \
- common/fdset.h \
- common/fdset.c \
- common/fdset_poll.h \
- common/fdset_poll.c \
- common/fdset_kqueue.h \
- common/fdset_kqueue.c \
- common/fdset_epoll.h \
- common/fdset_epoll.c \
+ common/dSFMT.h \
+ common/dSFMT-params.h \
+ common/dSFMT-params521.h \
+ common/dSFMT.c \
+ common/prng.h \
+ common/prng.c \
+ common/fdset.h \
+ common/fdset.c \
+ common/fdset_poll.h \
+ common/fdset_poll.c \
+ common/fdset_kqueue.h \
+ common/fdset_kqueue.c \
+ common/fdset_epoll.h \
+ common/fdset_epoll.c \
+ common/getline.h \
+ common/getline.c \
common/log.c \
- common/log.h
+ common/log.h \
+ common/mempool.c \
+ common/mempool.h \
+ common/hattrie/ahtable.c \
+ common/hattrie/ahtable.h \
+ common/hattrie/hat-trie.c \
+ common/hattrie/hat-trie.h \
+ common/hattrie/murmurhash3.c \
+ common/hattrie/murmurhash3.h
libknotd_la_SOURCES = \
- knot/stat/gatherer.c \
- knot/stat/stat.c \
- knot/stat/gatherer.h \
- knot/stat/stat.h \
- knot/common.h \
+ knot/stat/gatherer.c \
+ knot/stat/stat.c \
+ knot/stat/gatherer.h \
+ knot/stat/stat.h \
+ knot/stat/stat-common.h \
+ knot/knot.h \
knot/other/debug.h \
- knot/conf/cf-parse.y \
knot/conf/cf-lex.l \
+ knot/conf/cf-parse.y \
knot/conf/conf.c \
+ knot/conf/conf.h \
+ knot/conf/extra.c \
+ knot/conf/extra.h \
+ knot/conf/includes.c \
+ knot/conf/includes.h \
knot/conf/logconf.c \
knot/conf/logconf.h \
- knot/conf/conf.h \
knot/ctl/process.c \
knot/ctl/process.h \
knot/ctl/remote.c \
knot/ctl/remote.h \
knot/server/dthreads.c \
knot/server/journal.c \
- knot/server/socket.c \
- knot/server/server.c \
- knot/server/udp-handler.c \
- knot/server/tcp-handler.c \
- knot/server/xfr-handler.c \
- knot/server/zones.c \
- knot/server/socket.h \
- knot/server/udp-handler.h \
- knot/server/tcp-handler.h \
- knot/server/xfr-handler.h \
+ knot/server/socket.c \
+ knot/server/server.c \
+ knot/server/udp-handler.c \
+ knot/server/tcp-handler.c \
+ knot/server/xfr-handler.c \
+ knot/server/zones.c \
+ knot/server/socket.h \
+ knot/server/udp-handler.h \
+ knot/server/tcp-handler.h \
+ knot/server/xfr-handler.h \
knot/server/dthreads.h \
knot/server/journal.h \
- knot/server/zones.h \
- knot/server/notify.h \
- knot/server/notify.c \
- knot/server/zones.h \
- knot/server/rrl.c \
+ knot/server/zones.h \
+ knot/server/notify.h \
+ knot/server/notify.c \
+ knot/server/zones.h \
knot/server/rrl.h \
- knot/zone/zone-load.c \
- knot/zone/zone-load.h \
+ knot/server/rrl.c \
knot/zone/semantic-check.c \
knot/zone/semantic-check.h \
- knot/zone/zone-dump.c \
- knot/zone/zone-dump-text.c \
- knot/zone/zone-dump-text.h \
knot/zone/zone-dump.h \
+ knot/zone/zone-dump.c \
+ knot/zone/zone-load.h \
+ knot/zone/zone-load.c \
+ knot/zone/estimator.h \
+ knot/zone/estimator.c \
knot/server/server.h
+zscanner_tool_SOURCES = \
+ zscanner/test/zscanner-tool.c \
+ zscanner/test/tests.h \
+ zscanner/test/tests.c \
+ zscanner/test/processing.h \
+ zscanner/test/processing.c
+
+libzscanner_la_SOURCES = \
+ zscanner/file_loader.h \
+ zscanner/file_loader.c \
+ zscanner/scanner.h \
+ zscanner/scanner.c \
+ zscanner/scanner_functions.h \
+ zscanner/scanner_functions.c
+
libknotd_la_LIBADD = libknot.la libknots.la @LIBOBJS@
-libknots_la_LIBADD = @LIBOBJS@
+libknots_la_LIBADD = libzscanner.la @LIBOBJS@
+libzscanner_la_LIBADD = @LIBOBJS@
knotd_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
knotc_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
-knot_zcompile_LDADD = libknots.la libknot.la libknotd.la @LIBOBJS@
-unittests_LDADD = libknotd.la libknots.la @LIBOBJS@
-unittests_zcompile_LDADD = libknot.la libknots.la libknotd.la @LIBOBJS@
-unittests_libknot_LDADD = libknot.la libknots.la @LIBOBJS@
-unittests_libknot_realdata_LDADD = libknot.la libknots.la @LIBOBJS@
-unittests_xfr_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
-
-# automake complains on % rules:
-# `%'-style pattern rules are a GNU make extension
-
-tests/libknot/parsed_data.rc: tests/libknot/files/parsed_data
- ../resource.sh tests/libknot/files/parsed_data >$@
-
-tests/libknot/realdata/parsed_data.rc: tests/libknot/realdata/files/parsed_data
- ../resource.sh tests/libknot/realdata/files/parsed_data >$@
-
-tests/libknot/parsed_data_queries.rc: tests/libknot/files/parsed_data_queries
- ../resource.sh tests/libknot/files/parsed_data_queries >$@
-
-tests/libknot/raw_data_queries.rc: tests/libknot/files/raw_data_queries
- ../resource.sh tests/libknot/files/raw_data_queries >$@
-
-tests/libknot/raw_data.rc: tests/libknot/files/raw_data
- ../resource.sh tests/libknot/files/raw_data >$@
-
-tests/libknot/realdata/raw_data.rc: tests/libknot/realdata/files/raw_data
- ../resource.sh tests/libknot/realdata/files/raw_data >$@
-
-tests/sample_conf.rc: tests/files/sample_conf
- ../resource.sh tests/files/sample_conf >$@
+kdig_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
+khost_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
+knsupdate_LDADD = libknotd.la libknot.la libknots.la libzscanner.la @LIBOBJS@
+zscanner_tool_LDADD = libknots.la libknot.la libknotd.la libzscanner.la @LIBOBJS@
+# Create storage and run-time directories
+install-data-hook:
+ $(INSTALL) -d $(DESTDIR)/@run_dir@
+ $(INSTALL) -d $(DESTDIR)/@storage_dir@
diff --git a/src/Makefile.in b/src/Makefile.in
index 61a7298..90f5050 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.12.6 from Makefile.am.
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
-
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -51,25 +52,24 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-libexec_PROGRAMS = knot-zcompile$(EXEEXT) unittests$(EXEEXT) \
- unittests-zcompile$(EXEEXT) \
- unittests-libknot-realdata$(EXEEXT) unittests-libknot$(EXEEXT) \
- unittests-xfr$(EXEEXT)
sbin_PROGRAMS = knotc$(EXEEXT) knotd$(EXEEXT)
+bin_PROGRAMS = kdig$(EXEEXT) khost$(EXEEXT) knsupdate$(EXEEXT)
+noinst_PROGRAMS = zscanner-tool$(EXEEXT)
+@HAVE_RAGEL_TRUE@am__append_1 = zscanner/scanner.c
+@HAVE_RAGEL_TRUE@am__append_2 = zscanner/scanner.c
subdir = src
-DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.am \
- $(srcdir)/Makefile.in $(srcdir)/config.h.in \
- $(top_srcdir)/depcomp $(top_srcdir)/ylwrap \
- libknotd_la-cf-lex.c libknotd_la-cf-parse.c \
- libknotd_la-cf-parse.h zlexer.c zparser.c zparser.h
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/config.h.in knot/conf/libknotd_la-cf-lex.c \
+ knot/conf/libknotd_la-cf-parse.c \
+ knot/conf/libknotd_la-cf-parse.h
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compiler_flags.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_ext.m4 \
$(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
$(top_srcdir)/m4/ax_recvmmsg.m4 $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
- $(top_srcdir)/configure.ac
+ $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
@@ -78,164 +78,190 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libknot_la_LIBADD =
-am_libknot_la_OBJECTS = utils.lo debug.lo descriptor.lo tolower.lo \
- query.lo response.lo packet.lo zone.lo zone-contents.lo \
- zone-tree.lo zonedb.lo node.lo dname-table.lo zone-diff.lo \
- hash-functions.lo cuckoo-hash-table.lo universal-system.lo \
- name-server.lo changesets.lo xfr-in.lo ddns.lo edns.lo \
- rrset.lo dname.lo rdata.lo nsec3.lo tsig.lo tsig-op.lo
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libknot_la_OBJECTS = libknot/consts.lo libknot/util/utils.lo \
+ libknot/util/debug.lo libknot/util/tolower.lo \
+ libknot/packet/query.lo libknot/packet/response.lo \
+ libknot/packet/packet.lo libknot/zone/zone.lo \
+ libknot/zone/zone-contents.lo libknot/zone/zone-tree.lo \
+ libknot/zone/zonedb.lo libknot/zone/node.lo \
+ libknot/zone/zone-diff.lo libknot/nameserver/name-server.lo \
+ libknot/nameserver/chaos.lo libknot/updates/changesets.lo \
+ libknot/updates/xfr-in.lo libknot/updates/ddns.lo \
+ libknot/dname.lo libknot/nsec3.lo libknot/edns.lo \
+ libknot/rrset.lo libknot/rrset-dump.lo libknot/tsig.lo \
+ libknot/tsig-op.lo libknot/binary.lo libknot/sign/key.lo \
+ libknot/sign/bnutils.lo libknot/sign/dnssec.lo \
+ libknot/sign/sig0.lo
libknot_la_OBJECTS = $(am_libknot_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
libknotd_la_DEPENDENCIES = libknot.la libknots.la @LIBOBJS@
-am_libknotd_la_OBJECTS = gatherer.lo stat.lo libknotd_la-cf-parse.lo \
- libknotd_la-cf-lex.lo conf.lo logconf.lo process.lo remote.lo \
- dthreads.lo journal.lo socket.lo server.lo udp-handler.lo \
- tcp-handler.lo xfr-handler.lo zones.lo notify.lo rrl.lo \
- zone-load.lo semantic-check.lo zone-dump.lo zone-dump-text.lo
+am_libknotd_la_OBJECTS = knot/stat/gatherer.lo knot/stat/stat.lo \
+ knot/conf/libknotd_la-cf-lex.lo \
+ knot/conf/libknotd_la-cf-parse.lo knot/conf/conf.lo \
+ knot/conf/extra.lo knot/conf/includes.lo knot/conf/logconf.lo \
+ knot/ctl/process.lo knot/ctl/remote.lo knot/server/dthreads.lo \
+ knot/server/journal.lo knot/server/socket.lo \
+ knot/server/server.lo knot/server/udp-handler.lo \
+ knot/server/tcp-handler.lo knot/server/xfr-handler.lo \
+ knot/server/zones.lo knot/server/notify.lo knot/server/rrl.lo \
+ knot/zone/semantic-check.lo knot/zone/zone-dump.lo \
+ knot/zone/zone-load.lo knot/zone/estimator.lo
libknotd_la_OBJECTS = $(am_libknotd_la_OBJECTS)
-libknots_la_DEPENDENCIES = @LIBOBJS@
-am_libknots_la_OBJECTS = murmurhash3.lo slab.lo tap.lo mempattern.lo \
- lists.lo base64.lo heap.lo print.lo skip-list.lo base32hex.lo \
- general-tree.lo evqueue.lo evsched.lo acl.lo sockaddr.lo \
- ref.lo errors.lo errcode.lo dSFMT.lo prng.lo fdset.lo \
- fdset_poll.lo fdset_kqueue.lo fdset_epoll.lo log.lo
+libknots_la_DEPENDENCIES = libzscanner.la @LIBOBJS@
+am_libknots_la_OBJECTS = common/slab/slab.lo common/libtap/tap.lo \
+ common/mempattern.lo common/descriptor.lo common/lists.lo \
+ common/base64.lo common/heap.lo common/print.lo \
+ common/skip-list.lo common/base32hex.lo common/evqueue.lo \
+ common/evsched.lo common/acl.lo common/sockaddr.lo \
+ common/ref.lo common/errors.lo common/errcode.lo \
+ common/dSFMT.lo common/prng.lo common/fdset.lo \
+ common/fdset_poll.lo common/fdset_kqueue.lo \
+ common/fdset_epoll.lo common/getline.lo common/log.lo \
+ common/mempool.lo common/hattrie/ahtable.lo \
+ common/hattrie/hat-trie.lo common/hattrie/murmurhash3.lo
libknots_la_OBJECTS = $(am_libknots_la_OBJECTS)
-am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)" \
- "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"
-PROGRAMS = $(libexec_PROGRAMS) $(sbin_PROGRAMS)
-am_knot_zcompile_OBJECTS = zcompile_main.$(OBJEXT) \
- zcompile-error.$(OBJEXT) zparser.$(OBJEXT) zlexer.$(OBJEXT) \
- zcompile.$(OBJEXT) parser-util.$(OBJEXT) \
- parser-descriptor.$(OBJEXT)
-knot_zcompile_OBJECTS = $(am_knot_zcompile_OBJECTS)
-knot_zcompile_DEPENDENCIES = libknots.la libknot.la libknotd.la \
- @LIBOBJS@ $(am__empty)
-am_knotc_OBJECTS = knotc_main.$(OBJEXT)
+libzscanner_la_DEPENDENCIES = @LIBOBJS@
+am_libzscanner_la_OBJECTS = zscanner/file_loader.lo \
+ zscanner/scanner.lo zscanner/scanner_functions.lo
+libzscanner_la_OBJECTS = $(am_libzscanner_la_OBJECTS)
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"
+PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(sbin_PROGRAMS)
+am_kdig_OBJECTS = utils/common/msg.$(OBJEXT) \
+ utils/common/exec.$(OBJEXT) utils/common/params.$(OBJEXT) \
+ utils/common/resolv.$(OBJEXT) utils/common/netio.$(OBJEXT) \
+ utils/common/token.$(OBJEXT) utils/dig/dig_main.$(OBJEXT) \
+ utils/dig/dig_params.$(OBJEXT) utils/dig/dig_exec.$(OBJEXT)
+kdig_OBJECTS = $(am_kdig_OBJECTS)
+kdig_DEPENDENCIES = libknotd.la libknot.la libknots.la @LIBOBJS@
+am_khost_OBJECTS = utils/common/msg.$(OBJEXT) \
+ utils/common/exec.$(OBJEXT) utils/common/params.$(OBJEXT) \
+ utils/common/resolv.$(OBJEXT) utils/common/netio.$(OBJEXT) \
+ utils/common/token.$(OBJEXT) utils/host/host_main.$(OBJEXT) \
+ utils/dig/dig_params.$(OBJEXT) \
+ utils/host/host_params.$(OBJEXT) utils/dig/dig_exec.$(OBJEXT)
+khost_OBJECTS = $(am_khost_OBJECTS)
+khost_DEPENDENCIES = libknotd.la libknot.la libknots.la @LIBOBJS@
+am_knotc_OBJECTS = knot/ctl/knotc_main.$(OBJEXT)
knotc_OBJECTS = $(am_knotc_OBJECTS)
knotc_DEPENDENCIES = libknotd.la libknot.la libknots.la @LIBOBJS@
-am_knotd_OBJECTS = main.$(OBJEXT)
+am_knotd_OBJECTS = knot/main.$(OBJEXT)
knotd_OBJECTS = $(am_knotd_OBJECTS)
knotd_DEPENDENCIES = libknotd.la libknot.la libknots.la @LIBOBJS@
-am_unittests_OBJECTS = acl_tests.$(OBJEXT) base32hex_tests.$(OBJEXT) \
- base64_tests.$(OBJEXT) events_tests.$(OBJEXT) \
- skiplist_tests.$(OBJEXT) slab_tests.$(OBJEXT) \
- fdset_tests.$(OBJEXT) conf_tests.$(OBJEXT) \
- dthreads_tests.$(OBJEXT) journal_tests.$(OBJEXT) \
- server_tests.$(OBJEXT) rrl_tests.$(OBJEXT) \
- unittests_main.$(OBJEXT)
-nodist_unittests_OBJECTS =
-unittests_OBJECTS = $(am_unittests_OBJECTS) \
- $(nodist_unittests_OBJECTS)
-unittests_DEPENDENCIES = libknotd.la libknots.la @LIBOBJS@
-am_unittests_libknot_OBJECTS = cuckoo_tests.$(OBJEXT) \
- response_tests.$(OBJEXT) dname_tests.$(OBJEXT) \
- dname_table_tests.$(OBJEXT) nsec3_tests.$(OBJEXT) \
- packet_tests.$(OBJEXT) query_tests.$(OBJEXT) \
- edns_tests.$(OBJEXT) node_tests.$(OBJEXT) \
- rdata_tests.$(OBJEXT) rrset_tests.$(OBJEXT) \
- tsig_tests.$(OBJEXT) zone_tests.$(OBJEXT) \
- zone_tree_tests.$(OBJEXT) zonedb_tests.$(OBJEXT) \
- unittests_libknot.$(OBJEXT)
-unittests_libknot_OBJECTS = $(am_unittests_libknot_OBJECTS)
-unittests_libknot_DEPENDENCIES = libknot.la libknots.la @LIBOBJS@
-am_unittests_libknot_realdata_OBJECTS = \
- dname_tests_realdata.$(OBJEXT) \
- response_tests_realdata.$(OBJEXT) \
- edns_tests_realdata.$(OBJEXT) node_tests_realdata.$(OBJEXT) \
- rdata_tests_realdata.$(OBJEXT) rrset_tests_realdata.$(OBJEXT) \
- zone_tests_realdata.$(OBJEXT) zonedb_tests_realdata.$(OBJEXT) \
- packet_tests_realdata.$(OBJEXT) \
- libknot_tests_loader_realdata.$(OBJEXT) \
- unittests_libknot_realdata.$(OBJEXT)
-unittests_libknot_realdata_OBJECTS = \
- $(am_unittests_libknot_realdata_OBJECTS)
-unittests_libknot_realdata_DEPENDENCIES = libknot.la libknots.la \
- @LIBOBJS@ $(am__empty)
-am_unittests_xfr_OBJECTS = xfr_tests.$(OBJEXT)
-unittests_xfr_OBJECTS = $(am_unittests_xfr_OBJECTS)
-unittests_xfr_DEPENDENCIES = libknotd.la libknot.la libknots.la \
- @LIBOBJS@ $(am__empty)
-am_unittests_zcompile_OBJECTS = zcompile-error.$(OBJEXT) \
- zparser.$(OBJEXT) zlexer.$(OBJEXT) zcompile.$(OBJEXT) \
- parser-util.$(OBJEXT) parser-descriptor.$(OBJEXT) \
- unittests_zp_main.$(OBJEXT)
-unittests_zcompile_OBJECTS = $(am_unittests_zcompile_OBJECTS)
-unittests_zcompile_DEPENDENCIES = libknot.la libknots.la libknotd.la \
- @LIBOBJS@ $(am__empty)
+am_knsupdate_OBJECTS = utils/common/msg.$(OBJEXT) \
+ utils/common/params.$(OBJEXT) utils/common/resolv.$(OBJEXT) \
+ utils/common/netio.$(OBJEXT) utils/common/token.$(OBJEXT) \
+ utils/common/exec.$(OBJEXT) \
+ utils/nsupdate/nsupdate_main.$(OBJEXT) \
+ utils/nsupdate/nsupdate_params.$(OBJEXT) \
+ utils/nsupdate/nsupdate_exec.$(OBJEXT)
+knsupdate_OBJECTS = $(am_knsupdate_OBJECTS)
+knsupdate_DEPENDENCIES = libknotd.la libknot.la libknots.la \
+ libzscanner.la @LIBOBJS@
+am_zscanner_tool_OBJECTS = zscanner/test/zscanner-tool.$(OBJEXT) \
+ zscanner/test/tests.$(OBJEXT) \
+ zscanner/test/processing.$(OBJEXT)
+zscanner_tool_OBJECTS = $(am_zscanner_tool_OBJECTS)
+zscanner_tool_DEPENDENCIES = libknots.la libknot.la libknotd.la \
+ libzscanner.la @LIBOBJS@
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
-LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
CCLD = $(CC)
-LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
- $(LDFLAGS) -o $@
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS)
-LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
+LTLEXCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(LEX) $(AM_LFLAGS) $(LFLAGS)
+AM_V_LEX = $(am__v_LEX_@AM_V@)
+am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@)
+am__v_LEX_0 = @echo " LEX " $@;
YLWRAP = $(top_srcdir)/ylwrap
-am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \
- -e s/c++$$/h++/ -e s/c$$/h/
YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS)
-LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
- --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
+LTYACCCOMPILE = $(LIBTOOL) $(AM_V_lt) $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(YACC) $(AM_YFLAGS) $(YFLAGS)
+AM_V_YACC = $(am__v_YACC_@AM_V@)
+am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@)
+am__v_YACC_0 = @echo " YACC " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libknot_la_SOURCES) $(libknotd_la_SOURCES) \
- $(libknots_la_SOURCES) $(knot_zcompile_SOURCES) \
- $(knotc_SOURCES) $(knotd_SOURCES) $(unittests_SOURCES) \
- $(nodist_unittests_SOURCES) $(unittests_libknot_SOURCES) \
- $(unittests_libknot_realdata_SOURCES) $(unittests_xfr_SOURCES) \
- $(unittests_zcompile_SOURCES)
+ $(libknots_la_SOURCES) $(libzscanner_la_SOURCES) \
+ $(kdig_SOURCES) $(khost_SOURCES) $(knotc_SOURCES) \
+ $(knotd_SOURCES) $(knsupdate_SOURCES) $(zscanner_tool_SOURCES)
DIST_SOURCES = $(libknot_la_SOURCES) $(libknotd_la_SOURCES) \
- $(libknots_la_SOURCES) $(knot_zcompile_SOURCES) \
- $(knotc_SOURCES) $(knotd_SOURCES) $(unittests_SOURCES) \
- $(unittests_libknot_SOURCES) \
- $(unittests_libknot_realdata_SOURCES) $(unittests_xfr_SOURCES) \
- $(unittests_zcompile_SOURCES)
+ $(libknots_la_SOURCES) $(libzscanner_la_SOURCES) \
+ $(kdig_SOURCES) $(khost_SOURCES) $(knotc_SOURCES) \
+ $(knotd_SOURCES) $(knsupdate_SOURCES) $(zscanner_tool_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
-am__vpath_adj = case $$p in \
- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
- *) f=$$p;; \
- esac;
-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
-am__install_max = 40
-am__nobase_strip_setup = \
- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
-am__nobase_strip = \
- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
-am__nobase_list = $(am__nobase_strip_setup); \
- for p in $$list; do echo "$$p $$p"; done | \
- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
- if (++n[$$2] == $(am__install_max)) \
- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
- END { for (dir in files) print dir, files[dir] }'
-am__base_list = \
- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
-am__uninstall_files_from_dir = { \
- test -z "$$files" \
- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
- $(am__cd) "$$dir" && rm -f $$files; }; \
- }
-man5dir = $(mandir)/man5
-man8dir = $(mandir)/man8
-NROFF = nroff
-MANS = $(dist_man_MANS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
ETAGS = etags
CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
@@ -244,6 +270,7 @@ AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
+CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
@@ -258,7 +285,9 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+FSM_TYPE = @FSM_TYPE@
GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -292,6 +321,10 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RAGEL = @RAGEL@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@@ -334,8 +367,12 @@ htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
+libcrypto_CFLAGS = @libcrypto_CFLAGS@
+libcrypto_LIBS = @libcrypto_LIBS@
libdir = @libdir@
libexecdir = @libexecdir@
+liburcu_CFLAGS = @liburcu_CFLAGS@
+liburcu_LIBS = @liburcu_LIBS@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
@@ -345,177 +382,117 @@ pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+run_dir = @run_dir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
+storage_dir = @storage_dir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-ACLOCAL_AMFLAGS = -I ../m4
-dist_man_MANS = knot.conf.5 knotc.8 knotd.8
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+SUBDIRS = . tests
+noinst_LTLIBRARIES = libknot.la libknotd.la libknots.la libzscanner.la
# $(YACC) will generate header file
-AM_CFLAGS = -Wall -Ilibknot -DLIBEXECDIR='"$(libexecdir)"' -DSYSCONFDIR='"$(sysconfdir)"' -DSBINDIR='"$(sbindir)"'
+AM_CPPFLAGS = -I$(top_srcdir)/src/libknot -DSYSCONFDIR='"$(sysconfdir)"' \
+ -DSBINDIR='"$(sbindir)"' -DSTORAGE_DIR='"${storage_dir}"' \
+ -DRUN_DIR='"${run_dir}"'
+
AM_YFLAGS = -d
libknotd_la_YFLAGS = -pcf_ -d
libknotd_la_LFLAGS = # TODO: reentrant parser, prefix
-BUILT_SOURCES = \
- tests/libknot/parsed_data.rc \
- tests/libknot/realdata/parsed_data.rc \
- tests/libknot/raw_data_queries.rc \
- tests/libknot/raw_data.rc \
- tests/libknot/realdata/raw_data.rc \
- tests/libknot/parsed_data_queries.rc \
- tests/sample_conf.rc \
- zparser.h \
- zparser.c \
- zlexer.c \
- libknotd_la-cf-lex.c \
- libknotd_la-cf-parse.c \
- libknotd_la-cf-parse.h
-
-CLEANFILES = \
- tests/libknot/parsed_data.rc \
- tests/libknot/realdata/parsed_data.rc \
- tests/libknot/raw_data_queries.rc \
- tests/libknot/raw_data.rc \
- tests/libknot/realdata/raw_data.rc \
- tests/libknot/parsed_data_queries.rc \
- tests/sample_conf.rc \
- zparser.h \
- zparser.c \
- zlexer.c \
- libknotd_la-cf-lex.c \
- libknotd_la-cf-parse.c \
- libknotd_la-cf-parse.h
-
+EXTRA_DIST = \
+ zscanner/scanner.rl \
+ zscanner/scanner_body.rl \
+ zscanner/test/run_tests.sh \
+ zscanner/test/cases
+
+BUILT_SOURCES = knot/conf/libknotd_la-cf-lex.c \
+ knot/conf/libknotd_la-cf-parse.c \
+ knot/conf/libknotd_la-cf-parse.h $(am__append_1)
+CLEANFILES = knot/conf/libknotd_la-cf-lex.c \
+ knot/conf/libknotd_la-cf-parse.c \
+ knot/conf/libknotd_la-cf-parse.h $(am__append_2)
knotc_SOURCES = \
knot/ctl/knotc_main.c
-knot_zcompile_SOURCES = \
- zcompile/zcompile_main.c \
- zcompile/zcompile-error.c \
- zcompile/parser-util.h \
- zcompile/parser-descriptor.h \
- zcompile/zparser.y \
- zcompile/zlexer.l \
- zcompile/zcompile.c \
- zcompile/parser-util.c \
- zcompile/parser-descriptor.c
-
-unittests_SOURCES = \
- tests/common/acl_tests.c \
- tests/common/acl_tests.h \
- tests/common/base32hex_tests.c \
- tests/common/base32hex_tests.h \
- tests/common/base64_tests.c \
- tests/common/base64_tests.h \
- tests/common/events_tests.c \
- tests/common/events_tests.h \
- tests/common/skiplist_tests.c \
- tests/common/skiplist_tests.h \
- tests/common/slab_tests.c \
- tests/common/slab_tests.h \
- tests/common/fdset_tests.c \
- tests/common/fdset_tests.h \
- tests/knot/conf_tests.c \
- tests/knot/conf_tests.h \
- tests/knot/dthreads_tests.c \
- tests/knot/dthreads_tests.h \
- tests/knot/journal_tests.c \
- tests/knot/journal_tests.h \
- tests/knot/server_tests.c \
- tests/knot/server_tests.h \
- tests/knot/rrl_tests.c \
- tests/knot/rrl_tests.h \
- tests/unittests_main.c
-
-unittests_libknot_realdata_SOURCES = \
- tests/libknot/realdata/libknot/dname_tests_realdata.c \
- tests/libknot/realdata/libknot/response_tests_realdata.c \
- tests/libknot/realdata/libknot/edns_tests_realdata.c \
- tests/libknot/realdata/libknot/node_tests_realdata.c \
- tests/libknot/realdata/libknot/rdata_tests_realdata.c \
- tests/libknot/realdata/libknot/rrset_tests_realdata.c \
- tests/libknot/realdata/libknot/zone_tests_realdata.c \
- tests/libknot/realdata/libknot/zonedb_tests_realdata.c \
- tests/libknot/realdata/libknot/packet_tests_realdata.h \
- tests/libknot/realdata/libknot/packet_tests_realdata.c \
- tests/libknot/realdata/libknot_tests_loader_realdata.h \
- tests/libknot/realdata/libknot_tests_loader_realdata.c \
- tests/libknot/realdata/unittests_libknot_realdata.c
-
-unittests_libknot_SOURCES = \
- tests/libknot/libknot/cuckoo_tests.c \
- tests/libknot/libknot/cuckoo_tests.h \
- tests/libknot/libknot/response_tests.h \
- tests/libknot/libknot/response_tests.c \
- tests/libknot/libknot/dname_tests.c \
- tests/libknot/libknot/dname_tests.h \
- tests/libknot/libknot/dname_table_tests.h \
- tests/libknot/libknot/dname_table_tests.c \
- tests/libknot/libknot/nsec3_tests.h \
- tests/libknot/libknot/nsec3_tests.c \
- tests/libknot/libknot/packet_tests.h \
- tests/libknot/libknot/packet_tests.c \
- tests/libknot/libknot/query_tests.h \
- tests/libknot/libknot/query_tests.c \
- tests/libknot/libknot/edns_tests.c \
- tests/libknot/libknot/edns_tests.h \
- tests/libknot/libknot/node_tests.c \
- tests/libknot/libknot/node_tests.h \
- tests/libknot/libknot/rdata_tests.c \
- tests/libknot/libknot/rdata_tests.h \
- tests/libknot/libknot/rrset_tests.c \
- tests/libknot/libknot/rrset_tests.h \
- tests/libknot/libknot/tsig_tests.c \
- tests/libknot/libknot/tsig_tests.h \
- tests/libknot/libknot/zone_tests.c \
- tests/libknot/libknot/zone_tests.h \
- tests/libknot/libknot/zone_tree_tests.h \
- tests/libknot/libknot/zone_tree_tests.c \
- tests/libknot/libknot/zonedb_tests.c \
- tests/libknot/libknot/zonedb_tests.h \
- tests/libknot/unittests_libknot.c
-
-unittests_zcompile_SOURCES = \
- zcompile/parser-util.h \
- zcompile/parser-descriptor.h \
- zcompile/zcompile-error.c \
- zcompile/zparser.y \
- zcompile/zlexer.l \
- zcompile/zcompile.c \
- zcompile/parser-util.c \
- zcompile/parser-descriptor.c \
- zcompile/tests/unittests_zp_main.c
-
-unittests_xfr_SOURCES = \
- tests/xfr_tests.c \
- tests/xfr_tests.h
-
-nodist_unittests_SOURCES = \
- tests/libknot/parsed_data.rc \
- tests/libknot/raw_data_queries.rc \
- tests/libknot/raw_data.rc \
- tests/libknot/parsed_data_queries.rc \
- tests/sample_conf.rc
-
knotd_SOURCES = \
knot/main.c
-noinst_LTLIBRARIES = libknot.la libknotd.la libknots.la
+kdig_SOURCES = \
+ utils/common/msg.h \
+ utils/common/msg.c \
+ utils/common/exec.c \
+ utils/common/exec.h \
+ utils/common/params.c \
+ utils/common/params.h \
+ utils/common/resolv.c \
+ utils/common/resolv.h \
+ utils/common/netio.c \
+ utils/common/netio.h \
+ utils/common/token.c \
+ utils/common/token.h \
+ utils/dig/dig_main.c \
+ utils/dig/dig_params.c \
+ utils/dig/dig_params.h \
+ utils/dig/dig_exec.c \
+ utils/dig/dig_exec.h
+
+khost_SOURCES = \
+ utils/common/msg.h \
+ utils/common/msg.c \
+ utils/common/exec.c \
+ utils/common/exec.h \
+ utils/common/params.c \
+ utils/common/params.h \
+ utils/common/resolv.c \
+ utils/common/resolv.h \
+ utils/common/netio.c \
+ utils/common/netio.h \
+ utils/common/token.c \
+ utils/common/token.h \
+ utils/host/host_main.c \
+ utils/dig/dig_params.c \
+ utils/dig/dig_params.h \
+ utils/host/host_params.c \
+ utils/host/host_params.h \
+ utils/dig/dig_exec.c \
+ utils/dig/dig_exec.h
+
+knsupdate_SOURCES = \
+ utils/common/msg.h \
+ utils/common/msg.c \
+ utils/common/params.c \
+ utils/common/params.h \
+ utils/common/resolv.c \
+ utils/common/resolv.h \
+ utils/common/netio.c \
+ utils/common/netio.h \
+ utils/common/token.c \
+ utils/common/token.h \
+ utils/common/exec.c \
+ utils/common/exec.h \
+ utils/nsupdate/nsupdate_main.c \
+ utils/nsupdate/nsupdate_params.h \
+ utils/nsupdate/nsupdate_params.c \
+ utils/nsupdate/nsupdate_exec.h \
+ utils/nsupdate/nsupdate_exec.c
+
libknot_la_SOURCES = \
+ libknot/common.h \
+ libknot/consts.h \
+ libknot/consts.c \
libknot/util/utils.c \
libknot/util/debug.c \
libknot/util/debug.h \
libknot/util/utils.h \
- libknot/util/descriptor.c \
libknot/util/tolower.h \
libknot/util/tolower.c \
- libknot/util/descriptor.h \
libknot/util/wire.h \
+ libknot/util/endian.h \
libknot/packet/query.c \
libknot/packet/response.c \
libknot/packet/packet.c \
@@ -532,51 +509,57 @@ libknot_la_SOURCES = \
libknot/zone/zonedb.c \
libknot/zone/zonedb.h \
libknot/zone/node.c \
- libknot/zone/dname-table.h \
- libknot/zone/dname-table.c \
libknot/zone/zone-diff.h \
libknot/zone/zone-diff.c \
- libknot/hash/hash-functions.c \
- libknot/hash/cuckoo-hash-table.c \
- libknot/hash/universal-system.c \
- libknot/hash/universal-system.h \
- libknot/hash/cuckoo-hash-table.h \
- libknot/hash/hash-functions.h \
libknot/nameserver/name-server.h \
libknot/nameserver/name-server.c \
+ libknot/nameserver/chaos.h \
+ libknot/nameserver/chaos.c \
libknot/updates/changesets.h \
libknot/updates/changesets.c \
libknot/updates/xfr-in.h \
libknot/updates/xfr-in.c \
libknot/updates/ddns.h \
libknot/updates/ddns.c \
- libknot/edns.c \
- libknot/rrset.c \
libknot/dname.c \
- libknot/rdata.c \
libknot/nsec3.c \
libknot/consts.h \
libknot/edns.h \
- libknot/rdata.h \
+ libknot/edns.c \
libknot/libknot.h \
libknot/dname.h \
libknot/rrset.h \
+ libknot/rrset.c \
libknot/nsec3.h \
+ libknot/rrset-dump.h \
+ libknot/rrset-dump.c \
libknot/tsig.h \
libknot/tsig.c \
libknot/tsig-op.h \
- libknot/tsig-op.c
+ libknot/tsig-op.c \
+ libknot/binary.h \
+ libknot/binary.c \
+ libknot/sign/key.h \
+ libknot/sign/key.c \
+ libknot/sign/bnutils.h \
+ libknot/sign/bnutils.c \
+ libknot/sign/dnssec.h \
+ libknot/sign/dnssec.c \
+ libknot/sign/sig0.h \
+ libknot/sign/sig0.c
libknots_la_SOURCES = \
- common/hattrie/murmurhash3.c \
- common/hattrie/murmurhash3.h \
common/slab/slab.c \
common/slab/slab.h \
+ common/slab/alloc-common.h \
common/libtap/tap.c \
common/libtap/tap.h \
common/libtap/tap_unit.h \
+ common/atomic.h \
common/mempattern.h \
common/mempattern.c \
+ common/descriptor.h \
+ common/descriptor.c \
common/lists.c \
common/base64.c \
common/base64.h \
@@ -588,9 +571,6 @@ libknots_la_SOURCES = \
common/skip-list.c \
common/base32hex.c \
common/skip-list.h \
- common/general-tree.h \
- common/general-tree.c \
- common/tree.h \
common/base32hex.h \
common/evqueue.h \
common/evqueue.c \
@@ -607,82 +587,111 @@ libknots_la_SOURCES = \
common/errors.c \
common/errcode.h \
common/errcode.c \
- common/dSFMT.h \
- common/dSFMT-params.h \
- common/dSFMT-params521.h \
- common/dSFMT.c \
- common/prng.h \
- common/prng.c \
- common/fdset.h \
- common/fdset.c \
- common/fdset_poll.h \
- common/fdset_poll.c \
- common/fdset_kqueue.h \
- common/fdset_kqueue.c \
- common/fdset_epoll.h \
- common/fdset_epoll.c \
+ common/dSFMT.h \
+ common/dSFMT-params.h \
+ common/dSFMT-params521.h \
+ common/dSFMT.c \
+ common/prng.h \
+ common/prng.c \
+ common/fdset.h \
+ common/fdset.c \
+ common/fdset_poll.h \
+ common/fdset_poll.c \
+ common/fdset_kqueue.h \
+ common/fdset_kqueue.c \
+ common/fdset_epoll.h \
+ common/fdset_epoll.c \
+ common/getline.h \
+ common/getline.c \
common/log.c \
- common/log.h
+ common/log.h \
+ common/mempool.c \
+ common/mempool.h \
+ common/hattrie/ahtable.c \
+ common/hattrie/ahtable.h \
+ common/hattrie/hat-trie.c \
+ common/hattrie/hat-trie.h \
+ common/hattrie/murmurhash3.c \
+ common/hattrie/murmurhash3.h
libknotd_la_SOURCES = \
- knot/stat/gatherer.c \
- knot/stat/stat.c \
- knot/stat/gatherer.h \
- knot/stat/stat.h \
- knot/common.h \
+ knot/stat/gatherer.c \
+ knot/stat/stat.c \
+ knot/stat/gatherer.h \
+ knot/stat/stat.h \
+ knot/stat/stat-common.h \
+ knot/knot.h \
knot/other/debug.h \
- knot/conf/cf-parse.y \
knot/conf/cf-lex.l \
+ knot/conf/cf-parse.y \
knot/conf/conf.c \
+ knot/conf/conf.h \
+ knot/conf/extra.c \
+ knot/conf/extra.h \
+ knot/conf/includes.c \
+ knot/conf/includes.h \
knot/conf/logconf.c \
knot/conf/logconf.h \
- knot/conf/conf.h \
knot/ctl/process.c \
knot/ctl/process.h \
knot/ctl/remote.c \
knot/ctl/remote.h \
knot/server/dthreads.c \
knot/server/journal.c \
- knot/server/socket.c \
- knot/server/server.c \
- knot/server/udp-handler.c \
- knot/server/tcp-handler.c \
- knot/server/xfr-handler.c \
- knot/server/zones.c \
- knot/server/socket.h \
- knot/server/udp-handler.h \
- knot/server/tcp-handler.h \
- knot/server/xfr-handler.h \
+ knot/server/socket.c \
+ knot/server/server.c \
+ knot/server/udp-handler.c \
+ knot/server/tcp-handler.c \
+ knot/server/xfr-handler.c \
+ knot/server/zones.c \
+ knot/server/socket.h \
+ knot/server/udp-handler.h \
+ knot/server/tcp-handler.h \
+ knot/server/xfr-handler.h \
knot/server/dthreads.h \
knot/server/journal.h \
- knot/server/zones.h \
- knot/server/notify.h \
- knot/server/notify.c \
- knot/server/zones.h \
- knot/server/rrl.c \
+ knot/server/zones.h \
+ knot/server/notify.h \
+ knot/server/notify.c \
+ knot/server/zones.h \
knot/server/rrl.h \
- knot/zone/zone-load.c \
- knot/zone/zone-load.h \
+ knot/server/rrl.c \
knot/zone/semantic-check.c \
knot/zone/semantic-check.h \
- knot/zone/zone-dump.c \
- knot/zone/zone-dump-text.c \
- knot/zone/zone-dump-text.h \
knot/zone/zone-dump.h \
+ knot/zone/zone-dump.c \
+ knot/zone/zone-load.h \
+ knot/zone/zone-load.c \
+ knot/zone/estimator.h \
+ knot/zone/estimator.c \
knot/server/server.h
+zscanner_tool_SOURCES = \
+ zscanner/test/zscanner-tool.c \
+ zscanner/test/tests.h \
+ zscanner/test/tests.c \
+ zscanner/test/processing.h \
+ zscanner/test/processing.c
+
+libzscanner_la_SOURCES = \
+ zscanner/file_loader.h \
+ zscanner/file_loader.c \
+ zscanner/scanner.h \
+ zscanner/scanner.c \
+ zscanner/scanner_functions.h \
+ zscanner/scanner_functions.c
+
libknotd_la_LIBADD = libknot.la libknots.la @LIBOBJS@
-libknots_la_LIBADD = @LIBOBJS@
+libknots_la_LIBADD = libzscanner.la @LIBOBJS@
+libzscanner_la_LIBADD = @LIBOBJS@
knotd_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
knotc_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
-knot_zcompile_LDADD = libknots.la libknot.la libknotd.la @LIBOBJS@
-unittests_LDADD = libknotd.la libknots.la @LIBOBJS@
-unittests_zcompile_LDADD = libknot.la libknots.la libknotd.la @LIBOBJS@
-unittests_libknot_LDADD = libknot.la libknots.la @LIBOBJS@
-unittests_libknot_realdata_LDADD = libknot.la libknots.la @LIBOBJS@
-unittests_xfr_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
+kdig_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
+khost_LDADD = libknotd.la libknot.la libknots.la @LIBOBJS@
+knsupdate_LDADD = libknotd.la libknot.la libknots.la libzscanner.la @LIBOBJS@
+zscanner_tool_LDADD = libknots.la libknot.la libknotd.la libzscanner.la @LIBOBJS@
all: $(BUILT_SOURCES) config.h
- $(MAKE) $(AM_MAKEFLAGS) all-am
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
.SUFFIXES: .c .l .lo .o .obj .y
@@ -695,9 +704,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
exit 1;; \
esac; \
done; \
- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/Makefile'; \
$(am__cd) $(top_srcdir) && \
- $(AUTOMAKE) --gnu src/Makefile
+ $(AUTOMAKE) --gnits src/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
@@ -734,29 +743,300 @@ distclean-hdr:
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
- @list='$(noinst_LTLIBRARIES)'; \
- locs=`for p in $$list; do echo $$p; done | \
- sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
- sort -u`; \
- test -z "$$locs" || { \
- echo rm -f $${locs}; \
- rm -f $${locs}; \
- }
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libknot/$(am__dirstamp):
+ @$(MKDIR_P) libknot
+ @: > libknot/$(am__dirstamp)
+libknot/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/$(DEPDIR)
+ @: > libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/consts.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/util/$(am__dirstamp):
+ @$(MKDIR_P) libknot/util
+ @: > libknot/util/$(am__dirstamp)
+libknot/util/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/util/$(DEPDIR)
+ @: > libknot/util/$(DEPDIR)/$(am__dirstamp)
+libknot/util/utils.lo: libknot/util/$(am__dirstamp) \
+ libknot/util/$(DEPDIR)/$(am__dirstamp)
+libknot/util/debug.lo: libknot/util/$(am__dirstamp) \
+ libknot/util/$(DEPDIR)/$(am__dirstamp)
+libknot/util/tolower.lo: libknot/util/$(am__dirstamp) \
+ libknot/util/$(DEPDIR)/$(am__dirstamp)
+libknot/packet/$(am__dirstamp):
+ @$(MKDIR_P) libknot/packet
+ @: > libknot/packet/$(am__dirstamp)
+libknot/packet/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/packet/$(DEPDIR)
+ @: > libknot/packet/$(DEPDIR)/$(am__dirstamp)
+libknot/packet/query.lo: libknot/packet/$(am__dirstamp) \
+ libknot/packet/$(DEPDIR)/$(am__dirstamp)
+libknot/packet/response.lo: libknot/packet/$(am__dirstamp) \
+ libknot/packet/$(DEPDIR)/$(am__dirstamp)
+libknot/packet/packet.lo: libknot/packet/$(am__dirstamp) \
+ libknot/packet/$(DEPDIR)/$(am__dirstamp)
+libknot/zone/$(am__dirstamp):
+ @$(MKDIR_P) libknot/zone
+ @: > libknot/zone/$(am__dirstamp)
+libknot/zone/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/zone/$(DEPDIR)
+ @: > libknot/zone/$(DEPDIR)/$(am__dirstamp)
+libknot/zone/zone.lo: libknot/zone/$(am__dirstamp) \
+ libknot/zone/$(DEPDIR)/$(am__dirstamp)
+libknot/zone/zone-contents.lo: libknot/zone/$(am__dirstamp) \
+ libknot/zone/$(DEPDIR)/$(am__dirstamp)
+libknot/zone/zone-tree.lo: libknot/zone/$(am__dirstamp) \
+ libknot/zone/$(DEPDIR)/$(am__dirstamp)
+libknot/zone/zonedb.lo: libknot/zone/$(am__dirstamp) \
+ libknot/zone/$(DEPDIR)/$(am__dirstamp)
+libknot/zone/node.lo: libknot/zone/$(am__dirstamp) \
+ libknot/zone/$(DEPDIR)/$(am__dirstamp)
+libknot/zone/zone-diff.lo: libknot/zone/$(am__dirstamp) \
+ libknot/zone/$(DEPDIR)/$(am__dirstamp)
+libknot/nameserver/$(am__dirstamp):
+ @$(MKDIR_P) libknot/nameserver
+ @: > libknot/nameserver/$(am__dirstamp)
+libknot/nameserver/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/nameserver/$(DEPDIR)
+ @: > libknot/nameserver/$(DEPDIR)/$(am__dirstamp)
+libknot/nameserver/name-server.lo: libknot/nameserver/$(am__dirstamp) \
+ libknot/nameserver/$(DEPDIR)/$(am__dirstamp)
+libknot/nameserver/chaos.lo: libknot/nameserver/$(am__dirstamp) \
+ libknot/nameserver/$(DEPDIR)/$(am__dirstamp)
+libknot/updates/$(am__dirstamp):
+ @$(MKDIR_P) libknot/updates
+ @: > libknot/updates/$(am__dirstamp)
+libknot/updates/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/updates/$(DEPDIR)
+ @: > libknot/updates/$(DEPDIR)/$(am__dirstamp)
+libknot/updates/changesets.lo: libknot/updates/$(am__dirstamp) \
+ libknot/updates/$(DEPDIR)/$(am__dirstamp)
+libknot/updates/xfr-in.lo: libknot/updates/$(am__dirstamp) \
+ libknot/updates/$(DEPDIR)/$(am__dirstamp)
+libknot/updates/ddns.lo: libknot/updates/$(am__dirstamp) \
+ libknot/updates/$(DEPDIR)/$(am__dirstamp)
+libknot/dname.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/nsec3.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/edns.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/rrset.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/rrset-dump.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/tsig.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/tsig-op.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/binary.lo: libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/sign/$(am__dirstamp):
+ @$(MKDIR_P) libknot/sign
+ @: > libknot/sign/$(am__dirstamp)
+libknot/sign/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/sign/$(DEPDIR)
+ @: > libknot/sign/$(DEPDIR)/$(am__dirstamp)
+libknot/sign/key.lo: libknot/sign/$(am__dirstamp) \
+ libknot/sign/$(DEPDIR)/$(am__dirstamp)
+libknot/sign/bnutils.lo: libknot/sign/$(am__dirstamp) \
+ libknot/sign/$(DEPDIR)/$(am__dirstamp)
+libknot/sign/dnssec.lo: libknot/sign/$(am__dirstamp) \
+ libknot/sign/$(DEPDIR)/$(am__dirstamp)
+libknot/sign/sig0.lo: libknot/sign/$(am__dirstamp) \
+ libknot/sign/$(DEPDIR)/$(am__dirstamp)
libknot.la: $(libknot_la_OBJECTS) $(libknot_la_DEPENDENCIES) $(EXTRA_libknot_la_DEPENDENCIES)
- $(LINK) $(libknot_la_OBJECTS) $(libknot_la_LIBADD) $(LIBS)
-libknotd_la-cf-parse.h: libknotd_la-cf-parse.c
- @if test ! -f $@; then rm -f libknotd_la-cf-parse.c; else :; fi
- @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) libknotd_la-cf-parse.c; else :; fi
+ $(AM_V_CCLD)$(LINK) $(libknot_la_OBJECTS) $(libknot_la_LIBADD) $(LIBS)
+knot/stat/$(am__dirstamp):
+ @$(MKDIR_P) knot/stat
+ @: > knot/stat/$(am__dirstamp)
+knot/stat/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) knot/stat/$(DEPDIR)
+ @: > knot/stat/$(DEPDIR)/$(am__dirstamp)
+knot/stat/gatherer.lo: knot/stat/$(am__dirstamp) \
+ knot/stat/$(DEPDIR)/$(am__dirstamp)
+knot/stat/stat.lo: knot/stat/$(am__dirstamp) \
+ knot/stat/$(DEPDIR)/$(am__dirstamp)
+knot/conf/$(am__dirstamp):
+ @$(MKDIR_P) knot/conf
+ @: > knot/conf/$(am__dirstamp)
+knot/conf/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) knot/conf/$(DEPDIR)
+ @: > knot/conf/$(DEPDIR)/$(am__dirstamp)
+knot/conf/libknotd_la-cf-lex.lo: knot/conf/$(am__dirstamp) \
+ knot/conf/$(DEPDIR)/$(am__dirstamp)
+knot/conf/libknotd_la-cf-parse.h: knot/conf/libknotd_la-cf-parse.c
+ @if test ! -f $@; then rm -f knot/conf/libknotd_la-cf-parse.c; else :; fi
+ @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) knot/conf/libknotd_la-cf-parse.c; else :; fi
+knot/conf/libknotd_la-cf-parse.lo: knot/conf/$(am__dirstamp) \
+ knot/conf/$(DEPDIR)/$(am__dirstamp)
+knot/conf/conf.lo: knot/conf/$(am__dirstamp) \
+ knot/conf/$(DEPDIR)/$(am__dirstamp)
+knot/conf/extra.lo: knot/conf/$(am__dirstamp) \
+ knot/conf/$(DEPDIR)/$(am__dirstamp)
+knot/conf/includes.lo: knot/conf/$(am__dirstamp) \
+ knot/conf/$(DEPDIR)/$(am__dirstamp)
+knot/conf/logconf.lo: knot/conf/$(am__dirstamp) \
+ knot/conf/$(DEPDIR)/$(am__dirstamp)
+knot/ctl/$(am__dirstamp):
+ @$(MKDIR_P) knot/ctl
+ @: > knot/ctl/$(am__dirstamp)
+knot/ctl/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) knot/ctl/$(DEPDIR)
+ @: > knot/ctl/$(DEPDIR)/$(am__dirstamp)
+knot/ctl/process.lo: knot/ctl/$(am__dirstamp) \
+ knot/ctl/$(DEPDIR)/$(am__dirstamp)
+knot/ctl/remote.lo: knot/ctl/$(am__dirstamp) \
+ knot/ctl/$(DEPDIR)/$(am__dirstamp)
+knot/server/$(am__dirstamp):
+ @$(MKDIR_P) knot/server
+ @: > knot/server/$(am__dirstamp)
+knot/server/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) knot/server/$(DEPDIR)
+ @: > knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/dthreads.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/journal.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/socket.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/server.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/udp-handler.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/tcp-handler.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/xfr-handler.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/zones.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/notify.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/server/rrl.lo: knot/server/$(am__dirstamp) \
+ knot/server/$(DEPDIR)/$(am__dirstamp)
+knot/zone/$(am__dirstamp):
+ @$(MKDIR_P) knot/zone
+ @: > knot/zone/$(am__dirstamp)
+knot/zone/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) knot/zone/$(DEPDIR)
+ @: > knot/zone/$(DEPDIR)/$(am__dirstamp)
+knot/zone/semantic-check.lo: knot/zone/$(am__dirstamp) \
+ knot/zone/$(DEPDIR)/$(am__dirstamp)
+knot/zone/zone-dump.lo: knot/zone/$(am__dirstamp) \
+ knot/zone/$(DEPDIR)/$(am__dirstamp)
+knot/zone/zone-load.lo: knot/zone/$(am__dirstamp) \
+ knot/zone/$(DEPDIR)/$(am__dirstamp)
+knot/zone/estimator.lo: knot/zone/$(am__dirstamp) \
+ knot/zone/$(DEPDIR)/$(am__dirstamp)
libknotd.la: $(libknotd_la_OBJECTS) $(libknotd_la_DEPENDENCIES) $(EXTRA_libknotd_la_DEPENDENCIES)
- $(LINK) $(libknotd_la_OBJECTS) $(libknotd_la_LIBADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(libknotd_la_OBJECTS) $(libknotd_la_LIBADD) $(LIBS)
+common/slab/$(am__dirstamp):
+ @$(MKDIR_P) common/slab
+ @: > common/slab/$(am__dirstamp)
+common/slab/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) common/slab/$(DEPDIR)
+ @: > common/slab/$(DEPDIR)/$(am__dirstamp)
+common/slab/slab.lo: common/slab/$(am__dirstamp) \
+ common/slab/$(DEPDIR)/$(am__dirstamp)
+common/libtap/$(am__dirstamp):
+ @$(MKDIR_P) common/libtap
+ @: > common/libtap/$(am__dirstamp)
+common/libtap/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) common/libtap/$(DEPDIR)
+ @: > common/libtap/$(DEPDIR)/$(am__dirstamp)
+common/libtap/tap.lo: common/libtap/$(am__dirstamp) \
+ common/libtap/$(DEPDIR)/$(am__dirstamp)
+common/$(am__dirstamp):
+ @$(MKDIR_P) common
+ @: > common/$(am__dirstamp)
+common/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) common/$(DEPDIR)
+ @: > common/$(DEPDIR)/$(am__dirstamp)
+common/mempattern.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/descriptor.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/lists.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/base64.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/heap.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/print.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/skip-list.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/base32hex.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/evqueue.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/evsched.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/acl.lo: common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp)
+common/sockaddr.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/ref.lo: common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp)
+common/errors.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/errcode.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/dSFMT.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/prng.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/fdset.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/fdset_poll.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/fdset_kqueue.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/fdset_epoll.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/getline.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/log.lo: common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp)
+common/mempool.lo: common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/hattrie/$(am__dirstamp):
+ @$(MKDIR_P) common/hattrie
+ @: > common/hattrie/$(am__dirstamp)
+common/hattrie/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) common/hattrie/$(DEPDIR)
+ @: > common/hattrie/$(DEPDIR)/$(am__dirstamp)
+common/hattrie/ahtable.lo: common/hattrie/$(am__dirstamp) \
+ common/hattrie/$(DEPDIR)/$(am__dirstamp)
+common/hattrie/hat-trie.lo: common/hattrie/$(am__dirstamp) \
+ common/hattrie/$(DEPDIR)/$(am__dirstamp)
+common/hattrie/murmurhash3.lo: common/hattrie/$(am__dirstamp) \
+ common/hattrie/$(DEPDIR)/$(am__dirstamp)
libknots.la: $(libknots_la_OBJECTS) $(libknots_la_DEPENDENCIES) $(EXTRA_libknots_la_DEPENDENCIES)
- $(LINK) $(libknots_la_OBJECTS) $(libknots_la_LIBADD) $(LIBS)
-install-libexecPROGRAMS: $(libexec_PROGRAMS)
+ $(AM_V_CCLD)$(LINK) $(libknots_la_OBJECTS) $(libknots_la_LIBADD) $(LIBS)
+zscanner/$(am__dirstamp):
+ @$(MKDIR_P) zscanner
+ @: > zscanner/$(am__dirstamp)
+zscanner/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) zscanner/$(DEPDIR)
+ @: > zscanner/$(DEPDIR)/$(am__dirstamp)
+zscanner/file_loader.lo: zscanner/$(am__dirstamp) \
+ zscanner/$(DEPDIR)/$(am__dirstamp)
+zscanner/scanner.lo: zscanner/$(am__dirstamp) \
+ zscanner/$(DEPDIR)/$(am__dirstamp)
+zscanner/scanner_functions.lo: zscanner/$(am__dirstamp) \
+ zscanner/$(DEPDIR)/$(am__dirstamp)
+libzscanner.la: $(libzscanner_la_OBJECTS) $(libzscanner_la_DEPENDENCIES) $(EXTRA_libzscanner_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libzscanner_la_OBJECTS) $(libzscanner_la_LIBADD) $(LIBS)
+install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
- @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
@@ -774,23 +1054,48 @@ install-libexecPROGRAMS: $(libexec_PROGRAMS)
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
- echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \
- $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
-uninstall-libexecPROGRAMS:
+uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
- @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
- echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(libexecdir)" && rm -f $$files
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
-clean-libexecPROGRAMS:
- @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+installcheck-binPROGRAMS: $(bin_PROGRAMS)
+ bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
+ case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
+ *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
+ esac; \
+ f=`echo "$$p" | \
+ sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ for opt in --help --version; do \
+ if "$(DESTDIR)$(bindir)/$$f" $$opt >c$${pid}_.out \
+ 2>c$${pid}_.err </dev/null \
+ && test -n "`cat c$${pid}_.out`" \
+ && test -z "`cat c$${pid}_.err`"; then :; \
+ else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
+ done; \
+ done; rm -f c$${pid}_.???; exit $$bad
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
@@ -843,1502 +1148,553 @@ clean-sbinPROGRAMS:
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
-zparser.h: zparser.c
- @if test ! -f $@; then rm -f zparser.c; else :; fi
- @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) zparser.c; else :; fi
-knot-zcompile$(EXEEXT): $(knot_zcompile_OBJECTS) $(knot_zcompile_DEPENDENCIES) $(EXTRA_knot_zcompile_DEPENDENCIES)
- @rm -f knot-zcompile$(EXEEXT)
- $(LINK) $(knot_zcompile_OBJECTS) $(knot_zcompile_LDADD) $(LIBS)
+
+installcheck-sbinPROGRAMS: $(sbin_PROGRAMS)
+ bad=0; pid=$$$$; list="$(sbin_PROGRAMS)"; for p in $$list; do \
+ case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
+ *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
+ esac; \
+ f=`echo "$$p" | \
+ sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ for opt in --help --version; do \
+ if "$(DESTDIR)$(sbindir)/$$f" $$opt >c$${pid}_.out \
+ 2>c$${pid}_.err </dev/null \
+ && test -n "`cat c$${pid}_.out`" \
+ && test -z "`cat c$${pid}_.err`"; then :; \
+ else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
+ done; \
+ done; rm -f c$${pid}_.???; exit $$bad
+utils/common/$(am__dirstamp):
+ @$(MKDIR_P) utils/common
+ @: > utils/common/$(am__dirstamp)
+utils/common/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) utils/common/$(DEPDIR)
+ @: > utils/common/$(DEPDIR)/$(am__dirstamp)
+utils/common/msg.$(OBJEXT): utils/common/$(am__dirstamp) \
+ utils/common/$(DEPDIR)/$(am__dirstamp)
+utils/common/exec.$(OBJEXT): utils/common/$(am__dirstamp) \
+ utils/common/$(DEPDIR)/$(am__dirstamp)
+utils/common/params.$(OBJEXT): utils/common/$(am__dirstamp) \
+ utils/common/$(DEPDIR)/$(am__dirstamp)
+utils/common/resolv.$(OBJEXT): utils/common/$(am__dirstamp) \
+ utils/common/$(DEPDIR)/$(am__dirstamp)
+utils/common/netio.$(OBJEXT): utils/common/$(am__dirstamp) \
+ utils/common/$(DEPDIR)/$(am__dirstamp)
+utils/common/token.$(OBJEXT): utils/common/$(am__dirstamp) \
+ utils/common/$(DEPDIR)/$(am__dirstamp)
+utils/dig/$(am__dirstamp):
+ @$(MKDIR_P) utils/dig
+ @: > utils/dig/$(am__dirstamp)
+utils/dig/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) utils/dig/$(DEPDIR)
+ @: > utils/dig/$(DEPDIR)/$(am__dirstamp)
+utils/dig/dig_main.$(OBJEXT): utils/dig/$(am__dirstamp) \
+ utils/dig/$(DEPDIR)/$(am__dirstamp)
+utils/dig/dig_params.$(OBJEXT): utils/dig/$(am__dirstamp) \
+ utils/dig/$(DEPDIR)/$(am__dirstamp)
+utils/dig/dig_exec.$(OBJEXT): utils/dig/$(am__dirstamp) \
+ utils/dig/$(DEPDIR)/$(am__dirstamp)
+kdig$(EXEEXT): $(kdig_OBJECTS) $(kdig_DEPENDENCIES) $(EXTRA_kdig_DEPENDENCIES)
+ @rm -f kdig$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(kdig_OBJECTS) $(kdig_LDADD) $(LIBS)
+utils/host/$(am__dirstamp):
+ @$(MKDIR_P) utils/host
+ @: > utils/host/$(am__dirstamp)
+utils/host/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) utils/host/$(DEPDIR)
+ @: > utils/host/$(DEPDIR)/$(am__dirstamp)
+utils/host/host_main.$(OBJEXT): utils/host/$(am__dirstamp) \
+ utils/host/$(DEPDIR)/$(am__dirstamp)
+utils/host/host_params.$(OBJEXT): utils/host/$(am__dirstamp) \
+ utils/host/$(DEPDIR)/$(am__dirstamp)
+khost$(EXEEXT): $(khost_OBJECTS) $(khost_DEPENDENCIES) $(EXTRA_khost_DEPENDENCIES)
+ @rm -f khost$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(khost_OBJECTS) $(khost_LDADD) $(LIBS)
+knot/ctl/knotc_main.$(OBJEXT): knot/ctl/$(am__dirstamp) \
+ knot/ctl/$(DEPDIR)/$(am__dirstamp)
knotc$(EXEEXT): $(knotc_OBJECTS) $(knotc_DEPENDENCIES) $(EXTRA_knotc_DEPENDENCIES)
@rm -f knotc$(EXEEXT)
- $(LINK) $(knotc_OBJECTS) $(knotc_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(knotc_OBJECTS) $(knotc_LDADD) $(LIBS)
+knot/$(am__dirstamp):
+ @$(MKDIR_P) knot
+ @: > knot/$(am__dirstamp)
+knot/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) knot/$(DEPDIR)
+ @: > knot/$(DEPDIR)/$(am__dirstamp)
+knot/main.$(OBJEXT): knot/$(am__dirstamp) \
+ knot/$(DEPDIR)/$(am__dirstamp)
knotd$(EXEEXT): $(knotd_OBJECTS) $(knotd_DEPENDENCIES) $(EXTRA_knotd_DEPENDENCIES)
@rm -f knotd$(EXEEXT)
- $(LINK) $(knotd_OBJECTS) $(knotd_LDADD) $(LIBS)
-unittests$(EXEEXT): $(unittests_OBJECTS) $(unittests_DEPENDENCIES) $(EXTRA_unittests_DEPENDENCIES)
- @rm -f unittests$(EXEEXT)
- $(LINK) $(unittests_OBJECTS) $(unittests_LDADD) $(LIBS)
-unittests-libknot$(EXEEXT): $(unittests_libknot_OBJECTS) $(unittests_libknot_DEPENDENCIES) $(EXTRA_unittests_libknot_DEPENDENCIES)
- @rm -f unittests-libknot$(EXEEXT)
- $(LINK) $(unittests_libknot_OBJECTS) $(unittests_libknot_LDADD) $(LIBS)
-unittests-libknot-realdata$(EXEEXT): $(unittests_libknot_realdata_OBJECTS) $(unittests_libknot_realdata_DEPENDENCIES) $(EXTRA_unittests_libknot_realdata_DEPENDENCIES)
- @rm -f unittests-libknot-realdata$(EXEEXT)
- $(LINK) $(unittests_libknot_realdata_OBJECTS) $(unittests_libknot_realdata_LDADD) $(LIBS)
-unittests-xfr$(EXEEXT): $(unittests_xfr_OBJECTS) $(unittests_xfr_DEPENDENCIES) $(EXTRA_unittests_xfr_DEPENDENCIES)
- @rm -f unittests-xfr$(EXEEXT)
- $(LINK) $(unittests_xfr_OBJECTS) $(unittests_xfr_LDADD) $(LIBS)
-unittests-zcompile$(EXEEXT): $(unittests_zcompile_OBJECTS) $(unittests_zcompile_DEPENDENCIES) $(EXTRA_unittests_zcompile_DEPENDENCIES)
- @rm -f unittests-zcompile$(EXEEXT)
- $(LINK) $(unittests_zcompile_OBJECTS) $(unittests_zcompile_LDADD) $(LIBS)
+ $(AM_V_CCLD)$(LINK) $(knotd_OBJECTS) $(knotd_LDADD) $(LIBS)
+utils/nsupdate/$(am__dirstamp):
+ @$(MKDIR_P) utils/nsupdate
+ @: > utils/nsupdate/$(am__dirstamp)
+utils/nsupdate/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) utils/nsupdate/$(DEPDIR)
+ @: > utils/nsupdate/$(DEPDIR)/$(am__dirstamp)
+utils/nsupdate/nsupdate_main.$(OBJEXT): \
+ utils/nsupdate/$(am__dirstamp) \
+ utils/nsupdate/$(DEPDIR)/$(am__dirstamp)
+utils/nsupdate/nsupdate_params.$(OBJEXT): \
+ utils/nsupdate/$(am__dirstamp) \
+ utils/nsupdate/$(DEPDIR)/$(am__dirstamp)
+utils/nsupdate/nsupdate_exec.$(OBJEXT): \
+ utils/nsupdate/$(am__dirstamp) \
+ utils/nsupdate/$(DEPDIR)/$(am__dirstamp)
+knsupdate$(EXEEXT): $(knsupdate_OBJECTS) $(knsupdate_DEPENDENCIES) $(EXTRA_knsupdate_DEPENDENCIES)
+ @rm -f knsupdate$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(knsupdate_OBJECTS) $(knsupdate_LDADD) $(LIBS)
+zscanner/test/$(am__dirstamp):
+ @$(MKDIR_P) zscanner/test
+ @: > zscanner/test/$(am__dirstamp)
+zscanner/test/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) zscanner/test/$(DEPDIR)
+ @: > zscanner/test/$(DEPDIR)/$(am__dirstamp)
+zscanner/test/zscanner-tool.$(OBJEXT): zscanner/test/$(am__dirstamp) \
+ zscanner/test/$(DEPDIR)/$(am__dirstamp)
+zscanner/test/tests.$(OBJEXT): zscanner/test/$(am__dirstamp) \
+ zscanner/test/$(DEPDIR)/$(am__dirstamp)
+zscanner/test/processing.$(OBJEXT): zscanner/test/$(am__dirstamp) \
+ zscanner/test/$(DEPDIR)/$(am__dirstamp)
+zscanner-tool$(EXEEXT): $(zscanner_tool_OBJECTS) $(zscanner_tool_DEPENDENCIES) $(EXTRA_zscanner_tool_DEPENDENCIES)
+ @rm -f zscanner-tool$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(zscanner_tool_OBJECTS) $(zscanner_tool_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
+ -rm -f common/acl.$(OBJEXT)
+ -rm -f common/acl.lo
+ -rm -f common/base32hex.$(OBJEXT)
+ -rm -f common/base32hex.lo
+ -rm -f common/base64.$(OBJEXT)
+ -rm -f common/base64.lo
+ -rm -f common/dSFMT.$(OBJEXT)
+ -rm -f common/dSFMT.lo
+ -rm -f common/descriptor.$(OBJEXT)
+ -rm -f common/descriptor.lo
+ -rm -f common/errcode.$(OBJEXT)
+ -rm -f common/errcode.lo
+ -rm -f common/errors.$(OBJEXT)
+ -rm -f common/errors.lo
+ -rm -f common/evqueue.$(OBJEXT)
+ -rm -f common/evqueue.lo
+ -rm -f common/evsched.$(OBJEXT)
+ -rm -f common/evsched.lo
+ -rm -f common/fdset.$(OBJEXT)
+ -rm -f common/fdset.lo
+ -rm -f common/fdset_epoll.$(OBJEXT)
+ -rm -f common/fdset_epoll.lo
+ -rm -f common/fdset_kqueue.$(OBJEXT)
+ -rm -f common/fdset_kqueue.lo
+ -rm -f common/fdset_poll.$(OBJEXT)
+ -rm -f common/fdset_poll.lo
+ -rm -f common/getline.$(OBJEXT)
+ -rm -f common/getline.lo
+ -rm -f common/hattrie/ahtable.$(OBJEXT)
+ -rm -f common/hattrie/ahtable.lo
+ -rm -f common/hattrie/hat-trie.$(OBJEXT)
+ -rm -f common/hattrie/hat-trie.lo
+ -rm -f common/hattrie/murmurhash3.$(OBJEXT)
+ -rm -f common/hattrie/murmurhash3.lo
+ -rm -f common/heap.$(OBJEXT)
+ -rm -f common/heap.lo
+ -rm -f common/libtap/tap.$(OBJEXT)
+ -rm -f common/libtap/tap.lo
+ -rm -f common/lists.$(OBJEXT)
+ -rm -f common/lists.lo
+ -rm -f common/log.$(OBJEXT)
+ -rm -f common/log.lo
+ -rm -f common/mempattern.$(OBJEXT)
+ -rm -f common/mempattern.lo
+ -rm -f common/mempool.$(OBJEXT)
+ -rm -f common/mempool.lo
+ -rm -f common/print.$(OBJEXT)
+ -rm -f common/print.lo
+ -rm -f common/prng.$(OBJEXT)
+ -rm -f common/prng.lo
+ -rm -f common/ref.$(OBJEXT)
+ -rm -f common/ref.lo
+ -rm -f common/skip-list.$(OBJEXT)
+ -rm -f common/skip-list.lo
+ -rm -f common/slab/slab.$(OBJEXT)
+ -rm -f common/slab/slab.lo
+ -rm -f common/sockaddr.$(OBJEXT)
+ -rm -f common/sockaddr.lo
+ -rm -f knot/conf/conf.$(OBJEXT)
+ -rm -f knot/conf/conf.lo
+ -rm -f knot/conf/extra.$(OBJEXT)
+ -rm -f knot/conf/extra.lo
+ -rm -f knot/conf/includes.$(OBJEXT)
+ -rm -f knot/conf/includes.lo
+ -rm -f knot/conf/libknotd_la-cf-lex.$(OBJEXT)
+ -rm -f knot/conf/libknotd_la-cf-lex.lo
+ -rm -f knot/conf/libknotd_la-cf-parse.$(OBJEXT)
+ -rm -f knot/conf/libknotd_la-cf-parse.lo
+ -rm -f knot/conf/logconf.$(OBJEXT)
+ -rm -f knot/conf/logconf.lo
+ -rm -f knot/ctl/knotc_main.$(OBJEXT)
+ -rm -f knot/ctl/process.$(OBJEXT)
+ -rm -f knot/ctl/process.lo
+ -rm -f knot/ctl/remote.$(OBJEXT)
+ -rm -f knot/ctl/remote.lo
+ -rm -f knot/main.$(OBJEXT)
+ -rm -f knot/server/dthreads.$(OBJEXT)
+ -rm -f knot/server/dthreads.lo
+ -rm -f knot/server/journal.$(OBJEXT)
+ -rm -f knot/server/journal.lo
+ -rm -f knot/server/notify.$(OBJEXT)
+ -rm -f knot/server/notify.lo
+ -rm -f knot/server/rrl.$(OBJEXT)
+ -rm -f knot/server/rrl.lo
+ -rm -f knot/server/server.$(OBJEXT)
+ -rm -f knot/server/server.lo
+ -rm -f knot/server/socket.$(OBJEXT)
+ -rm -f knot/server/socket.lo
+ -rm -f knot/server/tcp-handler.$(OBJEXT)
+ -rm -f knot/server/tcp-handler.lo
+ -rm -f knot/server/udp-handler.$(OBJEXT)
+ -rm -f knot/server/udp-handler.lo
+ -rm -f knot/server/xfr-handler.$(OBJEXT)
+ -rm -f knot/server/xfr-handler.lo
+ -rm -f knot/server/zones.$(OBJEXT)
+ -rm -f knot/server/zones.lo
+ -rm -f knot/stat/gatherer.$(OBJEXT)
+ -rm -f knot/stat/gatherer.lo
+ -rm -f knot/stat/stat.$(OBJEXT)
+ -rm -f knot/stat/stat.lo
+ -rm -f knot/zone/estimator.$(OBJEXT)
+ -rm -f knot/zone/estimator.lo
+ -rm -f knot/zone/semantic-check.$(OBJEXT)
+ -rm -f knot/zone/semantic-check.lo
+ -rm -f knot/zone/zone-dump.$(OBJEXT)
+ -rm -f knot/zone/zone-dump.lo
+ -rm -f knot/zone/zone-load.$(OBJEXT)
+ -rm -f knot/zone/zone-load.lo
+ -rm -f libknot/binary.$(OBJEXT)
+ -rm -f libknot/binary.lo
+ -rm -f libknot/consts.$(OBJEXT)
+ -rm -f libknot/consts.lo
+ -rm -f libknot/dname.$(OBJEXT)
+ -rm -f libknot/dname.lo
+ -rm -f libknot/edns.$(OBJEXT)
+ -rm -f libknot/edns.lo
+ -rm -f libknot/nameserver/chaos.$(OBJEXT)
+ -rm -f libknot/nameserver/chaos.lo
+ -rm -f libknot/nameserver/name-server.$(OBJEXT)
+ -rm -f libknot/nameserver/name-server.lo
+ -rm -f libknot/nsec3.$(OBJEXT)
+ -rm -f libknot/nsec3.lo
+ -rm -f libknot/packet/packet.$(OBJEXT)
+ -rm -f libknot/packet/packet.lo
+ -rm -f libknot/packet/query.$(OBJEXT)
+ -rm -f libknot/packet/query.lo
+ -rm -f libknot/packet/response.$(OBJEXT)
+ -rm -f libknot/packet/response.lo
+ -rm -f libknot/rrset-dump.$(OBJEXT)
+ -rm -f libknot/rrset-dump.lo
+ -rm -f libknot/rrset.$(OBJEXT)
+ -rm -f libknot/rrset.lo
+ -rm -f libknot/sign/bnutils.$(OBJEXT)
+ -rm -f libknot/sign/bnutils.lo
+ -rm -f libknot/sign/dnssec.$(OBJEXT)
+ -rm -f libknot/sign/dnssec.lo
+ -rm -f libknot/sign/key.$(OBJEXT)
+ -rm -f libknot/sign/key.lo
+ -rm -f libknot/sign/sig0.$(OBJEXT)
+ -rm -f libknot/sign/sig0.lo
+ -rm -f libknot/tsig-op.$(OBJEXT)
+ -rm -f libknot/tsig-op.lo
+ -rm -f libknot/tsig.$(OBJEXT)
+ -rm -f libknot/tsig.lo
+ -rm -f libknot/updates/changesets.$(OBJEXT)
+ -rm -f libknot/updates/changesets.lo
+ -rm -f libknot/updates/ddns.$(OBJEXT)
+ -rm -f libknot/updates/ddns.lo
+ -rm -f libknot/updates/xfr-in.$(OBJEXT)
+ -rm -f libknot/updates/xfr-in.lo
+ -rm -f libknot/util/debug.$(OBJEXT)
+ -rm -f libknot/util/debug.lo
+ -rm -f libknot/util/tolower.$(OBJEXT)
+ -rm -f libknot/util/tolower.lo
+ -rm -f libknot/util/utils.$(OBJEXT)
+ -rm -f libknot/util/utils.lo
+ -rm -f libknot/zone/node.$(OBJEXT)
+ -rm -f libknot/zone/node.lo
+ -rm -f libknot/zone/zone-contents.$(OBJEXT)
+ -rm -f libknot/zone/zone-contents.lo
+ -rm -f libknot/zone/zone-diff.$(OBJEXT)
+ -rm -f libknot/zone/zone-diff.lo
+ -rm -f libknot/zone/zone-tree.$(OBJEXT)
+ -rm -f libknot/zone/zone-tree.lo
+ -rm -f libknot/zone/zone.$(OBJEXT)
+ -rm -f libknot/zone/zone.lo
+ -rm -f libknot/zone/zonedb.$(OBJEXT)
+ -rm -f libknot/zone/zonedb.lo
+ -rm -f utils/common/exec.$(OBJEXT)
+ -rm -f utils/common/msg.$(OBJEXT)
+ -rm -f utils/common/netio.$(OBJEXT)
+ -rm -f utils/common/params.$(OBJEXT)
+ -rm -f utils/common/resolv.$(OBJEXT)
+ -rm -f utils/common/token.$(OBJEXT)
+ -rm -f utils/dig/dig_exec.$(OBJEXT)
+ -rm -f utils/dig/dig_main.$(OBJEXT)
+ -rm -f utils/dig/dig_params.$(OBJEXT)
+ -rm -f utils/host/host_main.$(OBJEXT)
+ -rm -f utils/host/host_params.$(OBJEXT)
+ -rm -f utils/nsupdate/nsupdate_exec.$(OBJEXT)
+ -rm -f utils/nsupdate/nsupdate_main.$(OBJEXT)
+ -rm -f utils/nsupdate/nsupdate_params.$(OBJEXT)
+ -rm -f zscanner/file_loader.$(OBJEXT)
+ -rm -f zscanner/file_loader.lo
+ -rm -f zscanner/scanner.$(OBJEXT)
+ -rm -f zscanner/scanner.lo
+ -rm -f zscanner/scanner_functions.$(OBJEXT)
+ -rm -f zscanner/scanner_functions.lo
+ -rm -f zscanner/test/processing.$(OBJEXT)
+ -rm -f zscanner/test/tests.$(OBJEXT)
+ -rm -f zscanner/test/zscanner-tool.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base32hex.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base32hex_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/changesets.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conf_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cuckoo-hash-table.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cuckoo_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dSFMT.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ddns.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/descriptor.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dname-table.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dname.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dname_table_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dname_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dname_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dthreads.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dthreads_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edns.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edns_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/edns_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errcode.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/errors.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/events_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evqueue.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evsched.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdset.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdset_epoll.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdset_kqueue.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdset_poll.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fdset_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gatherer.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/general-tree.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash-functions.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/journal.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/journal_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/knotc_main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libknot_tests_loader_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libknotd_la-cf-lex.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libknotd_la-cf-parse.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lists.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logconf.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mempattern.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/murmurhash3.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/name-server.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/notify.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsec3.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nsec3_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packet_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser-descriptor.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser-util.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prng.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/process.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdata.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdata_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rdata_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ref.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/response.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/response_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/response_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrl.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrl_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrset.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrset_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrset_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/semantic-check.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/server_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skip-list.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skiplist_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slab.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/slab_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sockaddr.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stat.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tap.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp-handler.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tolower.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig-op.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsig_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp-handler.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unittests_libknot.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unittests_libknot_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unittests_main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unittests_zp_main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/universal-system.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfr-handler.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfr-in.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfr_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zcompile-error.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zcompile.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zcompile_main.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zlexer.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-contents.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-diff.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-dump-text.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-dump.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-load.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone-tree.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zone_tree_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zonedb.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zonedb_tests.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zonedb_tests_realdata.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zones.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zparser.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/acl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/base32hex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/base64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/dSFMT.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/descriptor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/errcode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/errors.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/evqueue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/evsched.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset_epoll.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset_kqueue.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset_poll.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/getline.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/heap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/lists.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/log.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/mempattern.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/mempool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/print.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/prng.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/ref.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/skip-list.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/sockaddr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/hattrie/$(DEPDIR)/ahtable.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/hattrie/$(DEPDIR)/hat-trie.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/hattrie/$(DEPDIR)/murmurhash3.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/libtap/$(DEPDIR)/tap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/slab/$(DEPDIR)/slab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/conf/$(DEPDIR)/conf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/conf/$(DEPDIR)/extra.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/conf/$(DEPDIR)/includes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/conf/$(DEPDIR)/libknotd_la-cf-lex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/conf/$(DEPDIR)/libknotd_la-cf-parse.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/conf/$(DEPDIR)/logconf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/ctl/$(DEPDIR)/knotc_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/ctl/$(DEPDIR)/process.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/ctl/$(DEPDIR)/remote.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/dthreads.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/journal.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/notify.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/rrl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/socket.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/tcp-handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/udp-handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/xfr-handler.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/server/$(DEPDIR)/zones.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/stat/$(DEPDIR)/gatherer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/stat/$(DEPDIR)/stat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/zone/$(DEPDIR)/estimator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/zone/$(DEPDIR)/semantic-check.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/zone/$(DEPDIR)/zone-dump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/zone/$(DEPDIR)/zone-load.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/binary.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/consts.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/dname.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/edns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/nsec3.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/rrset-dump.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/rrset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/tsig-op.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/tsig.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/nameserver/$(DEPDIR)/chaos.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/nameserver/$(DEPDIR)/name-server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/packet/$(DEPDIR)/packet.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/packet/$(DEPDIR)/query.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/packet/$(DEPDIR)/response.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/sign/$(DEPDIR)/bnutils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/sign/$(DEPDIR)/dnssec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/sign/$(DEPDIR)/key.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/sign/$(DEPDIR)/sig0.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/updates/$(DEPDIR)/changesets.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/updates/$(DEPDIR)/ddns.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/updates/$(DEPDIR)/xfr-in.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/util/$(DEPDIR)/debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/util/$(DEPDIR)/tolower.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/util/$(DEPDIR)/utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/zone/$(DEPDIR)/node.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/zone/$(DEPDIR)/zone-contents.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/zone/$(DEPDIR)/zone-diff.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/zone/$(DEPDIR)/zone-tree.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/zone/$(DEPDIR)/zone.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/zone/$(DEPDIR)/zonedb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/common/$(DEPDIR)/exec.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/common/$(DEPDIR)/msg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/common/$(DEPDIR)/netio.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/common/$(DEPDIR)/params.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/common/$(DEPDIR)/resolv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/common/$(DEPDIR)/token.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/dig/$(DEPDIR)/dig_exec.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/dig/$(DEPDIR)/dig_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/dig/$(DEPDIR)/dig_params.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/host/$(DEPDIR)/host_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/host/$(DEPDIR)/host_params.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/nsupdate/$(DEPDIR)/nsupdate_exec.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/nsupdate/$(DEPDIR)/nsupdate_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@utils/nsupdate/$(DEPDIR)/nsupdate_params.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@zscanner/$(DEPDIR)/file_loader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@zscanner/$(DEPDIR)/scanner.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@zscanner/$(DEPDIR)/scanner_functions.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@zscanner/test/$(DEPDIR)/processing.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@zscanner/test/$(DEPDIR)/tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@zscanner/test/$(DEPDIR)/zscanner-tool.Po@am__quote@
.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
-
-utils.lo: libknot/util/utils.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT utils.lo -MD -MP -MF $(DEPDIR)/utils.Tpo -c -o utils.lo `test -f 'libknot/util/utils.c' || echo '$(srcdir)/'`libknot/util/utils.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/utils.Tpo $(DEPDIR)/utils.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/util/utils.c' object='utils.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o utils.lo `test -f 'libknot/util/utils.c' || echo '$(srcdir)/'`libknot/util/utils.c
-
-debug.lo: libknot/util/debug.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT debug.lo -MD -MP -MF $(DEPDIR)/debug.Tpo -c -o debug.lo `test -f 'libknot/util/debug.c' || echo '$(srcdir)/'`libknot/util/debug.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/debug.Tpo $(DEPDIR)/debug.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/util/debug.c' object='debug.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o debug.lo `test -f 'libknot/util/debug.c' || echo '$(srcdir)/'`libknot/util/debug.c
-
-descriptor.lo: libknot/util/descriptor.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT descriptor.lo -MD -MP -MF $(DEPDIR)/descriptor.Tpo -c -o descriptor.lo `test -f 'libknot/util/descriptor.c' || echo '$(srcdir)/'`libknot/util/descriptor.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/descriptor.Tpo $(DEPDIR)/descriptor.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/util/descriptor.c' object='descriptor.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o descriptor.lo `test -f 'libknot/util/descriptor.c' || echo '$(srcdir)/'`libknot/util/descriptor.c
-
-tolower.lo: libknot/util/tolower.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tolower.lo -MD -MP -MF $(DEPDIR)/tolower.Tpo -c -o tolower.lo `test -f 'libknot/util/tolower.c' || echo '$(srcdir)/'`libknot/util/tolower.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tolower.Tpo $(DEPDIR)/tolower.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/util/tolower.c' object='tolower.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tolower.lo `test -f 'libknot/util/tolower.c' || echo '$(srcdir)/'`libknot/util/tolower.c
-
-query.lo: libknot/packet/query.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT query.lo -MD -MP -MF $(DEPDIR)/query.Tpo -c -o query.lo `test -f 'libknot/packet/query.c' || echo '$(srcdir)/'`libknot/packet/query.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/query.Tpo $(DEPDIR)/query.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/packet/query.c' object='query.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o query.lo `test -f 'libknot/packet/query.c' || echo '$(srcdir)/'`libknot/packet/query.c
-
-response.lo: libknot/packet/response.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT response.lo -MD -MP -MF $(DEPDIR)/response.Tpo -c -o response.lo `test -f 'libknot/packet/response.c' || echo '$(srcdir)/'`libknot/packet/response.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/response.Tpo $(DEPDIR)/response.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/packet/response.c' object='response.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o response.lo `test -f 'libknot/packet/response.c' || echo '$(srcdir)/'`libknot/packet/response.c
-
-packet.lo: libknot/packet/packet.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet.lo -MD -MP -MF $(DEPDIR)/packet.Tpo -c -o packet.lo `test -f 'libknot/packet/packet.c' || echo '$(srcdir)/'`libknot/packet/packet.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet.Tpo $(DEPDIR)/packet.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/packet/packet.c' object='packet.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet.lo `test -f 'libknot/packet/packet.c' || echo '$(srcdir)/'`libknot/packet/packet.c
-
-zone.lo: libknot/zone/zone.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone.lo -MD -MP -MF $(DEPDIR)/zone.Tpo -c -o zone.lo `test -f 'libknot/zone/zone.c' || echo '$(srcdir)/'`libknot/zone/zone.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone.Tpo $(DEPDIR)/zone.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/zone/zone.c' object='zone.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone.lo `test -f 'libknot/zone/zone.c' || echo '$(srcdir)/'`libknot/zone/zone.c
-
-zone-contents.lo: libknot/zone/zone-contents.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone-contents.lo -MD -MP -MF $(DEPDIR)/zone-contents.Tpo -c -o zone-contents.lo `test -f 'libknot/zone/zone-contents.c' || echo '$(srcdir)/'`libknot/zone/zone-contents.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone-contents.Tpo $(DEPDIR)/zone-contents.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/zone/zone-contents.c' object='zone-contents.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone-contents.lo `test -f 'libknot/zone/zone-contents.c' || echo '$(srcdir)/'`libknot/zone/zone-contents.c
-
-zone-tree.lo: libknot/zone/zone-tree.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone-tree.lo -MD -MP -MF $(DEPDIR)/zone-tree.Tpo -c -o zone-tree.lo `test -f 'libknot/zone/zone-tree.c' || echo '$(srcdir)/'`libknot/zone/zone-tree.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone-tree.Tpo $(DEPDIR)/zone-tree.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/zone/zone-tree.c' object='zone-tree.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone-tree.lo `test -f 'libknot/zone/zone-tree.c' || echo '$(srcdir)/'`libknot/zone/zone-tree.c
-
-zonedb.lo: libknot/zone/zonedb.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zonedb.lo -MD -MP -MF $(DEPDIR)/zonedb.Tpo -c -o zonedb.lo `test -f 'libknot/zone/zonedb.c' || echo '$(srcdir)/'`libknot/zone/zonedb.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zonedb.Tpo $(DEPDIR)/zonedb.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/zone/zonedb.c' object='zonedb.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zonedb.lo `test -f 'libknot/zone/zonedb.c' || echo '$(srcdir)/'`libknot/zone/zonedb.c
-
-node.lo: libknot/zone/node.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT node.lo -MD -MP -MF $(DEPDIR)/node.Tpo -c -o node.lo `test -f 'libknot/zone/node.c' || echo '$(srcdir)/'`libknot/zone/node.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/node.Tpo $(DEPDIR)/node.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/zone/node.c' object='node.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o node.lo `test -f 'libknot/zone/node.c' || echo '$(srcdir)/'`libknot/zone/node.c
-
-dname-table.lo: libknot/zone/dname-table.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname-table.lo -MD -MP -MF $(DEPDIR)/dname-table.Tpo -c -o dname-table.lo `test -f 'libknot/zone/dname-table.c' || echo '$(srcdir)/'`libknot/zone/dname-table.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname-table.Tpo $(DEPDIR)/dname-table.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/zone/dname-table.c' object='dname-table.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname-table.lo `test -f 'libknot/zone/dname-table.c' || echo '$(srcdir)/'`libknot/zone/dname-table.c
-
-zone-diff.lo: libknot/zone/zone-diff.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone-diff.lo -MD -MP -MF $(DEPDIR)/zone-diff.Tpo -c -o zone-diff.lo `test -f 'libknot/zone/zone-diff.c' || echo '$(srcdir)/'`libknot/zone/zone-diff.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone-diff.Tpo $(DEPDIR)/zone-diff.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/zone/zone-diff.c' object='zone-diff.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone-diff.lo `test -f 'libknot/zone/zone-diff.c' || echo '$(srcdir)/'`libknot/zone/zone-diff.c
-
-hash-functions.lo: libknot/hash/hash-functions.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hash-functions.lo -MD -MP -MF $(DEPDIR)/hash-functions.Tpo -c -o hash-functions.lo `test -f 'libknot/hash/hash-functions.c' || echo '$(srcdir)/'`libknot/hash/hash-functions.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/hash-functions.Tpo $(DEPDIR)/hash-functions.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/hash/hash-functions.c' object='hash-functions.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o hash-functions.lo `test -f 'libknot/hash/hash-functions.c' || echo '$(srcdir)/'`libknot/hash/hash-functions.c
-
-cuckoo-hash-table.lo: libknot/hash/cuckoo-hash-table.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cuckoo-hash-table.lo -MD -MP -MF $(DEPDIR)/cuckoo-hash-table.Tpo -c -o cuckoo-hash-table.lo `test -f 'libknot/hash/cuckoo-hash-table.c' || echo '$(srcdir)/'`libknot/hash/cuckoo-hash-table.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cuckoo-hash-table.Tpo $(DEPDIR)/cuckoo-hash-table.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/hash/cuckoo-hash-table.c' object='cuckoo-hash-table.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cuckoo-hash-table.lo `test -f 'libknot/hash/cuckoo-hash-table.c' || echo '$(srcdir)/'`libknot/hash/cuckoo-hash-table.c
-
-universal-system.lo: libknot/hash/universal-system.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT universal-system.lo -MD -MP -MF $(DEPDIR)/universal-system.Tpo -c -o universal-system.lo `test -f 'libknot/hash/universal-system.c' || echo '$(srcdir)/'`libknot/hash/universal-system.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/universal-system.Tpo $(DEPDIR)/universal-system.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/hash/universal-system.c' object='universal-system.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o universal-system.lo `test -f 'libknot/hash/universal-system.c' || echo '$(srcdir)/'`libknot/hash/universal-system.c
-
-name-server.lo: libknot/nameserver/name-server.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT name-server.lo -MD -MP -MF $(DEPDIR)/name-server.Tpo -c -o name-server.lo `test -f 'libknot/nameserver/name-server.c' || echo '$(srcdir)/'`libknot/nameserver/name-server.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/name-server.Tpo $(DEPDIR)/name-server.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/nameserver/name-server.c' object='name-server.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o name-server.lo `test -f 'libknot/nameserver/name-server.c' || echo '$(srcdir)/'`libknot/nameserver/name-server.c
-
-changesets.lo: libknot/updates/changesets.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT changesets.lo -MD -MP -MF $(DEPDIR)/changesets.Tpo -c -o changesets.lo `test -f 'libknot/updates/changesets.c' || echo '$(srcdir)/'`libknot/updates/changesets.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/changesets.Tpo $(DEPDIR)/changesets.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/updates/changesets.c' object='changesets.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o changesets.lo `test -f 'libknot/updates/changesets.c' || echo '$(srcdir)/'`libknot/updates/changesets.c
-
-xfr-in.lo: libknot/updates/xfr-in.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xfr-in.lo -MD -MP -MF $(DEPDIR)/xfr-in.Tpo -c -o xfr-in.lo `test -f 'libknot/updates/xfr-in.c' || echo '$(srcdir)/'`libknot/updates/xfr-in.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xfr-in.Tpo $(DEPDIR)/xfr-in.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/updates/xfr-in.c' object='xfr-in.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xfr-in.lo `test -f 'libknot/updates/xfr-in.c' || echo '$(srcdir)/'`libknot/updates/xfr-in.c
-
-ddns.lo: libknot/updates/ddns.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ddns.lo -MD -MP -MF $(DEPDIR)/ddns.Tpo -c -o ddns.lo `test -f 'libknot/updates/ddns.c' || echo '$(srcdir)/'`libknot/updates/ddns.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ddns.Tpo $(DEPDIR)/ddns.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/updates/ddns.c' object='ddns.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ddns.lo `test -f 'libknot/updates/ddns.c' || echo '$(srcdir)/'`libknot/updates/ddns.c
-
-edns.lo: libknot/edns.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT edns.lo -MD -MP -MF $(DEPDIR)/edns.Tpo -c -o edns.lo `test -f 'libknot/edns.c' || echo '$(srcdir)/'`libknot/edns.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/edns.Tpo $(DEPDIR)/edns.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/edns.c' object='edns.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o edns.lo `test -f 'libknot/edns.c' || echo '$(srcdir)/'`libknot/edns.c
-
-rrset.lo: libknot/rrset.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrset.lo -MD -MP -MF $(DEPDIR)/rrset.Tpo -c -o rrset.lo `test -f 'libknot/rrset.c' || echo '$(srcdir)/'`libknot/rrset.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrset.Tpo $(DEPDIR)/rrset.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/rrset.c' object='rrset.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrset.lo `test -f 'libknot/rrset.c' || echo '$(srcdir)/'`libknot/rrset.c
-
-dname.lo: libknot/dname.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname.lo -MD -MP -MF $(DEPDIR)/dname.Tpo -c -o dname.lo `test -f 'libknot/dname.c' || echo '$(srcdir)/'`libknot/dname.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname.Tpo $(DEPDIR)/dname.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/dname.c' object='dname.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname.lo `test -f 'libknot/dname.c' || echo '$(srcdir)/'`libknot/dname.c
-
-rdata.lo: libknot/rdata.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rdata.lo -MD -MP -MF $(DEPDIR)/rdata.Tpo -c -o rdata.lo `test -f 'libknot/rdata.c' || echo '$(srcdir)/'`libknot/rdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rdata.Tpo $(DEPDIR)/rdata.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/rdata.c' object='rdata.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rdata.lo `test -f 'libknot/rdata.c' || echo '$(srcdir)/'`libknot/rdata.c
-
-nsec3.lo: libknot/nsec3.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nsec3.lo -MD -MP -MF $(DEPDIR)/nsec3.Tpo -c -o nsec3.lo `test -f 'libknot/nsec3.c' || echo '$(srcdir)/'`libknot/nsec3.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nsec3.Tpo $(DEPDIR)/nsec3.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/nsec3.c' object='nsec3.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nsec3.lo `test -f 'libknot/nsec3.c' || echo '$(srcdir)/'`libknot/nsec3.c
-
-tsig.lo: libknot/tsig.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsig.lo -MD -MP -MF $(DEPDIR)/tsig.Tpo -c -o tsig.lo `test -f 'libknot/tsig.c' || echo '$(srcdir)/'`libknot/tsig.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tsig.Tpo $(DEPDIR)/tsig.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/tsig.c' object='tsig.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsig.lo `test -f 'libknot/tsig.c' || echo '$(srcdir)/'`libknot/tsig.c
-
-tsig-op.lo: libknot/tsig-op.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsig-op.lo -MD -MP -MF $(DEPDIR)/tsig-op.Tpo -c -o tsig-op.lo `test -f 'libknot/tsig-op.c' || echo '$(srcdir)/'`libknot/tsig-op.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tsig-op.Tpo $(DEPDIR)/tsig-op.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/tsig-op.c' object='tsig-op.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsig-op.lo `test -f 'libknot/tsig-op.c' || echo '$(srcdir)/'`libknot/tsig-op.c
-
-gatherer.lo: knot/stat/gatherer.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gatherer.lo -MD -MP -MF $(DEPDIR)/gatherer.Tpo -c -o gatherer.lo `test -f 'knot/stat/gatherer.c' || echo '$(srcdir)/'`knot/stat/gatherer.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gatherer.Tpo $(DEPDIR)/gatherer.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/stat/gatherer.c' object='gatherer.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gatherer.lo `test -f 'knot/stat/gatherer.c' || echo '$(srcdir)/'`knot/stat/gatherer.c
-
-stat.lo: knot/stat/stat.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stat.lo -MD -MP -MF $(DEPDIR)/stat.Tpo -c -o stat.lo `test -f 'knot/stat/stat.c' || echo '$(srcdir)/'`knot/stat/stat.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/stat.Tpo $(DEPDIR)/stat.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/stat/stat.c' object='stat.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stat.lo `test -f 'knot/stat/stat.c' || echo '$(srcdir)/'`knot/stat/stat.c
-
-conf.lo: knot/conf/conf.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT conf.lo -MD -MP -MF $(DEPDIR)/conf.Tpo -c -o conf.lo `test -f 'knot/conf/conf.c' || echo '$(srcdir)/'`knot/conf/conf.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/conf.Tpo $(DEPDIR)/conf.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/conf/conf.c' object='conf.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o conf.lo `test -f 'knot/conf/conf.c' || echo '$(srcdir)/'`knot/conf/conf.c
-
-logconf.lo: knot/conf/logconf.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT logconf.lo -MD -MP -MF $(DEPDIR)/logconf.Tpo -c -o logconf.lo `test -f 'knot/conf/logconf.c' || echo '$(srcdir)/'`knot/conf/logconf.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/logconf.Tpo $(DEPDIR)/logconf.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/conf/logconf.c' object='logconf.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o logconf.lo `test -f 'knot/conf/logconf.c' || echo '$(srcdir)/'`knot/conf/logconf.c
-
-process.lo: knot/ctl/process.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT process.lo -MD -MP -MF $(DEPDIR)/process.Tpo -c -o process.lo `test -f 'knot/ctl/process.c' || echo '$(srcdir)/'`knot/ctl/process.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/process.Tpo $(DEPDIR)/process.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/ctl/process.c' object='process.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o process.lo `test -f 'knot/ctl/process.c' || echo '$(srcdir)/'`knot/ctl/process.c
-
-remote.lo: knot/ctl/remote.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT remote.lo -MD -MP -MF $(DEPDIR)/remote.Tpo -c -o remote.lo `test -f 'knot/ctl/remote.c' || echo '$(srcdir)/'`knot/ctl/remote.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/remote.Tpo $(DEPDIR)/remote.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/ctl/remote.c' object='remote.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o remote.lo `test -f 'knot/ctl/remote.c' || echo '$(srcdir)/'`knot/ctl/remote.c
-
-dthreads.lo: knot/server/dthreads.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dthreads.lo -MD -MP -MF $(DEPDIR)/dthreads.Tpo -c -o dthreads.lo `test -f 'knot/server/dthreads.c' || echo '$(srcdir)/'`knot/server/dthreads.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dthreads.Tpo $(DEPDIR)/dthreads.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/dthreads.c' object='dthreads.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dthreads.lo `test -f 'knot/server/dthreads.c' || echo '$(srcdir)/'`knot/server/dthreads.c
-
-journal.lo: knot/server/journal.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT journal.lo -MD -MP -MF $(DEPDIR)/journal.Tpo -c -o journal.lo `test -f 'knot/server/journal.c' || echo '$(srcdir)/'`knot/server/journal.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/journal.Tpo $(DEPDIR)/journal.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/journal.c' object='journal.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o journal.lo `test -f 'knot/server/journal.c' || echo '$(srcdir)/'`knot/server/journal.c
-
-socket.lo: knot/server/socket.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT socket.lo -MD -MP -MF $(DEPDIR)/socket.Tpo -c -o socket.lo `test -f 'knot/server/socket.c' || echo '$(srcdir)/'`knot/server/socket.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/socket.Tpo $(DEPDIR)/socket.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/socket.c' object='socket.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o socket.lo `test -f 'knot/server/socket.c' || echo '$(srcdir)/'`knot/server/socket.c
-
-server.lo: knot/server/server.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server.lo -MD -MP -MF $(DEPDIR)/server.Tpo -c -o server.lo `test -f 'knot/server/server.c' || echo '$(srcdir)/'`knot/server/server.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/server.Tpo $(DEPDIR)/server.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/server.c' object='server.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server.lo `test -f 'knot/server/server.c' || echo '$(srcdir)/'`knot/server/server.c
-
-udp-handler.lo: knot/server/udp-handler.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT udp-handler.lo -MD -MP -MF $(DEPDIR)/udp-handler.Tpo -c -o udp-handler.lo `test -f 'knot/server/udp-handler.c' || echo '$(srcdir)/'`knot/server/udp-handler.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/udp-handler.Tpo $(DEPDIR)/udp-handler.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/udp-handler.c' object='udp-handler.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o udp-handler.lo `test -f 'knot/server/udp-handler.c' || echo '$(srcdir)/'`knot/server/udp-handler.c
-
-tcp-handler.lo: knot/server/tcp-handler.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tcp-handler.lo -MD -MP -MF $(DEPDIR)/tcp-handler.Tpo -c -o tcp-handler.lo `test -f 'knot/server/tcp-handler.c' || echo '$(srcdir)/'`knot/server/tcp-handler.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tcp-handler.Tpo $(DEPDIR)/tcp-handler.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/tcp-handler.c' object='tcp-handler.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tcp-handler.lo `test -f 'knot/server/tcp-handler.c' || echo '$(srcdir)/'`knot/server/tcp-handler.c
-
-xfr-handler.lo: knot/server/xfr-handler.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xfr-handler.lo -MD -MP -MF $(DEPDIR)/xfr-handler.Tpo -c -o xfr-handler.lo `test -f 'knot/server/xfr-handler.c' || echo '$(srcdir)/'`knot/server/xfr-handler.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xfr-handler.Tpo $(DEPDIR)/xfr-handler.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/xfr-handler.c' object='xfr-handler.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xfr-handler.lo `test -f 'knot/server/xfr-handler.c' || echo '$(srcdir)/'`knot/server/xfr-handler.c
-
-zones.lo: knot/server/zones.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zones.lo -MD -MP -MF $(DEPDIR)/zones.Tpo -c -o zones.lo `test -f 'knot/server/zones.c' || echo '$(srcdir)/'`knot/server/zones.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zones.Tpo $(DEPDIR)/zones.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/zones.c' object='zones.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zones.lo `test -f 'knot/server/zones.c' || echo '$(srcdir)/'`knot/server/zones.c
-
-notify.lo: knot/server/notify.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT notify.lo -MD -MP -MF $(DEPDIR)/notify.Tpo -c -o notify.lo `test -f 'knot/server/notify.c' || echo '$(srcdir)/'`knot/server/notify.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/notify.Tpo $(DEPDIR)/notify.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/notify.c' object='notify.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o notify.lo `test -f 'knot/server/notify.c' || echo '$(srcdir)/'`knot/server/notify.c
-
-rrl.lo: knot/server/rrl.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrl.lo -MD -MP -MF $(DEPDIR)/rrl.Tpo -c -o rrl.lo `test -f 'knot/server/rrl.c' || echo '$(srcdir)/'`knot/server/rrl.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrl.Tpo $(DEPDIR)/rrl.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/server/rrl.c' object='rrl.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrl.lo `test -f 'knot/server/rrl.c' || echo '$(srcdir)/'`knot/server/rrl.c
-
-zone-load.lo: knot/zone/zone-load.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone-load.lo -MD -MP -MF $(DEPDIR)/zone-load.Tpo -c -o zone-load.lo `test -f 'knot/zone/zone-load.c' || echo '$(srcdir)/'`knot/zone/zone-load.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone-load.Tpo $(DEPDIR)/zone-load.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/zone/zone-load.c' object='zone-load.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone-load.lo `test -f 'knot/zone/zone-load.c' || echo '$(srcdir)/'`knot/zone/zone-load.c
-
-semantic-check.lo: knot/zone/semantic-check.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT semantic-check.lo -MD -MP -MF $(DEPDIR)/semantic-check.Tpo -c -o semantic-check.lo `test -f 'knot/zone/semantic-check.c' || echo '$(srcdir)/'`knot/zone/semantic-check.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/semantic-check.Tpo $(DEPDIR)/semantic-check.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/zone/semantic-check.c' object='semantic-check.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o semantic-check.lo `test -f 'knot/zone/semantic-check.c' || echo '$(srcdir)/'`knot/zone/semantic-check.c
-
-zone-dump.lo: knot/zone/zone-dump.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone-dump.lo -MD -MP -MF $(DEPDIR)/zone-dump.Tpo -c -o zone-dump.lo `test -f 'knot/zone/zone-dump.c' || echo '$(srcdir)/'`knot/zone/zone-dump.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone-dump.Tpo $(DEPDIR)/zone-dump.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/zone/zone-dump.c' object='zone-dump.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone-dump.lo `test -f 'knot/zone/zone-dump.c' || echo '$(srcdir)/'`knot/zone/zone-dump.c
-
-zone-dump-text.lo: knot/zone/zone-dump-text.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone-dump-text.lo -MD -MP -MF $(DEPDIR)/zone-dump-text.Tpo -c -o zone-dump-text.lo `test -f 'knot/zone/zone-dump-text.c' || echo '$(srcdir)/'`knot/zone/zone-dump-text.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone-dump-text.Tpo $(DEPDIR)/zone-dump-text.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/zone/zone-dump-text.c' object='zone-dump-text.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone-dump-text.lo `test -f 'knot/zone/zone-dump-text.c' || echo '$(srcdir)/'`knot/zone/zone-dump-text.c
-
-murmurhash3.lo: common/hattrie/murmurhash3.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT murmurhash3.lo -MD -MP -MF $(DEPDIR)/murmurhash3.Tpo -c -o murmurhash3.lo `test -f 'common/hattrie/murmurhash3.c' || echo '$(srcdir)/'`common/hattrie/murmurhash3.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/murmurhash3.Tpo $(DEPDIR)/murmurhash3.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/hattrie/murmurhash3.c' object='murmurhash3.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o murmurhash3.lo `test -f 'common/hattrie/murmurhash3.c' || echo '$(srcdir)/'`common/hattrie/murmurhash3.c
-
-slab.lo: common/slab/slab.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT slab.lo -MD -MP -MF $(DEPDIR)/slab.Tpo -c -o slab.lo `test -f 'common/slab/slab.c' || echo '$(srcdir)/'`common/slab/slab.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/slab.Tpo $(DEPDIR)/slab.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/slab/slab.c' object='slab.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o slab.lo `test -f 'common/slab/slab.c' || echo '$(srcdir)/'`common/slab/slab.c
-
-tap.lo: common/libtap/tap.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tap.lo -MD -MP -MF $(DEPDIR)/tap.Tpo -c -o tap.lo `test -f 'common/libtap/tap.c' || echo '$(srcdir)/'`common/libtap/tap.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tap.Tpo $(DEPDIR)/tap.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/libtap/tap.c' object='tap.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tap.lo `test -f 'common/libtap/tap.c' || echo '$(srcdir)/'`common/libtap/tap.c
-
-mempattern.lo: common/mempattern.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mempattern.lo -MD -MP -MF $(DEPDIR)/mempattern.Tpo -c -o mempattern.lo `test -f 'common/mempattern.c' || echo '$(srcdir)/'`common/mempattern.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mempattern.Tpo $(DEPDIR)/mempattern.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/mempattern.c' object='mempattern.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mempattern.lo `test -f 'common/mempattern.c' || echo '$(srcdir)/'`common/mempattern.c
-
-lists.lo: common/lists.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lists.lo -MD -MP -MF $(DEPDIR)/lists.Tpo -c -o lists.lo `test -f 'common/lists.c' || echo '$(srcdir)/'`common/lists.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lists.Tpo $(DEPDIR)/lists.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/lists.c' object='lists.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lists.lo `test -f 'common/lists.c' || echo '$(srcdir)/'`common/lists.c
-
-base64.lo: common/base64.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT base64.lo -MD -MP -MF $(DEPDIR)/base64.Tpo -c -o base64.lo `test -f 'common/base64.c' || echo '$(srcdir)/'`common/base64.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/base64.Tpo $(DEPDIR)/base64.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/base64.c' object='base64.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o base64.lo `test -f 'common/base64.c' || echo '$(srcdir)/'`common/base64.c
-
-heap.lo: common/heap.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT heap.lo -MD -MP -MF $(DEPDIR)/heap.Tpo -c -o heap.lo `test -f 'common/heap.c' || echo '$(srcdir)/'`common/heap.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/heap.Tpo $(DEPDIR)/heap.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/heap.c' object='heap.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o heap.lo `test -f 'common/heap.c' || echo '$(srcdir)/'`common/heap.c
-
-print.lo: common/print.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT print.lo -MD -MP -MF $(DEPDIR)/print.Tpo -c -o print.lo `test -f 'common/print.c' || echo '$(srcdir)/'`common/print.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/print.Tpo $(DEPDIR)/print.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/print.c' object='print.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o print.lo `test -f 'common/print.c' || echo '$(srcdir)/'`common/print.c
-
-skip-list.lo: common/skip-list.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT skip-list.lo -MD -MP -MF $(DEPDIR)/skip-list.Tpo -c -o skip-list.lo `test -f 'common/skip-list.c' || echo '$(srcdir)/'`common/skip-list.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/skip-list.Tpo $(DEPDIR)/skip-list.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/skip-list.c' object='skip-list.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o skip-list.lo `test -f 'common/skip-list.c' || echo '$(srcdir)/'`common/skip-list.c
-
-base32hex.lo: common/base32hex.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT base32hex.lo -MD -MP -MF $(DEPDIR)/base32hex.Tpo -c -o base32hex.lo `test -f 'common/base32hex.c' || echo '$(srcdir)/'`common/base32hex.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/base32hex.Tpo $(DEPDIR)/base32hex.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/base32hex.c' object='base32hex.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o base32hex.lo `test -f 'common/base32hex.c' || echo '$(srcdir)/'`common/base32hex.c
-
-general-tree.lo: common/general-tree.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT general-tree.lo -MD -MP -MF $(DEPDIR)/general-tree.Tpo -c -o general-tree.lo `test -f 'common/general-tree.c' || echo '$(srcdir)/'`common/general-tree.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/general-tree.Tpo $(DEPDIR)/general-tree.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/general-tree.c' object='general-tree.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o general-tree.lo `test -f 'common/general-tree.c' || echo '$(srcdir)/'`common/general-tree.c
-
-evqueue.lo: common/evqueue.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT evqueue.lo -MD -MP -MF $(DEPDIR)/evqueue.Tpo -c -o evqueue.lo `test -f 'common/evqueue.c' || echo '$(srcdir)/'`common/evqueue.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/evqueue.Tpo $(DEPDIR)/evqueue.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/evqueue.c' object='evqueue.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o evqueue.lo `test -f 'common/evqueue.c' || echo '$(srcdir)/'`common/evqueue.c
-
-evsched.lo: common/evsched.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT evsched.lo -MD -MP -MF $(DEPDIR)/evsched.Tpo -c -o evsched.lo `test -f 'common/evsched.c' || echo '$(srcdir)/'`common/evsched.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/evsched.Tpo $(DEPDIR)/evsched.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/evsched.c' object='evsched.lo' libtool=yes @AMDEPBACKSLASH@
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o evsched.lo `test -f 'common/evsched.c' || echo '$(srcdir)/'`common/evsched.c
-
-acl.lo: common/acl.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT acl.lo -MD -MP -MF $(DEPDIR)/acl.Tpo -c -o acl.lo `test -f 'common/acl.c' || echo '$(srcdir)/'`common/acl.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/acl.Tpo $(DEPDIR)/acl.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/acl.c' object='acl.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o acl.lo `test -f 'common/acl.c' || echo '$(srcdir)/'`common/acl.c
-
-sockaddr.lo: common/sockaddr.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sockaddr.lo -MD -MP -MF $(DEPDIR)/sockaddr.Tpo -c -o sockaddr.lo `test -f 'common/sockaddr.c' || echo '$(srcdir)/'`common/sockaddr.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/sockaddr.Tpo $(DEPDIR)/sockaddr.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/sockaddr.c' object='sockaddr.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sockaddr.lo `test -f 'common/sockaddr.c' || echo '$(srcdir)/'`common/sockaddr.c
-
-ref.lo: common/ref.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ref.lo -MD -MP -MF $(DEPDIR)/ref.Tpo -c -o ref.lo `test -f 'common/ref.c' || echo '$(srcdir)/'`common/ref.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ref.Tpo $(DEPDIR)/ref.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/ref.c' object='ref.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ref.lo `test -f 'common/ref.c' || echo '$(srcdir)/'`common/ref.c
-
-errors.lo: common/errors.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errors.lo -MD -MP -MF $(DEPDIR)/errors.Tpo -c -o errors.lo `test -f 'common/errors.c' || echo '$(srcdir)/'`common/errors.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/errors.Tpo $(DEPDIR)/errors.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/errors.c' object='errors.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errors.lo `test -f 'common/errors.c' || echo '$(srcdir)/'`common/errors.c
-
-errcode.lo: common/errcode.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT errcode.lo -MD -MP -MF $(DEPDIR)/errcode.Tpo -c -o errcode.lo `test -f 'common/errcode.c' || echo '$(srcdir)/'`common/errcode.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/errcode.Tpo $(DEPDIR)/errcode.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/errcode.c' object='errcode.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o errcode.lo `test -f 'common/errcode.c' || echo '$(srcdir)/'`common/errcode.c
-
-dSFMT.lo: common/dSFMT.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dSFMT.lo -MD -MP -MF $(DEPDIR)/dSFMT.Tpo -c -o dSFMT.lo `test -f 'common/dSFMT.c' || echo '$(srcdir)/'`common/dSFMT.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dSFMT.Tpo $(DEPDIR)/dSFMT.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/dSFMT.c' object='dSFMT.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dSFMT.lo `test -f 'common/dSFMT.c' || echo '$(srcdir)/'`common/dSFMT.c
-
-prng.lo: common/prng.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT prng.lo -MD -MP -MF $(DEPDIR)/prng.Tpo -c -o prng.lo `test -f 'common/prng.c' || echo '$(srcdir)/'`common/prng.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/prng.Tpo $(DEPDIR)/prng.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/prng.c' object='prng.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o prng.lo `test -f 'common/prng.c' || echo '$(srcdir)/'`common/prng.c
-
-fdset.lo: common/fdset.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdset.lo -MD -MP -MF $(DEPDIR)/fdset.Tpo -c -o fdset.lo `test -f 'common/fdset.c' || echo '$(srcdir)/'`common/fdset.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fdset.Tpo $(DEPDIR)/fdset.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/fdset.c' object='fdset.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdset.lo `test -f 'common/fdset.c' || echo '$(srcdir)/'`common/fdset.c
-
-fdset_poll.lo: common/fdset_poll.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdset_poll.lo -MD -MP -MF $(DEPDIR)/fdset_poll.Tpo -c -o fdset_poll.lo `test -f 'common/fdset_poll.c' || echo '$(srcdir)/'`common/fdset_poll.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fdset_poll.Tpo $(DEPDIR)/fdset_poll.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/fdset_poll.c' object='fdset_poll.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdset_poll.lo `test -f 'common/fdset_poll.c' || echo '$(srcdir)/'`common/fdset_poll.c
-
-fdset_kqueue.lo: common/fdset_kqueue.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdset_kqueue.lo -MD -MP -MF $(DEPDIR)/fdset_kqueue.Tpo -c -o fdset_kqueue.lo `test -f 'common/fdset_kqueue.c' || echo '$(srcdir)/'`common/fdset_kqueue.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fdset_kqueue.Tpo $(DEPDIR)/fdset_kqueue.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/fdset_kqueue.c' object='fdset_kqueue.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdset_kqueue.lo `test -f 'common/fdset_kqueue.c' || echo '$(srcdir)/'`common/fdset_kqueue.c
-
-fdset_epoll.lo: common/fdset_epoll.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdset_epoll.lo -MD -MP -MF $(DEPDIR)/fdset_epoll.Tpo -c -o fdset_epoll.lo `test -f 'common/fdset_epoll.c' || echo '$(srcdir)/'`common/fdset_epoll.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fdset_epoll.Tpo $(DEPDIR)/fdset_epoll.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/fdset_epoll.c' object='fdset_epoll.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdset_epoll.lo `test -f 'common/fdset_epoll.c' || echo '$(srcdir)/'`common/fdset_epoll.c
-
-log.lo: common/log.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT log.lo -MD -MP -MF $(DEPDIR)/log.Tpo -c -o log.lo `test -f 'common/log.c' || echo '$(srcdir)/'`common/log.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/log.Tpo $(DEPDIR)/log.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/log.c' object='log.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o log.lo `test -f 'common/log.c' || echo '$(srcdir)/'`common/log.c
-
-zcompile_main.o: zcompile/zcompile_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zcompile_main.o -MD -MP -MF $(DEPDIR)/zcompile_main.Tpo -c -o zcompile_main.o `test -f 'zcompile/zcompile_main.c' || echo '$(srcdir)/'`zcompile/zcompile_main.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zcompile_main.Tpo $(DEPDIR)/zcompile_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/zcompile_main.c' object='zcompile_main.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zcompile_main.o `test -f 'zcompile/zcompile_main.c' || echo '$(srcdir)/'`zcompile/zcompile_main.c
-
-zcompile_main.obj: zcompile/zcompile_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zcompile_main.obj -MD -MP -MF $(DEPDIR)/zcompile_main.Tpo -c -o zcompile_main.obj `if test -f 'zcompile/zcompile_main.c'; then $(CYGPATH_W) 'zcompile/zcompile_main.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/zcompile_main.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zcompile_main.Tpo $(DEPDIR)/zcompile_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/zcompile_main.c' object='zcompile_main.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zcompile_main.obj `if test -f 'zcompile/zcompile_main.c'; then $(CYGPATH_W) 'zcompile/zcompile_main.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/zcompile_main.c'; fi`
-
-zcompile-error.o: zcompile/zcompile-error.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zcompile-error.o -MD -MP -MF $(DEPDIR)/zcompile-error.Tpo -c -o zcompile-error.o `test -f 'zcompile/zcompile-error.c' || echo '$(srcdir)/'`zcompile/zcompile-error.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zcompile-error.Tpo $(DEPDIR)/zcompile-error.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/zcompile-error.c' object='zcompile-error.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zcompile-error.o `test -f 'zcompile/zcompile-error.c' || echo '$(srcdir)/'`zcompile/zcompile-error.c
-
-zcompile-error.obj: zcompile/zcompile-error.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zcompile-error.obj -MD -MP -MF $(DEPDIR)/zcompile-error.Tpo -c -o zcompile-error.obj `if test -f 'zcompile/zcompile-error.c'; then $(CYGPATH_W) 'zcompile/zcompile-error.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/zcompile-error.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zcompile-error.Tpo $(DEPDIR)/zcompile-error.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/zcompile-error.c' object='zcompile-error.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zcompile-error.obj `if test -f 'zcompile/zcompile-error.c'; then $(CYGPATH_W) 'zcompile/zcompile-error.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/zcompile-error.c'; fi`
-
-zcompile.o: zcompile/zcompile.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zcompile.o -MD -MP -MF $(DEPDIR)/zcompile.Tpo -c -o zcompile.o `test -f 'zcompile/zcompile.c' || echo '$(srcdir)/'`zcompile/zcompile.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zcompile.Tpo $(DEPDIR)/zcompile.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/zcompile.c' object='zcompile.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zcompile.o `test -f 'zcompile/zcompile.c' || echo '$(srcdir)/'`zcompile/zcompile.c
-
-zcompile.obj: zcompile/zcompile.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zcompile.obj -MD -MP -MF $(DEPDIR)/zcompile.Tpo -c -o zcompile.obj `if test -f 'zcompile/zcompile.c'; then $(CYGPATH_W) 'zcompile/zcompile.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/zcompile.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zcompile.Tpo $(DEPDIR)/zcompile.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/zcompile.c' object='zcompile.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zcompile.obj `if test -f 'zcompile/zcompile.c'; then $(CYGPATH_W) 'zcompile/zcompile.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/zcompile.c'; fi`
-
-parser-util.o: zcompile/parser-util.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parser-util.o -MD -MP -MF $(DEPDIR)/parser-util.Tpo -c -o parser-util.o `test -f 'zcompile/parser-util.c' || echo '$(srcdir)/'`zcompile/parser-util.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parser-util.Tpo $(DEPDIR)/parser-util.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/parser-util.c' object='parser-util.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parser-util.o `test -f 'zcompile/parser-util.c' || echo '$(srcdir)/'`zcompile/parser-util.c
-
-parser-util.obj: zcompile/parser-util.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parser-util.obj -MD -MP -MF $(DEPDIR)/parser-util.Tpo -c -o parser-util.obj `if test -f 'zcompile/parser-util.c'; then $(CYGPATH_W) 'zcompile/parser-util.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/parser-util.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parser-util.Tpo $(DEPDIR)/parser-util.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/parser-util.c' object='parser-util.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parser-util.obj `if test -f 'zcompile/parser-util.c'; then $(CYGPATH_W) 'zcompile/parser-util.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/parser-util.c'; fi`
-
-parser-descriptor.o: zcompile/parser-descriptor.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parser-descriptor.o -MD -MP -MF $(DEPDIR)/parser-descriptor.Tpo -c -o parser-descriptor.o `test -f 'zcompile/parser-descriptor.c' || echo '$(srcdir)/'`zcompile/parser-descriptor.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parser-descriptor.Tpo $(DEPDIR)/parser-descriptor.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/parser-descriptor.c' object='parser-descriptor.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parser-descriptor.o `test -f 'zcompile/parser-descriptor.c' || echo '$(srcdir)/'`zcompile/parser-descriptor.c
-
-parser-descriptor.obj: zcompile/parser-descriptor.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT parser-descriptor.obj -MD -MP -MF $(DEPDIR)/parser-descriptor.Tpo -c -o parser-descriptor.obj `if test -f 'zcompile/parser-descriptor.c'; then $(CYGPATH_W) 'zcompile/parser-descriptor.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/parser-descriptor.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/parser-descriptor.Tpo $(DEPDIR)/parser-descriptor.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/parser-descriptor.c' object='parser-descriptor.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o parser-descriptor.obj `if test -f 'zcompile/parser-descriptor.c'; then $(CYGPATH_W) 'zcompile/parser-descriptor.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/parser-descriptor.c'; fi`
-
-knotc_main.o: knot/ctl/knotc_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knotc_main.o -MD -MP -MF $(DEPDIR)/knotc_main.Tpo -c -o knotc_main.o `test -f 'knot/ctl/knotc_main.c' || echo '$(srcdir)/'`knot/ctl/knotc_main.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/knotc_main.Tpo $(DEPDIR)/knotc_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/ctl/knotc_main.c' object='knotc_main.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knotc_main.o `test -f 'knot/ctl/knotc_main.c' || echo '$(srcdir)/'`knot/ctl/knotc_main.c
-
-knotc_main.obj: knot/ctl/knotc_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT knotc_main.obj -MD -MP -MF $(DEPDIR)/knotc_main.Tpo -c -o knotc_main.obj `if test -f 'knot/ctl/knotc_main.c'; then $(CYGPATH_W) 'knot/ctl/knotc_main.c'; else $(CYGPATH_W) '$(srcdir)/knot/ctl/knotc_main.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/knotc_main.Tpo $(DEPDIR)/knotc_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/ctl/knotc_main.c' object='knotc_main.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o knotc_main.obj `if test -f 'knot/ctl/knotc_main.c'; then $(CYGPATH_W) 'knot/ctl/knotc_main.c'; else $(CYGPATH_W) '$(srcdir)/knot/ctl/knotc_main.c'; fi`
-
-main.o: knot/main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.o -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.o `test -f 'knot/main.c' || echo '$(srcdir)/'`knot/main.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/main.c' object='main.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.o `test -f 'knot/main.c' || echo '$(srcdir)/'`knot/main.c
-
-main.obj: knot/main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT main.obj -MD -MP -MF $(DEPDIR)/main.Tpo -c -o main.obj `if test -f 'knot/main.c'; then $(CYGPATH_W) 'knot/main.c'; else $(CYGPATH_W) '$(srcdir)/knot/main.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/main.Tpo $(DEPDIR)/main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='knot/main.c' object='main.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o main.obj `if test -f 'knot/main.c'; then $(CYGPATH_W) 'knot/main.c'; else $(CYGPATH_W) '$(srcdir)/knot/main.c'; fi`
-
-acl_tests.o: tests/common/acl_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT acl_tests.o -MD -MP -MF $(DEPDIR)/acl_tests.Tpo -c -o acl_tests.o `test -f 'tests/common/acl_tests.c' || echo '$(srcdir)/'`tests/common/acl_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/acl_tests.Tpo $(DEPDIR)/acl_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/acl_tests.c' object='acl_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o acl_tests.o `test -f 'tests/common/acl_tests.c' || echo '$(srcdir)/'`tests/common/acl_tests.c
-
-acl_tests.obj: tests/common/acl_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT acl_tests.obj -MD -MP -MF $(DEPDIR)/acl_tests.Tpo -c -o acl_tests.obj `if test -f 'tests/common/acl_tests.c'; then $(CYGPATH_W) 'tests/common/acl_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/acl_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/acl_tests.Tpo $(DEPDIR)/acl_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/acl_tests.c' object='acl_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o acl_tests.obj `if test -f 'tests/common/acl_tests.c'; then $(CYGPATH_W) 'tests/common/acl_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/acl_tests.c'; fi`
-
-base32hex_tests.o: tests/common/base32hex_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT base32hex_tests.o -MD -MP -MF $(DEPDIR)/base32hex_tests.Tpo -c -o base32hex_tests.o `test -f 'tests/common/base32hex_tests.c' || echo '$(srcdir)/'`tests/common/base32hex_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/base32hex_tests.Tpo $(DEPDIR)/base32hex_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/base32hex_tests.c' object='base32hex_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o base32hex_tests.o `test -f 'tests/common/base32hex_tests.c' || echo '$(srcdir)/'`tests/common/base32hex_tests.c
-
-base32hex_tests.obj: tests/common/base32hex_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT base32hex_tests.obj -MD -MP -MF $(DEPDIR)/base32hex_tests.Tpo -c -o base32hex_tests.obj `if test -f 'tests/common/base32hex_tests.c'; then $(CYGPATH_W) 'tests/common/base32hex_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/base32hex_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/base32hex_tests.Tpo $(DEPDIR)/base32hex_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/base32hex_tests.c' object='base32hex_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o base32hex_tests.obj `if test -f 'tests/common/base32hex_tests.c'; then $(CYGPATH_W) 'tests/common/base32hex_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/base32hex_tests.c'; fi`
-
-base64_tests.o: tests/common/base64_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT base64_tests.o -MD -MP -MF $(DEPDIR)/base64_tests.Tpo -c -o base64_tests.o `test -f 'tests/common/base64_tests.c' || echo '$(srcdir)/'`tests/common/base64_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/base64_tests.Tpo $(DEPDIR)/base64_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/base64_tests.c' object='base64_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o base64_tests.o `test -f 'tests/common/base64_tests.c' || echo '$(srcdir)/'`tests/common/base64_tests.c
-
-base64_tests.obj: tests/common/base64_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT base64_tests.obj -MD -MP -MF $(DEPDIR)/base64_tests.Tpo -c -o base64_tests.obj `if test -f 'tests/common/base64_tests.c'; then $(CYGPATH_W) 'tests/common/base64_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/base64_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/base64_tests.Tpo $(DEPDIR)/base64_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/base64_tests.c' object='base64_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o base64_tests.obj `if test -f 'tests/common/base64_tests.c'; then $(CYGPATH_W) 'tests/common/base64_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/base64_tests.c'; fi`
-
-events_tests.o: tests/common/events_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT events_tests.o -MD -MP -MF $(DEPDIR)/events_tests.Tpo -c -o events_tests.o `test -f 'tests/common/events_tests.c' || echo '$(srcdir)/'`tests/common/events_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/events_tests.Tpo $(DEPDIR)/events_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/events_tests.c' object='events_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o events_tests.o `test -f 'tests/common/events_tests.c' || echo '$(srcdir)/'`tests/common/events_tests.c
-
-events_tests.obj: tests/common/events_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT events_tests.obj -MD -MP -MF $(DEPDIR)/events_tests.Tpo -c -o events_tests.obj `if test -f 'tests/common/events_tests.c'; then $(CYGPATH_W) 'tests/common/events_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/events_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/events_tests.Tpo $(DEPDIR)/events_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/events_tests.c' object='events_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o events_tests.obj `if test -f 'tests/common/events_tests.c'; then $(CYGPATH_W) 'tests/common/events_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/events_tests.c'; fi`
-
-skiplist_tests.o: tests/common/skiplist_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT skiplist_tests.o -MD -MP -MF $(DEPDIR)/skiplist_tests.Tpo -c -o skiplist_tests.o `test -f 'tests/common/skiplist_tests.c' || echo '$(srcdir)/'`tests/common/skiplist_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/skiplist_tests.Tpo $(DEPDIR)/skiplist_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/skiplist_tests.c' object='skiplist_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o skiplist_tests.o `test -f 'tests/common/skiplist_tests.c' || echo '$(srcdir)/'`tests/common/skiplist_tests.c
-
-skiplist_tests.obj: tests/common/skiplist_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT skiplist_tests.obj -MD -MP -MF $(DEPDIR)/skiplist_tests.Tpo -c -o skiplist_tests.obj `if test -f 'tests/common/skiplist_tests.c'; then $(CYGPATH_W) 'tests/common/skiplist_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/skiplist_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/skiplist_tests.Tpo $(DEPDIR)/skiplist_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/skiplist_tests.c' object='skiplist_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o skiplist_tests.obj `if test -f 'tests/common/skiplist_tests.c'; then $(CYGPATH_W) 'tests/common/skiplist_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/skiplist_tests.c'; fi`
-
-slab_tests.o: tests/common/slab_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT slab_tests.o -MD -MP -MF $(DEPDIR)/slab_tests.Tpo -c -o slab_tests.o `test -f 'tests/common/slab_tests.c' || echo '$(srcdir)/'`tests/common/slab_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/slab_tests.Tpo $(DEPDIR)/slab_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/slab_tests.c' object='slab_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o slab_tests.o `test -f 'tests/common/slab_tests.c' || echo '$(srcdir)/'`tests/common/slab_tests.c
-
-slab_tests.obj: tests/common/slab_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT slab_tests.obj -MD -MP -MF $(DEPDIR)/slab_tests.Tpo -c -o slab_tests.obj `if test -f 'tests/common/slab_tests.c'; then $(CYGPATH_W) 'tests/common/slab_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/slab_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/slab_tests.Tpo $(DEPDIR)/slab_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/slab_tests.c' object='slab_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o slab_tests.obj `if test -f 'tests/common/slab_tests.c'; then $(CYGPATH_W) 'tests/common/slab_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/slab_tests.c'; fi`
-
-fdset_tests.o: tests/common/fdset_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdset_tests.o -MD -MP -MF $(DEPDIR)/fdset_tests.Tpo -c -o fdset_tests.o `test -f 'tests/common/fdset_tests.c' || echo '$(srcdir)/'`tests/common/fdset_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fdset_tests.Tpo $(DEPDIR)/fdset_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/fdset_tests.c' object='fdset_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdset_tests.o `test -f 'tests/common/fdset_tests.c' || echo '$(srcdir)/'`tests/common/fdset_tests.c
-
-fdset_tests.obj: tests/common/fdset_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT fdset_tests.obj -MD -MP -MF $(DEPDIR)/fdset_tests.Tpo -c -o fdset_tests.obj `if test -f 'tests/common/fdset_tests.c'; then $(CYGPATH_W) 'tests/common/fdset_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/fdset_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/fdset_tests.Tpo $(DEPDIR)/fdset_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/fdset_tests.c' object='fdset_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fdset_tests.obj `if test -f 'tests/common/fdset_tests.c'; then $(CYGPATH_W) 'tests/common/fdset_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/fdset_tests.c'; fi`
-
-conf_tests.o: tests/knot/conf_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT conf_tests.o -MD -MP -MF $(DEPDIR)/conf_tests.Tpo -c -o conf_tests.o `test -f 'tests/knot/conf_tests.c' || echo '$(srcdir)/'`tests/knot/conf_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/conf_tests.Tpo $(DEPDIR)/conf_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/conf_tests.c' object='conf_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o conf_tests.o `test -f 'tests/knot/conf_tests.c' || echo '$(srcdir)/'`tests/knot/conf_tests.c
-
-conf_tests.obj: tests/knot/conf_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT conf_tests.obj -MD -MP -MF $(DEPDIR)/conf_tests.Tpo -c -o conf_tests.obj `if test -f 'tests/knot/conf_tests.c'; then $(CYGPATH_W) 'tests/knot/conf_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/conf_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/conf_tests.Tpo $(DEPDIR)/conf_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/conf_tests.c' object='conf_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o conf_tests.obj `if test -f 'tests/knot/conf_tests.c'; then $(CYGPATH_W) 'tests/knot/conf_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/conf_tests.c'; fi`
-
-dthreads_tests.o: tests/knot/dthreads_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dthreads_tests.o -MD -MP -MF $(DEPDIR)/dthreads_tests.Tpo -c -o dthreads_tests.o `test -f 'tests/knot/dthreads_tests.c' || echo '$(srcdir)/'`tests/knot/dthreads_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dthreads_tests.Tpo $(DEPDIR)/dthreads_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/dthreads_tests.c' object='dthreads_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dthreads_tests.o `test -f 'tests/knot/dthreads_tests.c' || echo '$(srcdir)/'`tests/knot/dthreads_tests.c
-
-dthreads_tests.obj: tests/knot/dthreads_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dthreads_tests.obj -MD -MP -MF $(DEPDIR)/dthreads_tests.Tpo -c -o dthreads_tests.obj `if test -f 'tests/knot/dthreads_tests.c'; then $(CYGPATH_W) 'tests/knot/dthreads_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/dthreads_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dthreads_tests.Tpo $(DEPDIR)/dthreads_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/dthreads_tests.c' object='dthreads_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dthreads_tests.obj `if test -f 'tests/knot/dthreads_tests.c'; then $(CYGPATH_W) 'tests/knot/dthreads_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/dthreads_tests.c'; fi`
-
-journal_tests.o: tests/knot/journal_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT journal_tests.o -MD -MP -MF $(DEPDIR)/journal_tests.Tpo -c -o journal_tests.o `test -f 'tests/knot/journal_tests.c' || echo '$(srcdir)/'`tests/knot/journal_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/journal_tests.Tpo $(DEPDIR)/journal_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/journal_tests.c' object='journal_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o journal_tests.o `test -f 'tests/knot/journal_tests.c' || echo '$(srcdir)/'`tests/knot/journal_tests.c
-
-journal_tests.obj: tests/knot/journal_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT journal_tests.obj -MD -MP -MF $(DEPDIR)/journal_tests.Tpo -c -o journal_tests.obj `if test -f 'tests/knot/journal_tests.c'; then $(CYGPATH_W) 'tests/knot/journal_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/journal_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/journal_tests.Tpo $(DEPDIR)/journal_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/journal_tests.c' object='journal_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o journal_tests.obj `if test -f 'tests/knot/journal_tests.c'; then $(CYGPATH_W) 'tests/knot/journal_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/journal_tests.c'; fi`
-
-server_tests.o: tests/knot/server_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_tests.o -MD -MP -MF $(DEPDIR)/server_tests.Tpo -c -o server_tests.o `test -f 'tests/knot/server_tests.c' || echo '$(srcdir)/'`tests/knot/server_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/server_tests.Tpo $(DEPDIR)/server_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/server_tests.c' object='server_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_tests.o `test -f 'tests/knot/server_tests.c' || echo '$(srcdir)/'`tests/knot/server_tests.c
-
-server_tests.obj: tests/knot/server_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server_tests.obj -MD -MP -MF $(DEPDIR)/server_tests.Tpo -c -o server_tests.obj `if test -f 'tests/knot/server_tests.c'; then $(CYGPATH_W) 'tests/knot/server_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/server_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/server_tests.Tpo $(DEPDIR)/server_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/server_tests.c' object='server_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server_tests.obj `if test -f 'tests/knot/server_tests.c'; then $(CYGPATH_W) 'tests/knot/server_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/server_tests.c'; fi`
-
-rrl_tests.o: tests/knot/rrl_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrl_tests.o -MD -MP -MF $(DEPDIR)/rrl_tests.Tpo -c -o rrl_tests.o `test -f 'tests/knot/rrl_tests.c' || echo '$(srcdir)/'`tests/knot/rrl_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrl_tests.Tpo $(DEPDIR)/rrl_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/rrl_tests.c' object='rrl_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrl_tests.o `test -f 'tests/knot/rrl_tests.c' || echo '$(srcdir)/'`tests/knot/rrl_tests.c
-
-rrl_tests.obj: tests/knot/rrl_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrl_tests.obj -MD -MP -MF $(DEPDIR)/rrl_tests.Tpo -c -o rrl_tests.obj `if test -f 'tests/knot/rrl_tests.c'; then $(CYGPATH_W) 'tests/knot/rrl_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/rrl_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrl_tests.Tpo $(DEPDIR)/rrl_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/knot/rrl_tests.c' object='rrl_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrl_tests.obj `if test -f 'tests/knot/rrl_tests.c'; then $(CYGPATH_W) 'tests/knot/rrl_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/knot/rrl_tests.c'; fi`
-
-unittests_main.o: tests/unittests_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_main.o -MD -MP -MF $(DEPDIR)/unittests_main.Tpo -c -o unittests_main.o `test -f 'tests/unittests_main.c' || echo '$(srcdir)/'`tests/unittests_main.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_main.Tpo $(DEPDIR)/unittests_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/unittests_main.c' object='unittests_main.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_main.o `test -f 'tests/unittests_main.c' || echo '$(srcdir)/'`tests/unittests_main.c
-
-unittests_main.obj: tests/unittests_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_main.obj -MD -MP -MF $(DEPDIR)/unittests_main.Tpo -c -o unittests_main.obj `if test -f 'tests/unittests_main.c'; then $(CYGPATH_W) 'tests/unittests_main.c'; else $(CYGPATH_W) '$(srcdir)/tests/unittests_main.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_main.Tpo $(DEPDIR)/unittests_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/unittests_main.c' object='unittests_main.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_main.obj `if test -f 'tests/unittests_main.c'; then $(CYGPATH_W) 'tests/unittests_main.c'; else $(CYGPATH_W) '$(srcdir)/tests/unittests_main.c'; fi`
-
-cuckoo_tests.o: tests/libknot/libknot/cuckoo_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cuckoo_tests.o -MD -MP -MF $(DEPDIR)/cuckoo_tests.Tpo -c -o cuckoo_tests.o `test -f 'tests/libknot/libknot/cuckoo_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/cuckoo_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cuckoo_tests.Tpo $(DEPDIR)/cuckoo_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/cuckoo_tests.c' object='cuckoo_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cuckoo_tests.o `test -f 'tests/libknot/libknot/cuckoo_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/cuckoo_tests.c
-
-cuckoo_tests.obj: tests/libknot/libknot/cuckoo_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cuckoo_tests.obj -MD -MP -MF $(DEPDIR)/cuckoo_tests.Tpo -c -o cuckoo_tests.obj `if test -f 'tests/libknot/libknot/cuckoo_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/cuckoo_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/cuckoo_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cuckoo_tests.Tpo $(DEPDIR)/cuckoo_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/cuckoo_tests.c' object='cuckoo_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cuckoo_tests.obj `if test -f 'tests/libknot/libknot/cuckoo_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/cuckoo_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/cuckoo_tests.c'; fi`
-
-response_tests.o: tests/libknot/libknot/response_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT response_tests.o -MD -MP -MF $(DEPDIR)/response_tests.Tpo -c -o response_tests.o `test -f 'tests/libknot/libknot/response_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/response_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/response_tests.Tpo $(DEPDIR)/response_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/response_tests.c' object='response_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o response_tests.o `test -f 'tests/libknot/libknot/response_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/response_tests.c
-
-response_tests.obj: tests/libknot/libknot/response_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT response_tests.obj -MD -MP -MF $(DEPDIR)/response_tests.Tpo -c -o response_tests.obj `if test -f 'tests/libknot/libknot/response_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/response_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/response_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/response_tests.Tpo $(DEPDIR)/response_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/response_tests.c' object='response_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o response_tests.obj `if test -f 'tests/libknot/libknot/response_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/response_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/response_tests.c'; fi`
-
-dname_tests.o: tests/libknot/libknot/dname_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname_tests.o -MD -MP -MF $(DEPDIR)/dname_tests.Tpo -c -o dname_tests.o `test -f 'tests/libknot/libknot/dname_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/dname_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname_tests.Tpo $(DEPDIR)/dname_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/dname_tests.c' object='dname_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname_tests.o `test -f 'tests/libknot/libknot/dname_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/dname_tests.c
-
-dname_tests.obj: tests/libknot/libknot/dname_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname_tests.obj -MD -MP -MF $(DEPDIR)/dname_tests.Tpo -c -o dname_tests.obj `if test -f 'tests/libknot/libknot/dname_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/dname_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/dname_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname_tests.Tpo $(DEPDIR)/dname_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/dname_tests.c' object='dname_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname_tests.obj `if test -f 'tests/libknot/libknot/dname_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/dname_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/dname_tests.c'; fi`
-
-dname_table_tests.o: tests/libknot/libknot/dname_table_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname_table_tests.o -MD -MP -MF $(DEPDIR)/dname_table_tests.Tpo -c -o dname_table_tests.o `test -f 'tests/libknot/libknot/dname_table_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/dname_table_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname_table_tests.Tpo $(DEPDIR)/dname_table_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/dname_table_tests.c' object='dname_table_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname_table_tests.o `test -f 'tests/libknot/libknot/dname_table_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/dname_table_tests.c
-
-dname_table_tests.obj: tests/libknot/libknot/dname_table_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname_table_tests.obj -MD -MP -MF $(DEPDIR)/dname_table_tests.Tpo -c -o dname_table_tests.obj `if test -f 'tests/libknot/libknot/dname_table_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/dname_table_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/dname_table_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname_table_tests.Tpo $(DEPDIR)/dname_table_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/dname_table_tests.c' object='dname_table_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname_table_tests.obj `if test -f 'tests/libknot/libknot/dname_table_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/dname_table_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/dname_table_tests.c'; fi`
-
-nsec3_tests.o: tests/libknot/libknot/nsec3_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nsec3_tests.o -MD -MP -MF $(DEPDIR)/nsec3_tests.Tpo -c -o nsec3_tests.o `test -f 'tests/libknot/libknot/nsec3_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/nsec3_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nsec3_tests.Tpo $(DEPDIR)/nsec3_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/nsec3_tests.c' object='nsec3_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nsec3_tests.o `test -f 'tests/libknot/libknot/nsec3_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/nsec3_tests.c
-
-nsec3_tests.obj: tests/libknot/libknot/nsec3_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nsec3_tests.obj -MD -MP -MF $(DEPDIR)/nsec3_tests.Tpo -c -o nsec3_tests.obj `if test -f 'tests/libknot/libknot/nsec3_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/nsec3_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/nsec3_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/nsec3_tests.Tpo $(DEPDIR)/nsec3_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/nsec3_tests.c' object='nsec3_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nsec3_tests.obj `if test -f 'tests/libknot/libknot/nsec3_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/nsec3_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/nsec3_tests.c'; fi`
-
-packet_tests.o: tests/libknot/libknot/packet_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet_tests.o -MD -MP -MF $(DEPDIR)/packet_tests.Tpo -c -o packet_tests.o `test -f 'tests/libknot/libknot/packet_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/packet_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet_tests.Tpo $(DEPDIR)/packet_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/packet_tests.c' object='packet_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet_tests.o `test -f 'tests/libknot/libknot/packet_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/packet_tests.c
-
-packet_tests.obj: tests/libknot/libknot/packet_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet_tests.obj -MD -MP -MF $(DEPDIR)/packet_tests.Tpo -c -o packet_tests.obj `if test -f 'tests/libknot/libknot/packet_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/packet_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/packet_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet_tests.Tpo $(DEPDIR)/packet_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/packet_tests.c' object='packet_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet_tests.obj `if test -f 'tests/libknot/libknot/packet_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/packet_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/packet_tests.c'; fi`
-
-query_tests.o: tests/libknot/libknot/query_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT query_tests.o -MD -MP -MF $(DEPDIR)/query_tests.Tpo -c -o query_tests.o `test -f 'tests/libknot/libknot/query_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/query_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/query_tests.Tpo $(DEPDIR)/query_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/query_tests.c' object='query_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o query_tests.o `test -f 'tests/libknot/libknot/query_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/query_tests.c
-
-query_tests.obj: tests/libknot/libknot/query_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT query_tests.obj -MD -MP -MF $(DEPDIR)/query_tests.Tpo -c -o query_tests.obj `if test -f 'tests/libknot/libknot/query_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/query_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/query_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/query_tests.Tpo $(DEPDIR)/query_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/query_tests.c' object='query_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o query_tests.obj `if test -f 'tests/libknot/libknot/query_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/query_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/query_tests.c'; fi`
-
-edns_tests.o: tests/libknot/libknot/edns_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT edns_tests.o -MD -MP -MF $(DEPDIR)/edns_tests.Tpo -c -o edns_tests.o `test -f 'tests/libknot/libknot/edns_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/edns_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/edns_tests.Tpo $(DEPDIR)/edns_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/edns_tests.c' object='edns_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o edns_tests.o `test -f 'tests/libknot/libknot/edns_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/edns_tests.c
-
-edns_tests.obj: tests/libknot/libknot/edns_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT edns_tests.obj -MD -MP -MF $(DEPDIR)/edns_tests.Tpo -c -o edns_tests.obj `if test -f 'tests/libknot/libknot/edns_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/edns_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/edns_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/edns_tests.Tpo $(DEPDIR)/edns_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/edns_tests.c' object='edns_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o edns_tests.obj `if test -f 'tests/libknot/libknot/edns_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/edns_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/edns_tests.c'; fi`
-
-node_tests.o: tests/libknot/libknot/node_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT node_tests.o -MD -MP -MF $(DEPDIR)/node_tests.Tpo -c -o node_tests.o `test -f 'tests/libknot/libknot/node_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/node_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/node_tests.Tpo $(DEPDIR)/node_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/node_tests.c' object='node_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o node_tests.o `test -f 'tests/libknot/libknot/node_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/node_tests.c
-
-node_tests.obj: tests/libknot/libknot/node_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT node_tests.obj -MD -MP -MF $(DEPDIR)/node_tests.Tpo -c -o node_tests.obj `if test -f 'tests/libknot/libknot/node_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/node_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/node_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/node_tests.Tpo $(DEPDIR)/node_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/node_tests.c' object='node_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o node_tests.obj `if test -f 'tests/libknot/libknot/node_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/node_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/node_tests.c'; fi`
-
-rdata_tests.o: tests/libknot/libknot/rdata_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rdata_tests.o -MD -MP -MF $(DEPDIR)/rdata_tests.Tpo -c -o rdata_tests.o `test -f 'tests/libknot/libknot/rdata_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/rdata_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rdata_tests.Tpo $(DEPDIR)/rdata_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/rdata_tests.c' object='rdata_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rdata_tests.o `test -f 'tests/libknot/libknot/rdata_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/rdata_tests.c
-
-rdata_tests.obj: tests/libknot/libknot/rdata_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rdata_tests.obj -MD -MP -MF $(DEPDIR)/rdata_tests.Tpo -c -o rdata_tests.obj `if test -f 'tests/libknot/libknot/rdata_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/rdata_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/rdata_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rdata_tests.Tpo $(DEPDIR)/rdata_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/rdata_tests.c' object='rdata_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rdata_tests.obj `if test -f 'tests/libknot/libknot/rdata_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/rdata_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/rdata_tests.c'; fi`
-
-rrset_tests.o: tests/libknot/libknot/rrset_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrset_tests.o -MD -MP -MF $(DEPDIR)/rrset_tests.Tpo -c -o rrset_tests.o `test -f 'tests/libknot/libknot/rrset_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/rrset_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrset_tests.Tpo $(DEPDIR)/rrset_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/rrset_tests.c' object='rrset_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrset_tests.o `test -f 'tests/libknot/libknot/rrset_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/rrset_tests.c
-
-rrset_tests.obj: tests/libknot/libknot/rrset_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrset_tests.obj -MD -MP -MF $(DEPDIR)/rrset_tests.Tpo -c -o rrset_tests.obj `if test -f 'tests/libknot/libknot/rrset_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/rrset_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/rrset_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrset_tests.Tpo $(DEPDIR)/rrset_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/rrset_tests.c' object='rrset_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrset_tests.obj `if test -f 'tests/libknot/libknot/rrset_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/rrset_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/rrset_tests.c'; fi`
-
-tsig_tests.o: tests/libknot/libknot/tsig_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsig_tests.o -MD -MP -MF $(DEPDIR)/tsig_tests.Tpo -c -o tsig_tests.o `test -f 'tests/libknot/libknot/tsig_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/tsig_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tsig_tests.Tpo $(DEPDIR)/tsig_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/tsig_tests.c' object='tsig_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsig_tests.o `test -f 'tests/libknot/libknot/tsig_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/tsig_tests.c
-
-tsig_tests.obj: tests/libknot/libknot/tsig_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tsig_tests.obj -MD -MP -MF $(DEPDIR)/tsig_tests.Tpo -c -o tsig_tests.obj `if test -f 'tests/libknot/libknot/tsig_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/tsig_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/tsig_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tsig_tests.Tpo $(DEPDIR)/tsig_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/tsig_tests.c' object='tsig_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tsig_tests.obj `if test -f 'tests/libknot/libknot/tsig_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/tsig_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/tsig_tests.c'; fi`
-
-zone_tests.o: tests/libknot/libknot/zone_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone_tests.o -MD -MP -MF $(DEPDIR)/zone_tests.Tpo -c -o zone_tests.o `test -f 'tests/libknot/libknot/zone_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/zone_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone_tests.Tpo $(DEPDIR)/zone_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/zone_tests.c' object='zone_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone_tests.o `test -f 'tests/libknot/libknot/zone_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/zone_tests.c
-
-zone_tests.obj: tests/libknot/libknot/zone_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone_tests.obj -MD -MP -MF $(DEPDIR)/zone_tests.Tpo -c -o zone_tests.obj `if test -f 'tests/libknot/libknot/zone_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/zone_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/zone_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone_tests.Tpo $(DEPDIR)/zone_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/zone_tests.c' object='zone_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone_tests.obj `if test -f 'tests/libknot/libknot/zone_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/zone_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/zone_tests.c'; fi`
-
-zone_tree_tests.o: tests/libknot/libknot/zone_tree_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone_tree_tests.o -MD -MP -MF $(DEPDIR)/zone_tree_tests.Tpo -c -o zone_tree_tests.o `test -f 'tests/libknot/libknot/zone_tree_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/zone_tree_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone_tree_tests.Tpo $(DEPDIR)/zone_tree_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/zone_tree_tests.c' object='zone_tree_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone_tree_tests.o `test -f 'tests/libknot/libknot/zone_tree_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/zone_tree_tests.c
-
-zone_tree_tests.obj: tests/libknot/libknot/zone_tree_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone_tree_tests.obj -MD -MP -MF $(DEPDIR)/zone_tree_tests.Tpo -c -o zone_tree_tests.obj `if test -f 'tests/libknot/libknot/zone_tree_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/zone_tree_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/zone_tree_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone_tree_tests.Tpo $(DEPDIR)/zone_tree_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/zone_tree_tests.c' object='zone_tree_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone_tree_tests.obj `if test -f 'tests/libknot/libknot/zone_tree_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/zone_tree_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/zone_tree_tests.c'; fi`
-
-zonedb_tests.o: tests/libknot/libknot/zonedb_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zonedb_tests.o -MD -MP -MF $(DEPDIR)/zonedb_tests.Tpo -c -o zonedb_tests.o `test -f 'tests/libknot/libknot/zonedb_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/zonedb_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zonedb_tests.Tpo $(DEPDIR)/zonedb_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/zonedb_tests.c' object='zonedb_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zonedb_tests.o `test -f 'tests/libknot/libknot/zonedb_tests.c' || echo '$(srcdir)/'`tests/libknot/libknot/zonedb_tests.c
-
-zonedb_tests.obj: tests/libknot/libknot/zonedb_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zonedb_tests.obj -MD -MP -MF $(DEPDIR)/zonedb_tests.Tpo -c -o zonedb_tests.obj `if test -f 'tests/libknot/libknot/zonedb_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/zonedb_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/zonedb_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zonedb_tests.Tpo $(DEPDIR)/zonedb_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/libknot/zonedb_tests.c' object='zonedb_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zonedb_tests.obj `if test -f 'tests/libknot/libknot/zonedb_tests.c'; then $(CYGPATH_W) 'tests/libknot/libknot/zonedb_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/libknot/zonedb_tests.c'; fi`
-
-unittests_libknot.o: tests/libknot/unittests_libknot.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_libknot.o -MD -MP -MF $(DEPDIR)/unittests_libknot.Tpo -c -o unittests_libknot.o `test -f 'tests/libknot/unittests_libknot.c' || echo '$(srcdir)/'`tests/libknot/unittests_libknot.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_libknot.Tpo $(DEPDIR)/unittests_libknot.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/unittests_libknot.c' object='unittests_libknot.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_libknot.o `test -f 'tests/libknot/unittests_libknot.c' || echo '$(srcdir)/'`tests/libknot/unittests_libknot.c
-
-unittests_libknot.obj: tests/libknot/unittests_libknot.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_libknot.obj -MD -MP -MF $(DEPDIR)/unittests_libknot.Tpo -c -o unittests_libknot.obj `if test -f 'tests/libknot/unittests_libknot.c'; then $(CYGPATH_W) 'tests/libknot/unittests_libknot.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/unittests_libknot.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_libknot.Tpo $(DEPDIR)/unittests_libknot.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/unittests_libknot.c' object='unittests_libknot.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_libknot.obj `if test -f 'tests/libknot/unittests_libknot.c'; then $(CYGPATH_W) 'tests/libknot/unittests_libknot.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/unittests_libknot.c'; fi`
-
-dname_tests_realdata.o: tests/libknot/realdata/libknot/dname_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname_tests_realdata.o -MD -MP -MF $(DEPDIR)/dname_tests_realdata.Tpo -c -o dname_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/dname_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/dname_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname_tests_realdata.Tpo $(DEPDIR)/dname_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/dname_tests_realdata.c' object='dname_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/dname_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/dname_tests_realdata.c
-
-dname_tests_realdata.obj: tests/libknot/realdata/libknot/dname_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dname_tests_realdata.obj -MD -MP -MF $(DEPDIR)/dname_tests_realdata.Tpo -c -o dname_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/dname_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/dname_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/dname_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dname_tests_realdata.Tpo $(DEPDIR)/dname_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/dname_tests_realdata.c' object='dname_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o dname_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/dname_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/dname_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/dname_tests_realdata.c'; fi`
-
-response_tests_realdata.o: tests/libknot/realdata/libknot/response_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT response_tests_realdata.o -MD -MP -MF $(DEPDIR)/response_tests_realdata.Tpo -c -o response_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/response_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/response_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/response_tests_realdata.Tpo $(DEPDIR)/response_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/response_tests_realdata.c' object='response_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o response_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/response_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/response_tests_realdata.c
-
-response_tests_realdata.obj: tests/libknot/realdata/libknot/response_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT response_tests_realdata.obj -MD -MP -MF $(DEPDIR)/response_tests_realdata.Tpo -c -o response_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/response_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/response_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/response_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/response_tests_realdata.Tpo $(DEPDIR)/response_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/response_tests_realdata.c' object='response_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o response_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/response_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/response_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/response_tests_realdata.c'; fi`
-
-edns_tests_realdata.o: tests/libknot/realdata/libknot/edns_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT edns_tests_realdata.o -MD -MP -MF $(DEPDIR)/edns_tests_realdata.Tpo -c -o edns_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/edns_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/edns_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/edns_tests_realdata.Tpo $(DEPDIR)/edns_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/edns_tests_realdata.c' object='edns_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o edns_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/edns_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/edns_tests_realdata.c
-
-edns_tests_realdata.obj: tests/libknot/realdata/libknot/edns_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT edns_tests_realdata.obj -MD -MP -MF $(DEPDIR)/edns_tests_realdata.Tpo -c -o edns_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/edns_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/edns_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/edns_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/edns_tests_realdata.Tpo $(DEPDIR)/edns_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/edns_tests_realdata.c' object='edns_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o edns_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/edns_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/edns_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/edns_tests_realdata.c'; fi`
-
-node_tests_realdata.o: tests/libknot/realdata/libknot/node_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT node_tests_realdata.o -MD -MP -MF $(DEPDIR)/node_tests_realdata.Tpo -c -o node_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/node_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/node_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/node_tests_realdata.Tpo $(DEPDIR)/node_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/node_tests_realdata.c' object='node_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o node_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/node_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/node_tests_realdata.c
-
-node_tests_realdata.obj: tests/libknot/realdata/libknot/node_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT node_tests_realdata.obj -MD -MP -MF $(DEPDIR)/node_tests_realdata.Tpo -c -o node_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/node_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/node_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/node_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/node_tests_realdata.Tpo $(DEPDIR)/node_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/node_tests_realdata.c' object='node_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o node_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/node_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/node_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/node_tests_realdata.c'; fi`
-
-rdata_tests_realdata.o: tests/libknot/realdata/libknot/rdata_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rdata_tests_realdata.o -MD -MP -MF $(DEPDIR)/rdata_tests_realdata.Tpo -c -o rdata_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/rdata_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/rdata_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rdata_tests_realdata.Tpo $(DEPDIR)/rdata_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/rdata_tests_realdata.c' object='rdata_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rdata_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/rdata_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/rdata_tests_realdata.c
-
-rdata_tests_realdata.obj: tests/libknot/realdata/libknot/rdata_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rdata_tests_realdata.obj -MD -MP -MF $(DEPDIR)/rdata_tests_realdata.Tpo -c -o rdata_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/rdata_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/rdata_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/rdata_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rdata_tests_realdata.Tpo $(DEPDIR)/rdata_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/rdata_tests_realdata.c' object='rdata_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rdata_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/rdata_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/rdata_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/rdata_tests_realdata.c'; fi`
-
-rrset_tests_realdata.o: tests/libknot/realdata/libknot/rrset_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrset_tests_realdata.o -MD -MP -MF $(DEPDIR)/rrset_tests_realdata.Tpo -c -o rrset_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/rrset_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/rrset_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrset_tests_realdata.Tpo $(DEPDIR)/rrset_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/rrset_tests_realdata.c' object='rrset_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrset_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/rrset_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/rrset_tests_realdata.c
-
-rrset_tests_realdata.obj: tests/libknot/realdata/libknot/rrset_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rrset_tests_realdata.obj -MD -MP -MF $(DEPDIR)/rrset_tests_realdata.Tpo -c -o rrset_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/rrset_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/rrset_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/rrset_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rrset_tests_realdata.Tpo $(DEPDIR)/rrset_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/rrset_tests_realdata.c' object='rrset_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o rrset_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/rrset_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/rrset_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/rrset_tests_realdata.c'; fi`
-
-zone_tests_realdata.o: tests/libknot/realdata/libknot/zone_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone_tests_realdata.o -MD -MP -MF $(DEPDIR)/zone_tests_realdata.Tpo -c -o zone_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/zone_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/zone_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone_tests_realdata.Tpo $(DEPDIR)/zone_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/zone_tests_realdata.c' object='zone_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/zone_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/zone_tests_realdata.c
-
-zone_tests_realdata.obj: tests/libknot/realdata/libknot/zone_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zone_tests_realdata.obj -MD -MP -MF $(DEPDIR)/zone_tests_realdata.Tpo -c -o zone_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/zone_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/zone_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/zone_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zone_tests_realdata.Tpo $(DEPDIR)/zone_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/zone_tests_realdata.c' object='zone_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zone_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/zone_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/zone_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/zone_tests_realdata.c'; fi`
-
-zonedb_tests_realdata.o: tests/libknot/realdata/libknot/zonedb_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zonedb_tests_realdata.o -MD -MP -MF $(DEPDIR)/zonedb_tests_realdata.Tpo -c -o zonedb_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/zonedb_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/zonedb_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zonedb_tests_realdata.Tpo $(DEPDIR)/zonedb_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/zonedb_tests_realdata.c' object='zonedb_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zonedb_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/zonedb_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/zonedb_tests_realdata.c
-
-zonedb_tests_realdata.obj: tests/libknot/realdata/libknot/zonedb_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT zonedb_tests_realdata.obj -MD -MP -MF $(DEPDIR)/zonedb_tests_realdata.Tpo -c -o zonedb_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/zonedb_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/zonedb_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/zonedb_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/zonedb_tests_realdata.Tpo $(DEPDIR)/zonedb_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/zonedb_tests_realdata.c' object='zonedb_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o zonedb_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/zonedb_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/zonedb_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/zonedb_tests_realdata.c'; fi`
-
-packet_tests_realdata.o: tests/libknot/realdata/libknot/packet_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet_tests_realdata.o -MD -MP -MF $(DEPDIR)/packet_tests_realdata.Tpo -c -o packet_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/packet_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/packet_tests_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet_tests_realdata.Tpo $(DEPDIR)/packet_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/packet_tests_realdata.c' object='packet_tests_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet_tests_realdata.o `test -f 'tests/libknot/realdata/libknot/packet_tests_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot/packet_tests_realdata.c
-
-packet_tests_realdata.obj: tests/libknot/realdata/libknot/packet_tests_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT packet_tests_realdata.obj -MD -MP -MF $(DEPDIR)/packet_tests_realdata.Tpo -c -o packet_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/packet_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/packet_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/packet_tests_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/packet_tests_realdata.Tpo $(DEPDIR)/packet_tests_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot/packet_tests_realdata.c' object='packet_tests_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o packet_tests_realdata.obj `if test -f 'tests/libknot/realdata/libknot/packet_tests_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot/packet_tests_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot/packet_tests_realdata.c'; fi`
-
-libknot_tests_loader_realdata.o: tests/libknot/realdata/libknot_tests_loader_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libknot_tests_loader_realdata.o -MD -MP -MF $(DEPDIR)/libknot_tests_loader_realdata.Tpo -c -o libknot_tests_loader_realdata.o `test -f 'tests/libknot/realdata/libknot_tests_loader_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot_tests_loader_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libknot_tests_loader_realdata.Tpo $(DEPDIR)/libknot_tests_loader_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot_tests_loader_realdata.c' object='libknot_tests_loader_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libknot_tests_loader_realdata.o `test -f 'tests/libknot/realdata/libknot_tests_loader_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/libknot_tests_loader_realdata.c
-
-libknot_tests_loader_realdata.obj: tests/libknot/realdata/libknot_tests_loader_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libknot_tests_loader_realdata.obj -MD -MP -MF $(DEPDIR)/libknot_tests_loader_realdata.Tpo -c -o libknot_tests_loader_realdata.obj `if test -f 'tests/libknot/realdata/libknot_tests_loader_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot_tests_loader_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot_tests_loader_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libknot_tests_loader_realdata.Tpo $(DEPDIR)/libknot_tests_loader_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/libknot_tests_loader_realdata.c' object='libknot_tests_loader_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libknot_tests_loader_realdata.obj `if test -f 'tests/libknot/realdata/libknot_tests_loader_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/libknot_tests_loader_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/libknot_tests_loader_realdata.c'; fi`
-
-unittests_libknot_realdata.o: tests/libknot/realdata/unittests_libknot_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_libknot_realdata.o -MD -MP -MF $(DEPDIR)/unittests_libknot_realdata.Tpo -c -o unittests_libknot_realdata.o `test -f 'tests/libknot/realdata/unittests_libknot_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/unittests_libknot_realdata.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_libknot_realdata.Tpo $(DEPDIR)/unittests_libknot_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/unittests_libknot_realdata.c' object='unittests_libknot_realdata.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_libknot_realdata.o `test -f 'tests/libknot/realdata/unittests_libknot_realdata.c' || echo '$(srcdir)/'`tests/libknot/realdata/unittests_libknot_realdata.c
-
-unittests_libknot_realdata.obj: tests/libknot/realdata/unittests_libknot_realdata.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_libknot_realdata.obj -MD -MP -MF $(DEPDIR)/unittests_libknot_realdata.Tpo -c -o unittests_libknot_realdata.obj `if test -f 'tests/libknot/realdata/unittests_libknot_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/unittests_libknot_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/unittests_libknot_realdata.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_libknot_realdata.Tpo $(DEPDIR)/unittests_libknot_realdata.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/libknot/realdata/unittests_libknot_realdata.c' object='unittests_libknot_realdata.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_libknot_realdata.obj `if test -f 'tests/libknot/realdata/unittests_libknot_realdata.c'; then $(CYGPATH_W) 'tests/libknot/realdata/unittests_libknot_realdata.c'; else $(CYGPATH_W) '$(srcdir)/tests/libknot/realdata/unittests_libknot_realdata.c'; fi`
-
-xfr_tests.o: tests/xfr_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xfr_tests.o -MD -MP -MF $(DEPDIR)/xfr_tests.Tpo -c -o xfr_tests.o `test -f 'tests/xfr_tests.c' || echo '$(srcdir)/'`tests/xfr_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xfr_tests.Tpo $(DEPDIR)/xfr_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/xfr_tests.c' object='xfr_tests.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xfr_tests.o `test -f 'tests/xfr_tests.c' || echo '$(srcdir)/'`tests/xfr_tests.c
-
-xfr_tests.obj: tests/xfr_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT xfr_tests.obj -MD -MP -MF $(DEPDIR)/xfr_tests.Tpo -c -o xfr_tests.obj `if test -f 'tests/xfr_tests.c'; then $(CYGPATH_W) 'tests/xfr_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/xfr_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/xfr_tests.Tpo $(DEPDIR)/xfr_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/xfr_tests.c' object='xfr_tests.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o xfr_tests.obj `if test -f 'tests/xfr_tests.c'; then $(CYGPATH_W) 'tests/xfr_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/xfr_tests.c'; fi`
-
-unittests_zp_main.o: zcompile/tests/unittests_zp_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_zp_main.o -MD -MP -MF $(DEPDIR)/unittests_zp_main.Tpo -c -o unittests_zp_main.o `test -f 'zcompile/tests/unittests_zp_main.c' || echo '$(srcdir)/'`zcompile/tests/unittests_zp_main.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_zp_main.Tpo $(DEPDIR)/unittests_zp_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/tests/unittests_zp_main.c' object='unittests_zp_main.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_zp_main.o `test -f 'zcompile/tests/unittests_zp_main.c' || echo '$(srcdir)/'`zcompile/tests/unittests_zp_main.c
-
-unittests_zp_main.obj: zcompile/tests/unittests_zp_main.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT unittests_zp_main.obj -MD -MP -MF $(DEPDIR)/unittests_zp_main.Tpo -c -o unittests_zp_main.obj `if test -f 'zcompile/tests/unittests_zp_main.c'; then $(CYGPATH_W) 'zcompile/tests/unittests_zp_main.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/tests/unittests_zp_main.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/unittests_zp_main.Tpo $(DEPDIR)/unittests_zp_main.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='zcompile/tests/unittests_zp_main.c' object='unittests_zp_main.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o unittests_zp_main.obj `if test -f 'zcompile/tests/unittests_zp_main.c'; then $(CYGPATH_W) 'zcompile/tests/unittests_zp_main.c'; else $(CYGPATH_W) '$(srcdir)/zcompile/tests/unittests_zp_main.c'; fi`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
.l.c:
- $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
-
-libknotd_la-cf-lex.c: knot/conf/cf-lex.l
- \
- $(am__skiplex) \
- $(SHELL) $(YLWRAP) `test -f 'knot/conf/cf-lex.l' || echo '$(srcdir)/'`knot/conf/cf-lex.l $(LEX_OUTPUT_ROOT).c libknotd_la-cf-lex.c -- $(LEX) $(libknotd_la_LFLAGS) $(LFLAGS)
+ $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE)
-zlexer.c: zcompile/zlexer.l
- \
+knot/conf/libknotd_la-cf-lex.c: knot/conf/cf-lex.l
+ $(AM_V_LEX) \
$(am__skiplex) \
- $(SHELL) $(YLWRAP) `test -f 'zcompile/zlexer.l' || echo '$(srcdir)/'`zcompile/zlexer.l $(LEX_OUTPUT_ROOT).c zlexer.c -- $(LEX) $(AM_LFLAGS) $(LFLAGS)
+ $(SHELL) $(YLWRAP) `test -f 'knot/conf/cf-lex.l' || echo '$(srcdir)/'`knot/conf/cf-lex.l $(LEX_OUTPUT_ROOT).c knot/conf/libknotd_la-cf-lex.c -- $(LEX) $(libknotd_la_LFLAGS) $(LFLAGS)
.y.c:
- $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE)
+ $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE)
-libknotd_la-cf-parse.c: knot/conf/cf-parse.y
- \
+knot/conf/libknotd_la-cf-parse.c: knot/conf/cf-parse.y
+ $(AM_V_YACC) \
$(am__skipyacc) \
- $(SHELL) $(YLWRAP) `test -f 'knot/conf/cf-parse.y' || echo '$(srcdir)/'`knot/conf/cf-parse.y y.tab.c libknotd_la-cf-parse.c y.tab.h `echo libknotd_la-cf-parse.c | $(am__yacc_c2h)` y.output libknotd_la-cf-parse.output -- $(YACC) $(libknotd_la_YFLAGS) $(YFLAGS)
-
-zparser.c: zcompile/zparser.y
- \
- $(am__skipyacc) \
- $(SHELL) $(YLWRAP) `test -f 'zcompile/zparser.y' || echo '$(srcdir)/'`zcompile/zparser.y y.tab.c zparser.c y.tab.h `echo zparser.c | $(am__yacc_c2h)` y.output zparser.output -- $(YACC) $(AM_YFLAGS) $(YFLAGS)
+ $(SHELL) $(YLWRAP) `test -f 'knot/conf/cf-parse.y' || echo '$(srcdir)/'`knot/conf/cf-parse.y y.tab.c knot/conf/libknotd_la-cf-parse.c y.tab.h knot/conf/libknotd_la-cf-parse.h y.output knot/conf/libknotd_la-cf-parse.output -- $(YACC) $(libknotd_la_YFLAGS) $(YFLAGS)
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
-install-man5: $(dist_man_MANS)
- @$(NORMAL_INSTALL)
- @list1=''; \
- list2='$(dist_man_MANS)'; \
- test -n "$(man5dir)" \
- && test -n "`echo $$list1$$list2`" \
- || exit 0; \
- echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \
- { for i in $$list1; do echo "$$i"; done; \
- if test -n "$$list2"; then \
- for i in $$list2; do echo "$$i"; done \
- | sed -n '/\.5[a-z]*$$/p'; \
- fi; \
- } | while read p; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; echo "$$p"; \
- done | \
- sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
- sed 'N;N;s,\n, ,g' | { \
- list=; while read file base inst; do \
- if test "$$base" = "$$inst"; then list="$$list $$file"; else \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \
+ -rm -rf common/.libs common/_libs
+ -rm -rf common/hattrie/.libs common/hattrie/_libs
+ -rm -rf common/libtap/.libs common/libtap/_libs
+ -rm -rf common/slab/.libs common/slab/_libs
+ -rm -rf knot/conf/.libs knot/conf/_libs
+ -rm -rf knot/ctl/.libs knot/ctl/_libs
+ -rm -rf knot/server/.libs knot/server/_libs
+ -rm -rf knot/stat/.libs knot/stat/_libs
+ -rm -rf knot/zone/.libs knot/zone/_libs
+ -rm -rf libknot/.libs libknot/_libs
+ -rm -rf libknot/nameserver/.libs libknot/nameserver/_libs
+ -rm -rf libknot/packet/.libs libknot/packet/_libs
+ -rm -rf libknot/sign/.libs libknot/sign/_libs
+ -rm -rf libknot/updates/.libs libknot/updates/_libs
+ -rm -rf libknot/util/.libs libknot/util/_libs
+ -rm -rf libknot/zone/.libs libknot/zone/_libs
+ -rm -rf zscanner/.libs zscanner/_libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
done; \
- for i in $$list; do echo "$$i"; done | $(am__base_list) | \
- while read files; do \
- test -z "$$files" || { \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \
- done; }
-
-uninstall-man5:
- @$(NORMAL_UNINSTALL)
- @list=''; test -n "$(man5dir)" || exit 0; \
- files=`{ for i in $$list; do echo "$$i"; done; \
- l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.5[a-z]*$$/p'; \
- } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir)
-install-man8: $(dist_man_MANS)
- @$(NORMAL_INSTALL)
- @list1=''; \
- list2='$(dist_man_MANS)'; \
- test -n "$(man8dir)" \
- && test -n "`echo $$list1$$list2`" \
- || exit 0; \
- echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \
- { for i in $$list1; do echo "$$i"; done; \
- if test -n "$$list2"; then \
- for i in $$list2; do echo "$$i"; done \
- | sed -n '/\.8[a-z]*$$/p'; \
- fi; \
- } | while read p; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- echo "$$d$$p"; echo "$$p"; \
- done | \
- sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
- sed 'N;N;s,\n, ,g' | { \
- list=; while read file base inst; do \
- if test "$$base" = "$$inst"; then list="$$list $$file"; else \
- echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
- $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
fi; \
done; \
- for i in $$list; do echo "$$i"; done | $(am__base_list) | \
- while read files; do \
- test -z "$$files" || { \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
- done; }
-
-uninstall-man8:
- @$(NORMAL_UNINSTALL)
- @list=''; test -n "$(man8dir)" || exit 0; \
- files=`{ for i in $$list; do echo "$$i"; done; \
- l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
- sed -n '/\.8[a-z]*$$/p'; \
- } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
- -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
- dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@@ -2350,10 +1706,23 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
mkid -fID $$unique
tags: TAGS
-TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
@@ -2372,7 +1741,7 @@ TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
fi; \
fi
ctags: CTAGS
-CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
@@ -2389,37 +1758,10 @@ GTAGS:
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
-cscopelist: $(HEADERS) $(SOURCES) $(LISP)
- list='$(SOURCES) $(HEADERS) $(LISP)'; \
- case "$(srcdir)" in \
- [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
- *) sdir=$(subdir)/$(srcdir) ;; \
- esac; \
- for i in $$list; do \
- if test -f "$$i"; then \
- echo "$(subdir)/$$i"; \
- else \
- echo "$$sdir/$$i"; \
- fi; \
- done >> $(top_builddir)/cscope.files
-
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
- @list='$(MANS)'; if test -n "$$list"; then \
- list=`for p in $$list; do \
- if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
- if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \
- if test -n "$$list" && \
- grep 'ab help2man is required to generate this page' $$list >/dev/null; then \
- echo "error: found man pages containing the 'missing help2man' replacement text:" >&2; \
- grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \
- echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \
- echo " typically 'make maintainer-clean' will remove them" >&2; \
- exit 1; \
- else :; fi; \
- else :; fi
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
@@ -2449,24 +1791,50 @@ distdir: $(DISTFILES)
|| exit 1; \
fi; \
done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
check-am: all-am
check: $(BUILT_SOURCES)
- $(MAKE) $(AM_MAKEFLAGS) check-am
-all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) config.h
-installdirs:
- for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man8dir)"; do \
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) config.h
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: $(BUILT_SOURCES)
- $(MAKE) $(AM_MAKEFLAGS) install-am
-install-exec: install-exec-am
-install-data: install-data-am
-uninstall: uninstall-am
+ $(MAKE) $(AM_MAKEFLAGS) install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
-installcheck: installcheck-am
+installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
@@ -2485,135 +1853,164 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f common/$(DEPDIR)/$(am__dirstamp)
+ -rm -f common/$(am__dirstamp)
+ -rm -f common/hattrie/$(DEPDIR)/$(am__dirstamp)
+ -rm -f common/hattrie/$(am__dirstamp)
+ -rm -f common/libtap/$(DEPDIR)/$(am__dirstamp)
+ -rm -f common/libtap/$(am__dirstamp)
+ -rm -f common/slab/$(DEPDIR)/$(am__dirstamp)
+ -rm -f common/slab/$(am__dirstamp)
+ -rm -f knot/$(DEPDIR)/$(am__dirstamp)
+ -rm -f knot/$(am__dirstamp)
+ -rm -f knot/conf/$(DEPDIR)/$(am__dirstamp)
+ -rm -f knot/conf/$(am__dirstamp)
+ -rm -f knot/ctl/$(DEPDIR)/$(am__dirstamp)
+ -rm -f knot/ctl/$(am__dirstamp)
+ -rm -f knot/server/$(DEPDIR)/$(am__dirstamp)
+ -rm -f knot/server/$(am__dirstamp)
+ -rm -f knot/stat/$(DEPDIR)/$(am__dirstamp)
+ -rm -f knot/stat/$(am__dirstamp)
+ -rm -f knot/zone/$(DEPDIR)/$(am__dirstamp)
+ -rm -f knot/zone/$(am__dirstamp)
+ -rm -f libknot/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/$(am__dirstamp)
+ -rm -f libknot/nameserver/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/nameserver/$(am__dirstamp)
+ -rm -f libknot/packet/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/packet/$(am__dirstamp)
+ -rm -f libknot/sign/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/sign/$(am__dirstamp)
+ -rm -f libknot/updates/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/updates/$(am__dirstamp)
+ -rm -f libknot/util/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/util/$(am__dirstamp)
+ -rm -f libknot/zone/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/zone/$(am__dirstamp)
+ -rm -f utils/common/$(DEPDIR)/$(am__dirstamp)
+ -rm -f utils/common/$(am__dirstamp)
+ -rm -f utils/dig/$(DEPDIR)/$(am__dirstamp)
+ -rm -f utils/dig/$(am__dirstamp)
+ -rm -f utils/host/$(DEPDIR)/$(am__dirstamp)
+ -rm -f utils/host/$(am__dirstamp)
+ -rm -f utils/nsupdate/$(DEPDIR)/$(am__dirstamp)
+ -rm -f utils/nsupdate/$(am__dirstamp)
+ -rm -f zscanner/$(DEPDIR)/$(am__dirstamp)
+ -rm -f zscanner/$(am__dirstamp)
+ -rm -f zscanner/test/$(DEPDIR)/$(am__dirstamp)
+ -rm -f zscanner/test/$(am__dirstamp)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
- -rm -f libknotd_la-cf-lex.c
- -rm -f libknotd_la-cf-parse.c
- -rm -f libknotd_la-cf-parse.h
- -rm -f zlexer.c
- -rm -f zparser.c
- -rm -f zparser.h
+ -rm -f knot/conf/libknotd_la-cf-lex.c
+ -rm -f knot/conf/libknotd_la-cf-parse.c
+ -rm -f knot/conf/libknotd_la-cf-parse.h
-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
-clean: clean-am
+clean: clean-recursive
-clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \
- clean-noinstLTLIBRARIES clean-sbinPROGRAMS mostlyclean-am
+clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
+ clean-sbinPROGRAMS mostlyclean-am
-distclean: distclean-am
- -rm -rf ./$(DEPDIR)
+distclean: distclean-recursive
+ -rm -rf common/$(DEPDIR) common/hattrie/$(DEPDIR) common/libtap/$(DEPDIR) common/slab/$(DEPDIR) knot/$(DEPDIR) knot/conf/$(DEPDIR) knot/ctl/$(DEPDIR) knot/server/$(DEPDIR) knot/stat/$(DEPDIR) knot/zone/$(DEPDIR) libknot/$(DEPDIR) libknot/nameserver/$(DEPDIR) libknot/packet/$(DEPDIR) libknot/sign/$(DEPDIR) libknot/updates/$(DEPDIR) libknot/util/$(DEPDIR) libknot/zone/$(DEPDIR) utils/common/$(DEPDIR) utils/dig/$(DEPDIR) utils/host/$(DEPDIR) utils/nsupdate/$(DEPDIR) zscanner/$(DEPDIR) zscanner/test/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-tags
-dvi: dvi-am
+dvi: dvi-recursive
dvi-am:
-html: html-am
+html: html-recursive
html-am:
-info: info-am
+info: info-recursive
info-am:
-install-data-am: install-man
-
-install-dvi: install-dvi-am
+install-data-am:
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+install-dvi: install-dvi-recursive
install-dvi-am:
-install-exec-am: install-libexecPROGRAMS install-sbinPROGRAMS
+install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
-install-html: install-html-am
+install-html: install-html-recursive
install-html-am:
-install-info: install-info-am
+install-info: install-info-recursive
install-info-am:
-install-man: install-man5 install-man8
+install-man:
-install-pdf: install-pdf-am
+install-pdf: install-pdf-recursive
install-pdf-am:
-install-ps: install-ps-am
+install-ps: install-ps-recursive
install-ps-am:
-installcheck-am:
+installcheck-am: installcheck-binPROGRAMS installcheck-sbinPROGRAMS
-maintainer-clean: maintainer-clean-am
- -rm -rf ./$(DEPDIR)
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf common/$(DEPDIR) common/hattrie/$(DEPDIR) common/libtap/$(DEPDIR) common/slab/$(DEPDIR) knot/$(DEPDIR) knot/conf/$(DEPDIR) knot/ctl/$(DEPDIR) knot/server/$(DEPDIR) knot/stat/$(DEPDIR) knot/zone/$(DEPDIR) libknot/$(DEPDIR) libknot/nameserver/$(DEPDIR) libknot/packet/$(DEPDIR) libknot/sign/$(DEPDIR) libknot/updates/$(DEPDIR) libknot/util/$(DEPDIR) libknot/zone/$(DEPDIR) utils/common/$(DEPDIR) utils/dig/$(DEPDIR) utils/host/$(DEPDIR) utils/nsupdate/$(DEPDIR) zscanner/$(DEPDIR) zscanner/test/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
-mostlyclean: mostlyclean-am
+mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
-pdf: pdf-am
+pdf: pdf-recursive
pdf-am:
-ps: ps-am
+ps: ps-recursive
ps-am:
-uninstall-am: uninstall-libexecPROGRAMS uninstall-man \
- uninstall-sbinPROGRAMS
-
-uninstall-man: uninstall-man5 uninstall-man8
+uninstall-am: uninstall-binPROGRAMS uninstall-sbinPROGRAMS
-.MAKE: all check install install-am install-strip
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check \
+ ctags-recursive install install-am install-data-am \
+ install-strip tags-recursive
-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
- clean-libexecPROGRAMS clean-libtool clean-noinstLTLIBRARIES \
- clean-sbinPROGRAMS cscopelist ctags distclean \
- distclean-compile distclean-generic distclean-hdr \
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-binPROGRAMS \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-noinstPROGRAMS clean-sbinPROGRAMS ctags ctags-recursive \
+ distclean distclean-compile distclean-generic distclean-hdr \
distclean-libtool distclean-tags distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-libexecPROGRAMS install-man \
- install-man5 install-man8 install-pdf install-pdf-am \
- install-ps install-ps-am install-sbinPROGRAMS install-strip \
- installcheck installcheck-am installdirs maintainer-clean \
- maintainer-clean-generic mostlyclean mostlyclean-compile \
- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
- tags uninstall uninstall-am uninstall-libexecPROGRAMS \
- uninstall-man uninstall-man5 uninstall-man8 \
- uninstall-sbinPROGRAMS
-
-
-# automake complains on % rules:
-# `%'-style pattern rules are a GNU make extension
-
-tests/libknot/parsed_data.rc: tests/libknot/files/parsed_data
- ../resource.sh tests/libknot/files/parsed_data >$@
-
-tests/libknot/realdata/parsed_data.rc: tests/libknot/realdata/files/parsed_data
- ../resource.sh tests/libknot/realdata/files/parsed_data >$@
-
-tests/libknot/parsed_data_queries.rc: tests/libknot/files/parsed_data_queries
- ../resource.sh tests/libknot/files/parsed_data_queries >$@
-
-tests/libknot/raw_data_queries.rc: tests/libknot/files/raw_data_queries
- ../resource.sh tests/libknot/files/raw_data_queries >$@
-
-tests/libknot/raw_data.rc: tests/libknot/files/raw_data
- ../resource.sh tests/libknot/files/raw_data >$@
-
-tests/libknot/realdata/raw_data.rc: tests/libknot/realdata/files/raw_data
- ../resource.sh tests/libknot/realdata/files/raw_data >$@
-
-tests/sample_conf.rc: tests/files/sample_conf
- ../resource.sh tests/files/sample_conf >$@
+ html-am info info-am install install-am install-binPROGRAMS \
+ install-data install-data-am install-data-hook install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-sbinPROGRAMS install-strip installcheck \
+ installcheck-am installcheck-binPROGRAMS \
+ installcheck-sbinPROGRAMS installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-binPROGRAMS uninstall-sbinPROGRAMS
+
+
+@HAVE_RAGEL_TRUE@zscanner/scanner.c: zscanner/scanner.rl zscanner/scanner_body.rl
+@HAVE_RAGEL_TRUE@ $(RAGEL) $(FSM_TYPE) -s -o $@ $(srcdir)/zscanner/scanner.rl
+
+# Create storage and run-time directories
+install-data-hook:
+ $(INSTALL) -d $(DESTDIR)/@run_dir@
+ $(INSTALL) -d $(DESTDIR)/@storage_dir@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/common/LICENSE.txt b/src/common/LICENSE.txt
deleted file mode 100644
index 15e3bef..0000000
--- a/src/common/LICENSE.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Copyright (c) 2007, 2008 Mutsuo Saito, Makoto Matsumoto and Hiroshima
-University. 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 the Hiroshima University nor the names of
- its contributors may be used to endorse or promote products
- derived from this software without specific prior written
- permission.
-
-THIS SOFTWARE IS PROVIDED BY THE 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/src/common/acl.c b/src/common/acl.c
index 252f3f9..26d3847 100644
--- a/src/common/acl.c
+++ b/src/common/acl.c
@@ -54,8 +54,8 @@ static int acl_compare(void *k1, void *k2)
}
/* Compare integers if IPv4. */
- if (a1->family == AF_INET) {
-
+ if (sockaddr_family(a1) == AF_INET) {
+
/* Compute mask .*/
uint32_t mask = acl_fill_mask32(a1->prefix);
@@ -69,21 +69,21 @@ static int acl_compare(void *k1, void *k2)
/* IPv6 matching. */
#ifndef DISABLE_IPV6
- if (a1->family == AF_INET6) {
-
+ if (sockaddr_family(a1) == AF_INET6) {
+
/* Get mask .*/
short chunk = a1->prefix;
-
+
/* Compare address by 32bit chunks. */
uint32_t* a1p = (uint32_t *)(&a1->addr6.sin6_addr);
uint32_t* a2p = (uint32_t *)(&a2->addr6.sin6_addr);
-
+
/* Mask 0 = 0 bits to compare from LO->HO (in big-endian).
* Mask 128 = 128 bits to compare.
*/
while (chunk > 0) {
uint32_t mask = 0xffffffff;
- if (chunk > sizeof(mask) << 3) {
+ if ((size_t)chunk > sizeof(mask) << 3) {
chunk -= sizeof(mask) << 3;
} else {
mask = acl_fill_mask32(chunk);
@@ -125,7 +125,7 @@ acl_t *acl_new(acl_rule_t default_rule, const char *name)
free(acl);
return 0;
}
-
+
/* Initialize skip list for rules with TSIG. */
/*! \todo This needs a better structure to make
* nodes with TSIG preferred, but for now
@@ -172,13 +172,12 @@ int acl_create(acl_t *acl, const sockaddr_t* addr, acl_rule_t rule, void *val,
if (key == NULL) {
return ACL_ERROR;
}
-
+
memcpy(&key->addr, addr, sizeof(sockaddr_t));
- sockaddr_update(&key->addr);
key->rule = rule;
key->val = val;
-
+
if (flags & ACL_PREFER) {
skip_insert(acl->rules_pref, &key->addr, key, 0);
} else {
@@ -198,12 +197,12 @@ int acl_match(acl_t *acl, const sockaddr_t* addr, acl_key_t **key)
if (found == NULL) {
found = skip_find(acl->rules, (void*)addr);
}
-
+
/* Set stored value if exists. */
if (key != NULL) {
*key = found;
}
-
+
/* Return appropriate rule. */
if (found == NULL) {
return acl->default_rule;
diff --git a/src/common/atomic.h b/src/common/atomic.h
new file mode 100644
index 0000000..17cd4e5
--- /dev/null
+++ b/src/common/atomic.h
@@ -0,0 +1,141 @@
+/* Copyright (C) 2011 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 atomic.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief Compatibility layer for atomic operations.
+ *
+ * Supports both __atomic and __sync legacy code.
+ * Based on the code bits from queue by Rusty Russel <rusty@rustcorp.com.au>.
+ *
+ * \addtogroup common_lib
+ * @{
+ */
+
+#ifndef _KNOTD_ATOMIC_H_
+#define _KNOTD_ATOMIC_H_
+
+#include <stdbool.h>
+#if defined(__ATOMIC_SEQ_CST) /* GCC4.7+ supports C11 atomics. */
+
+static inline unsigned int read_once(unsigned int *ptr, int memmodel)
+{
+ return __atomic_load_n(ptr, memmodel);
+}
+
+static inline void *read_ptr(void **ptr, int memmodel)
+{
+ return __atomic_load_n(ptr, memmodel);
+}
+
+static inline void store_once(unsigned int *ptr, unsigned int val, int memmodel)
+{
+ __atomic_store_n(ptr, val, memmodel);
+}
+
+static inline void store_ptr(void **ptr, void *val, int memmodel)
+{
+ __atomic_store_n(ptr, val, memmodel);
+}
+
+static inline void atomic_inc(unsigned int *val, int memmodel)
+{
+ __atomic_add_fetch(val, 1, memmodel);
+}
+
+static inline void atomic_dec(unsigned int *val, int memmodel)
+{
+ __atomic_sub_fetch(val, 1, memmodel);
+}
+
+static inline bool compare_and_swap(unsigned int *ptr,
+ unsigned int old, unsigned int nval, int memmodel)
+{
+ return __atomic_compare_exchange_n(ptr, &old, nval, false,
+ memmodel, memmodel);
+}
+
+#else /* Legacy __sync interface */
+
+#if defined(__i386__) || defined(__i686__) || defined(__amd64__)
+static inline void mb(void) /* mfence compatible */
+{
+ asm volatile ("mfence" : : : "memory");
+}
+#else /* last resort for other architectures */
+static inline void mb(void)
+{
+ __sync_synchronize();
+}
+#endif
+
+/* Define as full barrier. */
+#undef __ATOMIC_SEQ_CST
+#undef __ATOMIC_RELAXED
+#undef __ATOMIC_ACQUIRE
+#undef __ATOMIC_RELEASE
+#define __ATOMIC_SEQ_CST 1
+#define __ATOMIC_RELAXED 1
+#define __ATOMIC_ACQUIRE 1
+#define __ATOMIC_RELEASE 0
+
+static inline unsigned int read_once(unsigned int *ptr, int memmodel)
+{
+ return __sync_fetch_and_add(ptr, 0);
+}
+
+static inline void *read_ptr(void **ptr, int memmodel)
+{
+ return __sync_fetch_and_add(ptr, 0);
+}
+
+static inline void store_once(unsigned int *ptr, unsigned int val, int memmodel)
+{
+ *(volatile unsigned int *)ptr = val;
+ if (memmodel)
+ mb();
+}
+
+static inline void store_ptr(void **ptr, void *val, int memmodel)
+{
+ *(void * volatile *)ptr = val;
+ if (memmodel)
+ mb();
+}
+
+static inline void atomic_inc(unsigned int *val, int memmodel)
+{
+ __sync_fetch_and_add(val, 1);
+}
+
+static inline void atomic_dec(unsigned int *val, int memmodel)
+{
+ __sync_fetch_and_sub(val, 1);
+}
+
+static inline bool compare_and_swap(unsigned int *ptr,
+ unsigned int old, unsigned int nval, int memmodel)
+{
+ return __sync_bool_compare_and_swap(ptr, old, nval);
+}
+
+#endif
+
+#endif /* _KNOTD_ATOMIC_H_ */
+
+/*! @} */
diff --git a/src/common/base32hex.c b/src/common/base32hex.c
index 456d79b..e1af3c7 100644
--- a/src/common/base32hex.c
+++ b/src/common/base32hex.c
@@ -14,7 +14,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "base32hex.h"
+#include "errcode.h"
#include <stdlib.h> // malloc
#include <stdint.h> // uint8_t
@@ -80,9 +82,9 @@ const uint8_t base32hex_dec[256] = {
};
int32_t base32hex_encode(const uint8_t *in,
- const uint32_t in_len,
- uint8_t *out,
- const uint32_t out_len)
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
{
uint8_t rest_len = in_len % 5;
const uint8_t *data = in;
@@ -91,9 +93,11 @@ int32_t base32hex_encode(const uint8_t *in,
uint8_t num;
// Checking inputs.
- if (in == NULL || out == NULL || in_len > MAX_BIN_DATA_LEN ||
- out_len < ((in_len + 4) / 5) * 8) {
- return -1;
+ if (in == NULL || out == NULL) {
+ return KNOT_EINVAL;
+ }
+ if (in_len > MAX_BIN_DATA_LEN || out_len < ((in_len + 4) / 5) * 8) {
+ return KNOT_ERANGE;
}
// Encoding loop takes 5 bytes and creates 8 characters.
@@ -138,7 +142,7 @@ int32_t base32hex_encode(const uint8_t *in,
// Processing of padding, if any.
switch (rest_len) {
// Input data has 4-byte last block => 1-char padding.
- case 4:
+ case 4:
// Computing 1. Base32hex character.
num = *data >> 3;
*text++ = base32hex_enc[num];
@@ -175,7 +179,7 @@ int32_t base32hex_encode(const uint8_t *in,
break;
// Input data has 3-byte last block => 3-char padding.
- case 3:
+ case 3:
// Computing 1. Base32hex character.
num = *data >> 3;
*text++ = base32hex_enc[num];
@@ -205,7 +209,7 @@ int32_t base32hex_encode(const uint8_t *in,
break;
// Input data has 2-byte last block => 4-char padding.
- case 2:
+ case 2:
// Computing 1. Base32hex character.
num = *data >> 3;
*text++ = base32hex_enc[num];
@@ -231,7 +235,7 @@ int32_t base32hex_encode(const uint8_t *in,
break;
// Input data has 1-byte last block => 6-char padding.
- case 1:
+ case 1:
// Computing 1. Base32hex character.
num = *data >> 3;
*text++ = base32hex_enc[num];
@@ -255,31 +259,36 @@ int32_t base32hex_encode(const uint8_t *in,
}
int32_t base32hex_encode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out)
+ const uint32_t in_len,
+ uint8_t **out)
{
- uint32_t out_len = ((in_len + 4) / 5) * 8;
-
- // Checking inputs.
+ // Check input (output is longer).
if (in_len > MAX_BIN_DATA_LEN) {
- return -1;
+ return KNOT_ERANGE;
}
- // Allocating output buffer.
- *out = malloc(out_len);
+ // Compute output buffer length.
+ uint32_t out_len = ((in_len + 4) / 5) * 8;
+ // Allocate output buffer.
+ *out = malloc(out_len);
if (*out == NULL) {
- return -1;
+ return KNOT_ENOMEM;
}
- // Encoding data.
- return base32hex_encode(in, in_len, *out, out_len);
+ // Encode data.
+ int32_t ret = base32hex_encode(in, in_len, *out, out_len);
+ if (ret < 0) {
+ free(*out);
+ }
+
+ return ret;
}
int32_t base32hex_decode(const uint8_t *in,
- const uint32_t in_len,
- uint8_t *out,
- const uint32_t out_len)
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
{
const uint8_t *data = in;
const uint8_t *stop = in + in_len;
@@ -288,9 +297,14 @@ int32_t base32hex_decode(const uint8_t *in,
uint8_t c1, c2, c3, c4, c5, c6, c7, c8;
// Checking inputs.
- if (in == NULL || out == NULL || (in_len % 8) != 0 ||
- in_len > INT32_MAX || out_len < ((in_len + 7) / 8) * 5) {
- return -1;
+ if (in == NULL || out == NULL) {
+ return KNOT_EINVAL;
+ }
+ if (in_len > INT32_MAX || out_len < ((in_len + 7) / 8) * 5) {
+ return KNOT_ERANGE;
+ }
+ if ((in_len % 8) != 0) {
+ return KNOT_BASE32HEX_ESIZE;
}
// Decoding loop takes 8 characters and creates 5 bytes.
@@ -310,7 +324,7 @@ int32_t base32hex_decode(const uint8_t *in,
if (c8 == PD) {
pad_len = 1;
} else {
- return -2;
+ return KNOT_BASE32HEX_ECHAR;
}
}
@@ -319,7 +333,7 @@ int32_t base32hex_decode(const uint8_t *in,
if (c7 == PD && c6 == PD) {
pad_len = 3;
} else {
- return -2;
+ return KNOT_BASE32HEX_ECHAR;
}
}
@@ -328,7 +342,7 @@ int32_t base32hex_decode(const uint8_t *in,
if (c6 == PD) {
pad_len = 3;
} else {
- return -2;
+ return KNOT_BASE32HEX_ECHAR;
}
}
@@ -337,7 +351,7 @@ int32_t base32hex_decode(const uint8_t *in,
if (c5 == PD) {
pad_len = 4;
} else {
- return -2;
+ return KNOT_BASE32HEX_ECHAR;
}
}
@@ -346,7 +360,7 @@ int32_t base32hex_decode(const uint8_t *in,
if (c4 == PD && c3 == PD) {
pad_len = 6;
} else {
- return -2;
+ return KNOT_BASE32HEX_ECHAR;
}
}
@@ -355,13 +369,13 @@ int32_t base32hex_decode(const uint8_t *in,
if (c3 == PD) {
pad_len = 6;
} else {
- return -2;
+ return KNOT_BASE32HEX_ECHAR;
}
}
// 1. and 2. chars must not be padding.
if (c2 >= PD || c1 >= PD) {
- return -2;
+ return KNOT_BASE32HEX_ECHAR;
}
// Computing of output data based on padding length.
@@ -403,19 +417,23 @@ int32_t base32hex_decode(const uint8_t *in,
}
int32_t base32hex_decode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out)
+ const uint32_t in_len,
+ uint8_t **out)
{
+ // Compute output buffer length.
uint32_t out_len = ((in_len + 7) / 8) * 5;
- // Allocating output buffer.
+ // Allocate output buffer.
*out = malloc(out_len);
-
if (*out == NULL) {
- return -1;
+ return KNOT_ENOMEM;
}
- // Decoding data.
- return base32hex_decode(in, in_len, *out, out_len);
-}
+ // Decode data.
+ int32_t ret = base32hex_decode(in, in_len, *out, out_len);
+ if (ret < 0) {
+ free(*out);
+ }
+ return ret;
+}
diff --git a/src/common/base32hex.h b/src/common/base32hex.h
index c7f3f12..75fc5af 100644
--- a/src/common/base32hex.h
+++ b/src/common/base32hex.h
@@ -44,12 +44,12 @@
* \param out_len Size of output buffer.
*
* \retval >=0 length of output string.
- * \retval -1 if error.
+ * \retval errcode if error.
*/
int32_t base32hex_encode(const uint8_t *in,
- const uint32_t in_len,
- uint8_t *out,
- const uint32_t out_len);
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len);
/*!
* \brief Encodes binary data using Base32hex and output stores to own buffer.
@@ -64,11 +64,11 @@ int32_t base32hex_encode(const uint8_t *in,
* \param out Output data buffer.
*
* \retval >=0 length of output string.
- * \retval -1 if error.
+ * \retval errcode if error.
*/
int32_t base32hex_encode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out);
+ const uint32_t in_len,
+ uint8_t **out);
/*!
* \brief Decodes text data using Base32hex.
@@ -83,13 +83,12 @@ int32_t base32hex_encode_alloc(const uint8_t *in,
* \param out_len Size of output buffer.
*
* \retval >=0 length of output data.
- * \retval -1 if error.
- * \retval -2 if bad input data.
+ * \retval errcode if error.
*/
int32_t base32hex_decode(const uint8_t *in,
- const uint32_t in_len,
- uint8_t *out,
- const uint32_t out_len);
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len);
/*!
* \brief Decodes text data using Base32hex and output stores to own buffer.
@@ -105,12 +104,11 @@ int32_t base32hex_decode(const uint8_t *in,
* \param out Output data buffer.
*
* \retval >=0 length of output data.
- * \retval -1 if error.
- * \retval -2 if bad input data.
+ * \retval errcode if error.
*/
int32_t base32hex_decode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out);
+ const uint32_t in_len,
+ uint8_t **out);
#endif // _KNOTD_COMMON__BASE32HEX_H_
diff --git a/src/common/base64.c b/src/common/base64.c
index a153a70..3deee97 100644
--- a/src/common/base64.c
+++ b/src/common/base64.c
@@ -14,7 +14,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "base64.h"
+#include "errcode.h"
#include <stdlib.h> // malloc
#include <stdint.h> // uint8_t
@@ -81,9 +83,9 @@ const uint8_t base64_dec[256] = {
};
int32_t base64_encode(const uint8_t *in,
- const uint32_t in_len,
- uint8_t *out,
- const uint32_t out_len)
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
{
uint8_t rest_len = in_len % 3;
const uint8_t *data = in;
@@ -92,9 +94,11 @@ int32_t base64_encode(const uint8_t *in,
uint8_t num;
// Checking inputs.
- if (in == NULL || out == NULL || in_len > MAX_BIN_DATA_LEN ||
- out_len < ((in_len + 2) / 3) * 4) {
- return -1;
+ 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;
}
// Encoding loop takes 3 bytes and creates 4 characters.
@@ -121,7 +125,7 @@ int32_t base64_encode(const uint8_t *in,
// Processing of padding, if any.
switch (rest_len) {
// Input data has 2-byte last block => 1-char padding.
- case 2:
+ case 2:
// Computing 1. Base64 character.
num = *data >> 2;
*text++ = base64_enc[num];
@@ -138,9 +142,9 @@ int32_t base64_encode(const uint8_t *in,
// 1 padding character.
*text++ = base64_pad;
- break;
+ break;
// Input data has 1-byte last block => 2-char padding.
- case 1:
+ case 1:
// Computing 1. Base64 character.
num = *data >> 2;
*text++ = base64_enc[num];
@@ -153,38 +157,43 @@ int32_t base64_encode(const uint8_t *in,
*text++ = base64_pad;
*text++ = base64_pad;
- break;
+ break;
}
return (text - out);
}
int32_t base64_encode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out)
+ const uint32_t in_len,
+ uint8_t **out)
{
- uint32_t out_len = ((in_len + 2) / 3) * 4;
-
- // Checking inputs.
+ // Check input (output is longer).
if (in_len > MAX_BIN_DATA_LEN) {
- return -1;
+ return KNOT_ERANGE;
}
- // Allocating output buffer.
- *out = malloc(out_len);
+ // Compute output buffer length.
+ uint32_t out_len = ((in_len + 2) / 3) * 4;
+ // Allocate output buffer.
+ *out = malloc(out_len);
if (*out == NULL) {
- return -1;
+ return KNOT_ENOMEM;
}
- // Encoding data.
- return base64_encode(in, in_len, *out, out_len);
+ // 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)
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
{
const uint8_t *data = in;
const uint8_t *stop = in + in_len;
@@ -193,9 +202,14 @@ int32_t base64_decode(const uint8_t *in,
uint8_t c1, c2, c3, c4;
// Checking inputs.
- if (in == NULL || out == NULL || (in_len % 4) != 0 ||
- in_len > INT32_MAX || out_len < ((in_len + 3) / 4) * 3) {
- return -1;
+ 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;
}
// Decoding loop takes 4 characters and creates 3 bytes.
@@ -211,7 +225,7 @@ int32_t base64_decode(const uint8_t *in,
if (c4 == PD) {
pad_len = 1;
} else {
- return -2;
+ return KNOT_BASE64_ECHAR;
}
}
@@ -220,13 +234,13 @@ int32_t base64_decode(const uint8_t *in,
if (c3 == PD) {
pad_len = 2;
} else {
- return -2;
+ return KNOT_BASE64_ECHAR;
}
}
// 1. and 2. chars must not be padding.
if (c2 >= PD || c1 >= PD) {
- return -2;
+ return KNOT_BASE64_ECHAR;
}
// Computing of output data based on padding length.
@@ -253,19 +267,23 @@ int32_t base64_decode(const uint8_t *in,
}
int32_t base64_decode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out)
+ const uint32_t in_len,
+ uint8_t **out)
{
+ // Compute output buffer length.
uint32_t out_len = ((in_len + 3) / 4) * 3;
+ // Allocate output buffer.
*out = malloc(out_len);
-
- // Allocating output buffer.
if (*out == NULL) {
- return -1;
+ return KNOT_ENOMEM;
}
- // Decoding data.
- return base64_decode(in, in_len, *out, out_len);
-}
+ // Decode data.
+ int32_t ret = base64_decode(in, in_len, *out, out_len);
+ if (ret < 0) {
+ free(*out);
+ }
+ return ret;
+}
diff --git a/src/common/base64.h b/src/common/base64.h
index 8f99891..258c2dc 100644
--- a/src/common/base64.h
+++ b/src/common/base64.h
@@ -41,12 +41,12 @@
* \param out_len Size of output buffer.
*
* \retval >=0 length of output string.
- * \retval -1 if error.
+ * \retval errcode if error.
*/
int32_t base64_encode(const uint8_t *in,
- const uint32_t in_len,
- uint8_t *out,
- const uint32_t out_len);
+ 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.
@@ -61,11 +61,11 @@ int32_t base64_encode(const uint8_t *in,
* \param out Output data buffer.
*
* \retval >=0 length of output string.
- * \retval -1 if error.
+ * \retval errcode if error.
*/
int32_t base64_encode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out);
+ const uint32_t in_len,
+ uint8_t **out);
/*!
* \brief Decodes text data using Base64.
@@ -80,13 +80,12 @@ int32_t base64_encode_alloc(const uint8_t *in,
* \param out_len Size of output buffer.
*
* \retval >=0 length of output data.
- * \retval -1 if error.
- * \retval -2 if bad input data.
+ * \retval errcode if error.
*/
int32_t base64_decode(const uint8_t *in,
- const uint32_t in_len,
- uint8_t *out,
- const uint32_t out_len);
+ 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.
@@ -102,12 +101,11 @@ int32_t base64_decode(const uint8_t *in,
* \param out Output data buffer.
*
* \retval >=0 length of output data.
- * \retval -1 if error.
- * \retval -2 if bad input data.
+ * \retval errcode if error.
*/
int32_t base64_decode_alloc(const uint8_t *in,
- const uint32_t in_len,
- uint8_t **out);
+ const uint32_t in_len,
+ uint8_t **out);
#endif // _KNOTD_COMMON__BASE64_H_
diff --git a/src/common/dSFMT-params.h b/src/common/dSFMT-params.h
index c779d8a..3a4a868 100644
--- a/src/common/dSFMT-params.h
+++ b/src/common/dSFMT-params.h
@@ -1,5 +1,3 @@
-#include <config.h>
-
#ifndef DSFMT_PARAMS_H
#define DSFMT_PARAMS_H
@@ -10,7 +8,7 @@
following definitions are in dSFMT-paramsXXXX.h file.
----------------------*/
/** the pick up position of the array.
-#define DSFMT_POS1 122
+#define DSFMT_POS1 122
*/
/** the parameter of shift left as four 32-bit registers.
diff --git a/src/common/dSFMT.c b/src/common/dSFMT.c
index 090bb80..4b238b5 100644
--- a/src/common/dSFMT.c
+++ b/src/common/dSFMT.c
@@ -1,5 +1,5 @@
-/**
- * @file dSFMT.c
+/**
+ * @file dSFMT.c
* @brief double precision SIMD-oriented Fast Mersenne Twister (dSFMT)
* based on IEEE 754 format.
*
@@ -11,6 +11,8 @@
*
* The new BSD License is applied to this software, see LICENSE.txt
*/
+
+#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -128,7 +130,7 @@ static void setup_const(void) {
*/
inline static void do_recursion(w128_t *r, w128_t *a, w128_t *b, w128_t *u) {
__m128i v, w, x, y, z;
-
+
x = a->si;
z = _mm_slli_epi64(x, DSFMT_SL1);
y = _mm_shuffle_epi32(u->si, SSE2_SHUFF);
@@ -237,7 +239,7 @@ inline static void convert_o0o1(w128_t *w) {
* This function fills the user-specified array with double precision
* floating point pseudorandom numbers of the IEEE 754 format.
* @param dsfmt dsfmt state vector.
- * @param array an 128-bit array to be filled by pseudorandom numbers.
+ * @param array an 128-bit array to be filled by pseudorandom numbers.
* @param size number of 128-bit pseudorandom numbers to be generated.
*/
inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array,
@@ -275,7 +277,7 @@ inline static void gen_rand_array_c1o2(dsfmt_t *dsfmt, w128_t *array,
* This function fills the user-specified array with double precision
* floating point pseudorandom numbers of the IEEE 754 format.
* @param dsfmt dsfmt state vector.
- * @param array an 128-bit array to be filled by pseudorandom numbers.
+ * @param array an 128-bit array to be filled by pseudorandom numbers.
* @param size number of 128-bit pseudorandom numbers to be generated.
*/
inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array,
@@ -318,7 +320,7 @@ inline static void gen_rand_array_c0o1(dsfmt_t *dsfmt, w128_t *array,
* This function fills the user-specified array with double precision
* floating point pseudorandom numbers of the IEEE 754 format.
* @param dsfmt dsfmt state vector.
- * @param array an 128-bit array to be filled by pseudorandom numbers.
+ * @param array an 128-bit array to be filled by pseudorandom numbers.
* @param size number of 128-bit pseudorandom numbers to be generated.
*/
inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array,
@@ -361,7 +363,7 @@ inline static void gen_rand_array_o0o1(dsfmt_t *dsfmt, w128_t *array,
* This function fills the user-specified array with double precision
* floating point pseudorandom numbers of the IEEE 754 format.
* @param dsfmt dsfmt state vector.
- * @param array an 128-bit array to be filled by pseudorandom numbers.
+ * @param array an 128-bit array to be filled by pseudorandom numbers.
* @param size number of 128-bit pseudorandom numbers to be generated.
*/
inline static void gen_rand_array_o0c1(dsfmt_t *dsfmt, w128_t *array,
@@ -634,7 +636,7 @@ void dsfmt_chk_init_gen_rand(dsfmt_t *dsfmt, uint32_t seed, int mexp) {
psfmt = &dsfmt->status[0].u32[0];
psfmt[idxof(0)] = seed;
for (i = 1; i < (DSFMT_N + 1) * 4; i++) {
- psfmt[idxof(i)] = 1812433253UL
+ psfmt[idxof(i)] = 1812433253UL
* (psfmt[idxof(i - 1)] ^ (psfmt[idxof(i - 1)] >> 30)) + i;
}
initial_mask(dsfmt);
@@ -685,7 +687,7 @@ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[],
} else {
count = size;
}
- r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)]
+ r = ini_func1(psfmt32[idxof(0)] ^ psfmt32[idxof(mid % size)]
^ psfmt32[idxof((size - 1) % size)]);
psfmt32[idxof(mid % size)] += r;
r += key_length;
@@ -693,8 +695,8 @@ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[],
psfmt32[idxof(0)] = r;
count--;
for (i = 1, j = 0; (j < count) && (j < key_length); j++) {
- r = ini_func1(psfmt32[idxof(i)]
- ^ psfmt32[idxof((i + mid) % size)]
+ r = ini_func1(psfmt32[idxof(i)]
+ ^ psfmt32[idxof((i + mid) % size)]
^ psfmt32[idxof((i + size - 1) % size)]);
psfmt32[idxof((i + mid) % size)] += r;
r += init_key[j] + i;
@@ -703,8 +705,8 @@ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[],
i = (i + 1) % size;
}
for (; j < count; j++) {
- r = ini_func1(psfmt32[idxof(i)]
- ^ psfmt32[idxof((i + mid) % size)]
+ r = ini_func1(psfmt32[idxof(i)]
+ ^ psfmt32[idxof((i + mid) % size)]
^ psfmt32[idxof((i + size - 1) % size)]);
psfmt32[idxof((i + mid) % size)] += r;
r += i;
@@ -713,8 +715,8 @@ void dsfmt_chk_init_by_array(dsfmt_t *dsfmt, uint32_t init_key[],
i = (i + 1) % size;
}
for (j = 0; j < size; j++) {
- r = ini_func2(psfmt32[idxof(i)]
- + psfmt32[idxof((i + mid) % size)]
+ r = ini_func2(psfmt32[idxof(i)]
+ + psfmt32[idxof((i + mid) % size)]
+ psfmt32[idxof((i + size - 1) % size)]);
psfmt32[idxof((i + mid) % size)] ^= r;
r -= i;
diff --git a/src/common/dSFMT.h b/src/common/dSFMT.h
index f1aa9bd..aaad333 100644
--- a/src/common/dSFMT.h
+++ b/src/common/dSFMT.h
@@ -1,5 +1,5 @@
-/**
- * @file dSFMT.h
+/**
+ * @file dSFMT.h
*
* @brief double precision SIMD oriented Fast Mersenne Twister(dSFMT)
* pseudorandom number generator based on IEEE 754 format.
@@ -18,7 +18,7 @@
* and you have to define PRIu64 and PRIx64 in this file as follows:
* @verbatim
typedef unsigned int uint32_t
- typedef unsigned long long uint64_t
+ typedef unsigned long long uint64_t
#define PRIu64 "llu"
#define PRIx64 "llx"
@endverbatim
@@ -28,8 +28,6 @@
* unsigned int and 64-bit unsigned int in hexadecimal format.
*/
-#include <config.h>
-
#ifndef DSFMT_H
#define DSFMT_H
@@ -45,7 +43,7 @@
/*-----------------
BASIC DEFINITIONS
-----------------*/
-/* Mersenne Exponent. The period of the sequence
+/* Mersenne Exponent. The period of the sequence
* is a multiple of 2^DSFMT_MEXP-1.
* #define DSFMT_MEXP 19937 */
/** DSFMT generator has an internal state array of 128-bit integers,
@@ -119,7 +117,7 @@ typedef unsigned __int64 uint64_t;
#endif
#ifndef UINT64_C
-# define UINT64_C(v) (v ## ULL)
+# define UINT64_C(v) (v ## ULL)
#endif
/*------------------------------------------
@@ -313,7 +311,7 @@ inline static double dsfmt_gv_genrand_close_open(void) {
* This function generates and returns double precision pseudorandom
* number which distributes uniformly in the range (0, 1].
* dsfmt_init_gen_rand() or dsfmt_init_by_array() must be called
- * before this function.
+ * before this function.
* @param dsfmt dsfmt internal state date
* @return double precision floating point pseudorandom number
*/
diff --git a/src/common/descriptor.c b/src/common/descriptor.c
new file mode 100644
index 0000000..233a995
--- /dev/null
+++ b/src/common/descriptor.c
@@ -0,0 +1,291 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "common/descriptor.h"
+#include "libknot/util/utils.h" // knot_lookup_table_t
+
+#include <stdio.h> // snprintf
+#include <stdlib.h> // strtoul
+
+/*!
+ * \brief The last RR type number in the descriptors table.
+ */
+const int KNOT_RRTYPE_LAST = KNOT_RRTYPE_ANY;
+
+/*!
+ * \brief Table with DNS classes.
+ */
+static knot_lookup_table_t dns_classes[] = {
+ { KNOT_CLASS_IN, "IN" },
+ { KNOT_CLASS_CH, "CH" },
+ { KNOT_CLASS_NONE, "NONE" },
+ { KNOT_CLASS_ANY, "ANY" },
+ { 0, NULL }
+};
+
+/*!
+ * \brief RR type descriptors.
+ */
+static const rdata_descriptor_t rdata_descriptors[] = {
+ [0] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, NULL },
+ [KNOT_RRTYPE_A] = { { 4, KNOT_RDATA_WF_END }, "A" },
+ [KNOT_RRTYPE_NS] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "NS" },
+ [KNOT_RRTYPE_CNAME] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "CNAME" },
+ [KNOT_RRTYPE_SOA] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_COMPRESSED_DNAME,
+ 20, KNOT_RDATA_WF_END }, "SOA" },
+ [KNOT_RRTYPE_PTR] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "PTR" },
+ [KNOT_RRTYPE_HINFO] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "HINFO" },
+ [KNOT_RRTYPE_MINFO] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "MINFO" },
+ [KNOT_RRTYPE_MX] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "MX" },
+ [KNOT_RRTYPE_TXT] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "TXT" },
+ [KNOT_RRTYPE_RP] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "RP" },
+ [KNOT_RRTYPE_AFSDB] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "AFSDB" },
+ [KNOT_RRTYPE_RT] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "RT" },
+ [KNOT_RRTYPE_SIG] = { { 18, KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "SIG" },
+ [KNOT_RRTYPE_KEY] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "KEY" },
+ [KNOT_RRTYPE_AAAA] = { { 16, KNOT_RDATA_WF_END }, "AAAA" },
+ [KNOT_RRTYPE_LOC] = { { 16, KNOT_RDATA_WF_END }, "LOC" },
+ [KNOT_RRTYPE_SRV] = { { 6, KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "SRV" },
+ [KNOT_RRTYPE_NAPTR] = { { KNOT_RDATA_WF_NAPTR_HEADER,
+ KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "NAPTR" },
+ [KNOT_RRTYPE_KX] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "KX" },
+ [KNOT_RRTYPE_CERT] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "CERT" },
+ [KNOT_RRTYPE_DNAME] = { { KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "DNAME" },
+ [KNOT_RRTYPE_OPT] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "OPT" },
+ [KNOT_RRTYPE_APL] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "APL" },
+ [KNOT_RRTYPE_DS] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "DS" },
+ [KNOT_RRTYPE_SSHFP] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "SSHFP" },
+ [KNOT_RRTYPE_IPSECKEY] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "IPSECKEY" },
+ [KNOT_RRTYPE_RRSIG] = { { 18, KNOT_RDATA_WF_LITERAL_DNAME,
+ KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "RRSIG" },
+ [KNOT_RRTYPE_NSEC] = { { KNOT_RDATA_WF_LITERAL_DNAME,
+ KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "NSEC" },
+ [KNOT_RRTYPE_DNSKEY] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "DNSKEY" },
+ [KNOT_RRTYPE_DHCID] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "DHCID" },
+ [KNOT_RRTYPE_NSEC3] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "NSEC3" },
+ [KNOT_RRTYPE_NSEC3PARAM] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "NSEC3PARAM" },
+ [KNOT_RRTYPE_TLSA] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "TLSA" },
+ [KNOT_RRTYPE_SPF] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "SPF" },
+ [KNOT_RRTYPE_NID] = { { 10 }, "NID" },
+ [KNOT_RRTYPE_L32] = { { 6 }, "L32" },
+ [KNOT_RRTYPE_L64] = { { 10 }, "L64" },
+ [KNOT_RRTYPE_LP] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME },
+ "LP" },
+ [KNOT_RRTYPE_EUI48] = { { 6, KNOT_RDATA_WF_END }, "EUI48" },
+ [KNOT_RRTYPE_EUI64] = { { 8, KNOT_RDATA_WF_END }, "EUI64" },
+ [KNOT_RRTYPE_TKEY] = { { KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "TKEY" },
+ [KNOT_RRTYPE_TSIG] = { { KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "TSIG" },
+ [KNOT_RRTYPE_IXFR] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "IXFR" },
+ [KNOT_RRTYPE_AXFR] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "AXFR" },
+ [KNOT_RRTYPE_ANY] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "ANY" },
+};
+
+const rdata_descriptor_t *get_rdata_descriptor(const uint16_t type)
+{
+ if (type <= KNOT_RRTYPE_ANY && rdata_descriptors[type].type_name != 0) {
+ return &rdata_descriptors[type];
+ } else {
+ return &rdata_descriptors[0];
+ }
+}
+
+int knot_rrtype_to_string(const uint16_t rrtype,
+ char *out,
+ const size_t out_len)
+{
+ int ret;
+
+ const rdata_descriptor_t *descr = get_rdata_descriptor(rrtype);
+
+ if (descr->type_name != 0) {
+ ret = snprintf(out, out_len, "%s", descr->type_name);
+ } else {
+ ret = snprintf(out, out_len, "TYPE%u", rrtype);
+ }
+
+ if (ret <= 0 || (size_t)ret >= out_len) {
+ return -1;
+ } else {
+ return ret;
+ }
+}
+
+int knot_rrtype_from_string(const char *name, uint16_t *num)
+{
+ int i;
+ char *end;
+ unsigned long n;
+
+ // Try to find name in descriptors table.
+ for (i = 0; i <= KNOT_RRTYPE_LAST; i++) {
+ if (rdata_descriptors[i].type_name != 0 &&
+ strcasecmp(rdata_descriptors[i].type_name, name) == 0) {
+ *num = i;
+ return 0;
+ }
+ }
+
+ // Type name must begin with TYPE.
+ if (strncasecmp(name, "TYPE", 4) != 0) {
+ return -1;
+ } else {
+ name += 4;
+ }
+
+ // The rest must be a number.
+ n = strtoul(name, &end, 10);
+ if (end == name || *end != '\0' || n > UINT16_MAX) {
+ return -1;
+ }
+
+ *num = n;
+ return 0;
+}
+
+int knot_rrclass_to_string(const uint16_t rrclass,
+ char *out,
+ const size_t out_len)
+{
+ int ret;
+
+ knot_lookup_table_t *entry = knot_lookup_by_id(dns_classes, rrclass);
+
+ if (entry != NULL) {
+ ret = snprintf(out, out_len, "%s", entry->name);
+ } else {
+ ret = snprintf(out, out_len, "CLASS%u", rrclass);
+ }
+
+ if (ret <= 0 || (size_t)ret >= out_len) {
+ return -1;
+ } else {
+ return ret;
+ }
+}
+
+int knot_rrclass_from_string(const char *name, uint16_t *num)
+{
+ char *end;
+ unsigned long n;
+
+ // Try to find name in lookup table.
+ knot_lookup_table_t *entry = knot_lookup_by_name(dns_classes, name);
+
+ if (entry != NULL) {
+ *num = entry->id;
+ return 0;
+ }
+
+ // Class name must begin with CLASS.
+ if (strncasecmp(name, "CLASS", 5) != 0) {
+ return -1;
+ } else {
+ name += 5;
+ }
+
+ // The rest must be a number.
+ n = strtoul(name, &end, 10);
+ if (end == name || *end != '\0' || n > UINT16_MAX) {
+ return -1;
+ }
+
+ *num = n;
+ return 0;
+}
+
+int descriptor_item_is_dname(const int item)
+{
+ return item == KNOT_RDATA_WF_LITERAL_DNAME ||
+ item == KNOT_RDATA_WF_COMPRESSED_DNAME ||
+ item == KNOT_RDATA_WF_UNCOMPRESSED_DNAME;
+}
+
+int descriptor_item_is_compr_dname(const int item)
+{
+ return item == KNOT_RDATA_WF_COMPRESSED_DNAME;
+}
+
+int descriptor_item_is_fixed(const int item)
+{
+ if (item > 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int descriptor_item_is_remainder(const int item)
+{
+ if (item == KNOT_RDATA_WF_REMAINDER) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int knot_rrtype_is_metatype(const uint16_t type)
+{
+ return type == KNOT_RRTYPE_SIG ||
+ type == KNOT_RRTYPE_OPT ||
+ type == KNOT_RRTYPE_TKEY ||
+ type == KNOT_RRTYPE_TSIG ||
+ type == KNOT_RRTYPE_IXFR ||
+ type == KNOT_RRTYPE_AXFR ||
+ type == KNOT_RRTYPE_ANY;
+}
diff --git a/src/common/descriptor.h b/src/common/descriptor.h
new file mode 100644
index 0000000..d7938cb
--- /dev/null
+++ b/src/common/descriptor.h
@@ -0,0 +1,252 @@
+/* Copyright (C) 2011 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 descriptor.h
+ *
+ * \author Jan Kadlec <jan.kadlec@nic.cz>
+ *
+ * \addtogroup common_lib
+ * @{
+ */
+
+#ifndef _KNOT_DESCRIPTOR_H_
+#define _KNOT_DESCRIPTOR_H_
+
+#include <stdint.h> // uint16_t
+#include <stdio.h> // size_t
+
+#define KNOT_MAX_RDATA_BLOCKS 8
+
+/*!
+ * \brief Resource record class codes.
+ */
+enum knot_rr_class {
+ KNOT_CLASS_IN = 1,
+ KNOT_CLASS_CH = 3,
+ KNOT_CLASS_NONE = 254,
+ KNOT_CLASS_ANY = 255
+};
+
+/*!
+ * \brief Resource record type constants.
+ *
+ * http://www.iana.org/assignments/dns-parameters/dns-parameters.xml
+ *
+ * METATYPE: Contains DNS data that can't be in a zone file.
+ * QTYPE: Specifies DNS query type; can't be in a zone file.
+ */
+enum knot_rr_type {
+ KNOT_RRTYPE_A = 1, /*!< An IPv4 host address. */
+ KNOT_RRTYPE_NS = 2, /*!< An authoritative name server. */
+
+ KNOT_RRTYPE_CNAME = 5, /*!< The canonical name for an alias. */
+ KNOT_RRTYPE_SOA = 6, /*!< The start of a zone of authority. */
+
+ KNOT_RRTYPE_PTR = 12, /*!< A domain name pointer. */
+ KNOT_RRTYPE_HINFO = 13, /*!< A host information. */
+ KNOT_RRTYPE_MINFO = 14, /*!< A mailbox information. */
+ KNOT_RRTYPE_MX = 15, /*!< Mail exchange. */
+ KNOT_RRTYPE_TXT = 16, /*!< Text strings. */
+ KNOT_RRTYPE_RP = 17, /*!< For responsible person. */
+ KNOT_RRTYPE_AFSDB = 18, /*!< For AFS Data Base location. */
+
+ KNOT_RRTYPE_RT = 21, /*!< For route through. */
+
+ KNOT_RRTYPE_SIG = 24, /*!< METATYPE. Transaction signature. */
+ KNOT_RRTYPE_KEY = 25, /*!< For security key. */
+
+ KNOT_RRTYPE_AAAA = 28, /*!< IPv6 address. */
+ KNOT_RRTYPE_LOC = 29, /*!< Location information. */
+
+ KNOT_RRTYPE_SRV = 33, /*!< Server selection. */
+
+ KNOT_RRTYPE_NAPTR = 35, /*!< Naming authority pointer . */
+ KNOT_RRTYPE_KX = 36, /*!< Key exchanger. */
+ KNOT_RRTYPE_CERT = 37, /*!< Certificate record. */
+
+ KNOT_RRTYPE_DNAME = 39, /*!< Delegation name. */
+
+ KNOT_RRTYPE_OPT = 41, /*!< METATYPE. Option for EDNS. */
+ KNOT_RRTYPE_APL = 42, /*!< Address prefix list. */
+ KNOT_RRTYPE_DS = 43, /*!< Delegation signer. */
+ KNOT_RRTYPE_SSHFP = 44, /*!< SSH public key fingerprint. */
+ KNOT_RRTYPE_IPSECKEY = 45, /*!< IPSEC key. */
+ KNOT_RRTYPE_RRSIG = 46, /*!< DNSSEC signature. */
+ KNOT_RRTYPE_NSEC = 47, /*!< Next-secure record. */
+ KNOT_RRTYPE_DNSKEY = 48, /*!< DNS key. */
+ KNOT_RRTYPE_DHCID = 49, /*!< DHCP identifier. */
+ KNOT_RRTYPE_NSEC3 = 50, /*!< NSEC version 3. */
+ KNOT_RRTYPE_NSEC3PARAM = 51, /*!< NSEC3 parameters. */
+ KNOT_RRTYPE_TLSA = 52, /*!< DANE record. */
+
+ KNOT_RRTYPE_SPF = 99, /*!< Sender policy framework. */
+
+ KNOT_RRTYPE_NID = 104, /*!< Node identifier. */
+ KNOT_RRTYPE_L32 = 105, /*!< 32-bit network locator. */
+ KNOT_RRTYPE_L64 = 106, /*!< 64-bit network locator. */
+ KNOT_RRTYPE_LP = 107, /*!< Subnetwork name. */
+ KNOT_RRTYPE_EUI48 = 108, /*!< 48-bit extended unique identifier. */
+ KNOT_RRTYPE_EUI64 = 109, /*!< 64-bit extended unique identifier. */
+
+ KNOT_RRTYPE_TKEY = 249, /*!< METATYPE. Transaction key. */
+ KNOT_RRTYPE_TSIG = 250, /*!< METATYPE. Transaction signature. */
+ KNOT_RRTYPE_IXFR = 251, /*!< QTYPE. Incremental zone transfer. */
+ KNOT_RRTYPE_AXFR = 252, /*!< QTYPE. Authoritative zone transfer. */
+
+ KNOT_RRTYPE_ANY = 255 /*!< QTYPE. Any record. */
+};
+
+/*!
+ * \brief Constants characterising the wire format of RDATA items.
+ */
+enum knot_rdata_wireformat {
+ /*!< Possibly compressed dname. */
+ KNOT_RDATA_WF_COMPRESSED_DNAME = -10,
+ /*!< Uncompressed dname. */
+ KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ /*!< Dname with preserved letter cases. */
+ KNOT_RDATA_WF_LITERAL_DNAME,
+ /*!< Initial part of NAPTR record before dname. */
+ KNOT_RDATA_WF_NAPTR_HEADER,
+ /*!< Uninteresting final part of a record. */
+ KNOT_RDATA_WF_REMAINDER,
+ /*!< The last descriptor in array. */
+ KNOT_RDATA_WF_END = 0
+};
+
+/*!
+ * \brief Structure describing rdata.
+ */
+typedef struct {
+ /*!< Item types describing rdata. */
+ const int block_types[KNOT_MAX_RDATA_BLOCKS];
+ /*!< RR type name. */
+ const char *type_name;
+} rdata_descriptor_t;
+
+/*!
+ * \brief Gets rdata descriptor for given RR name.
+ *
+ * \param name Mnemonic of RR type whose descriptor should be retvaled.
+ *
+ * \retval RR descriptor for given name, NULL descriptor if
+ * unknown type.
+ */
+const rdata_descriptor_t *get_rdata_descriptor(const uint16_t type);
+
+/*!
+ * \brief Converts numeric type representation to mnemonic string.
+ *
+ * \param rrtype Type RR type code to be converted.
+ * \param out Output buffer.
+ * \param out_len Length of the output buffer.
+ *
+ * \retval Length of output string.
+ * \retval -1 if error.
+ */
+int knot_rrtype_to_string(const uint16_t rrtype,
+ char *out,
+ const size_t out_len);
+
+/*!
+ * \brief Converts mnemonic string representation of a type to numeric one.
+ *
+ * \param name Mnemonic string to be converted.
+ * \param num Output variable.
+ *
+ * \retval 0 if OK.
+ * \retval -1 if error.
+ */
+int knot_rrtype_from_string(const char *name, uint16_t *num);
+
+/*!
+ * \brief Converts numeric class representation to the string one.
+ *
+ * \param rrclass Class code to be converted.
+ * \param out Output buffer.
+ * \param out_len Length of the output buffer.
+ *
+ * \retval Length of output string.
+ * \retval -1 if error.
+ */
+int knot_rrclass_to_string(const uint16_t rrclass,
+ char *out,
+ const size_t out_len);
+
+/*!
+ * \brief Converts string representation of a class to numeric one.
+ *
+ * \param name Mnemonic string to be converted.
+ * \param num Output variable.
+ *
+ * \retval 0 if OK.
+ * \retval -1 if error.
+ */
+int knot_rrclass_from_string(const char *name, uint16_t *num);
+
+/*!
+ * \brief Checks if given item is one of dname types.
+ *
+ * \param item Item value.
+ *
+ * \retval 1 if YES.
+ * \retval 0 if NO.
+ */
+int descriptor_item_is_dname(const int item);
+
+/*!
+ * \brief Checks if given item is compressible dname.
+ *
+ * \param item Item value.
+ *
+ * \retval 1 if YES.
+ * \retval 0 if NO.
+ */
+int descriptor_item_is_compr_dname(const int item);
+
+/*!
+ * \brief Checks if given item has fixed size.
+ *
+ * \param item Item value.
+ *
+ * \retval 1 if YES.
+ * \retval 0 if NO.
+ */
+int descriptor_item_is_fixed(const int item);
+
+/*!
+ * \brief Checks if given item is remainder.
+ *
+ * \param item Item value.
+ *
+ * \retval 1 if YES.
+ * \retval 0 if NO.
+ */
+int descriptor_item_is_remainder(const int item);
+
+/*!
+ * \brief Checks if given item is one of metatypes or qtypes.
+ *
+ * \param item Item value.
+ *
+ * \retval 1 if YES.
+ * \retval 0 if NO.
+ */
+int knot_rrtype_is_metatype(const uint16_t type);
+
+#endif // _KNOT_DESCRIPTOR_H_
+
+/*! @} */
diff --git a/src/common/errcode.c b/src/common/errcode.c
index 75c4e13..c03b473 100644
--- a/src/common/errcode.c
+++ b/src/common/errcode.c
@@ -14,63 +14,164 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "common/errcode.h"
#include "common/errors.h"
const error_table_t knot_error_msgs[] = {
- {KNOT_EOK, "OK"},
-
+ { KNOT_EOK, "OK" },
+
/* TSIG errors. */
- {KNOT_TSIG_EBADSIG, "Failed to verify TSIG MAC." },
- {KNOT_TSIG_EBADKEY, "TSIG key not recognized or invalid." },
- {KNOT_TSIG_EBADTIME, "TSIG signing time out of range." },
-
+ { KNOT_TSIG_EBADSIG, "Failed to verify TSIG MAC." },
+ { KNOT_TSIG_EBADKEY, "TSIG key not recognized or invalid." },
+ { KNOT_TSIG_EBADTIME, "TSIG signing time out of range." },
+
/* Directly mapped error codes. */
- {KNOT_ENOMEM, "Not enough memory."},
- {KNOT_EINVAL, "Invalid parameter."},
- {KNOT_ENOTSUP, "Operation not supported."},
- {KNOT_EBUSY, "Requested resource is busy."},
- {KNOT_EAGAIN, "OS lacked necessary resources."},
- {KNOT_EACCES, "Operation not permitted."},
- {KNOT_ECONNREFUSED, "Connection refused."},
- {KNOT_EISCONN, "Already connected."},
- {KNOT_EADDRINUSE, "Address already in use."},
- {KNOT_ENOENT, "Resource not found."},
- {KNOT_ERANGE, "Value is out of range."},
-
+ { KNOT_ENOMEM, "Not enough memory." },
+ { KNOT_EINVAL, "Invalid parameter." },
+ { KNOT_ENOTSUP, "Operation not supported." },
+ { KNOT_EBUSY, "Requested resource is busy." },
+ { KNOT_EAGAIN, "OS lacked necessary resources." },
+ { KNOT_EACCES, "Operation not permitted." },
+ { KNOT_ECONNREFUSED, "Connection refused." },
+ { KNOT_EISCONN, "Already connected." },
+ { KNOT_EADDRINUSE, "Address already in use." },
+ { KNOT_ENOENT, "Resource not found." },
+ { KNOT_ERANGE, "Value is out of range." },
+
/* General errors. */
- {KNOT_ERROR, "General error."},
- {KNOT_ENOTRUNNING, "Resource is not running."},
- {KNOT_EPARSEFAIL, "Parser failed."},
- {KNOT_ENOIPV6, "IPv6 support disabled."},
- {KNOT_EEXPIRED, "Resource is expired."},
- {KNOT_EUPTODATE, "Zone is up-to-date."},
- {KNOT_EFEWDATA, "Not enough data to parse."},
- {KNOT_ESPACE, "Not enough space provided."},
- {KNOT_EMALF, "Malformed data."},
- {KNOT_ECRYPTO, "Error in crypto library."},
- {KNOT_ENSEC3PAR, "Missing or wrong NSEC3PARAM record."},
- {KNOT_ENSEC3CHAIN, "Missing or wrong NSEC3 chain in the zone."},
- {KNOT_EBADZONE, "Name does not belong to the zone."},
- {KNOT_EHASH, "Error in hash table."},
- {KNOT_EZONEINVAL, "Invalid zone file."},
- {KNOT_ENOZONE, "No such zone found."},
- {KNOT_ENONODE, "No such node in zone found."},
- {KNOT_ENORRSET, "No such RRSet found."},
- {KNOT_EDNAMEPTR, "Domain name pointer larger than allowed."},
- {KNOT_EPAYLOAD, "Payload in OPT RR larger than max wire size."},
- {KNOT_ECRC, "CRC check failed."},
- {KNOT_EPREREQ, "UPDATE prerequisity not met."},
- {KNOT_ENOXFR, "Transfer was not sent."},
- {KNOT_ENOIXFR, "Transfer is not IXFR (is in AXFR format)."},
- {KNOT_EXFRREFUSED, "Zone transfer refused by the server."},
- {KNOT_EXFRDENIED, "Transfer not allowed."},
- {KNOT_ECONN, "Connection reset."},
- {KNOT_EIXFRSPACE, "IXFR reply did not fit in."},
- {KNOT_ECNAME, "CNAME loop found in zone."},
- {KNOT_ENODIFF, "Cannot create zone diff."},
- {KNOT_EDSDIGESTLEN, "DS digest length does not match digest type." },
- {KNOT_ELIMIT, "Exceeded response rate limit." },
-
- {KNOT_ERROR, 0}
+ { KNOT_ERROR, "General error." },
+ { KNOT_ENOTRUNNING, "Resource is not running." },
+ { KNOT_EPARSEFAIL, "Parser failed." },
+ { KNOT_ENOIPV6, "IPv6 support disabled." },
+ { KNOT_EEXPIRED, "Resource is expired." },
+ { KNOT_EUPTODATE, "Zone is up-to-date." },
+ { KNOT_EFEWDATA, "Not enough data to parse." },
+ { KNOT_ESPACE, "Not enough space provided." },
+ { KNOT_EMALF, "Malformed data." },
+ { KNOT_ECRYPTO, "Error in crypto library." },
+ { KNOT_ENSEC3PAR, "Missing or wrong NSEC3PARAM record." },
+ { KNOT_ENSEC3CHAIN, "Missing or wrong NSEC3 chain in the zone." },
+ { KNOT_EBADZONE, "Name does not belong to the zone." },
+ { KNOT_EHASH, "Error in hash table." },
+ { KNOT_EZONEINVAL, "Invalid zone file." },
+ { KNOT_ENOZONE, "No such zone found." },
+ { KNOT_ENONODE, "No such node in zone found." },
+ { KNOT_ENORRSET, "No such RRSet found." },
+ { KNOT_EDNAMEPTR, "Domain name pointer larger than allowed." },
+ { KNOT_EPAYLOAD, "Payload in OPT RR larger than max wire size." },
+ { KNOT_ECRC, "CRC check failed." },
+ { KNOT_EPREREQ, "UPDATE prerequisity not met." },
+ { KNOT_ENOXFR, "Transfer was not sent." },
+ { KNOT_ENOIXFR, "Transfer is not IXFR (is in AXFR format)." },
+ { KNOT_EXFRREFUSED, "Zone transfer refused by the server." },
+ { KNOT_EDENIED, "Not allowed." },
+ { KNOT_ECONN, "Connection reset." },
+ { KNOT_EIXFRSPACE, "IXFR reply did not fit in." },
+ { KNOT_ECNAME, "CNAME loop found in zone." },
+ { KNOT_ENODIFF, "Cannot create zone diff." },
+ { KNOT_EDSDIGESTLEN, "DS digest length does not match digest type." },
+ { KNOT_ENOTSIG, "expected a TSIG or SIG(0)" },
+ { KNOT_ELIMIT, "Exceeded response rate limit." },
+
+ /* Control states. */
+ { KNOT_CTL_STOP, "Stopping server." },
+ { KNOT_CTL_RESTART, "Restarting server." },
+
+ /* Network errors. */
+ { KNOT_NET_EADDR, "Bad address or host name." },
+ { KNOT_NET_ESOCKET, "Can't create socket." },
+ { KNOT_NET_ECONNECT, "Can't connect." },
+ { KNOT_NET_ESEND, "Can't send data." },
+ { KNOT_NET_ERECV, "Can't receive data." },
+ { KNOT_NET_ETIMEOUT, "Network timeout." },
+
+ /* Zone file loader errors. */
+ { FLOADER_EFSTAT, "Fstat error." },
+ { FLOADER_EDIRECTORY, "Zone file is a directory." },
+ { FLOADER_EEMPTY, "Empty zone file." },
+ { FLOADER_EDEFAULTS, "Zone defaults processing error." },
+ { FLOADER_EMMAP, "Mmap error." },
+ { FLOADER_EMUNMAP, "Munmap error." },
+ { FLOADER_ESCANNER, "Zone processing error." },
+
+ /* Zone scanner errors. */
+ { ZSCANNER_UNCOVERED_STATE, "General scanner error." },
+ { ZSCANNER_ELEFT_PARENTHESIS, "Too many left parentheses." },
+ { ZSCANNER_ERIGHT_PARENTHESIS, "Too many right parentheses." },
+ { ZSCANNER_EUNSUPPORTED_TYPE, "Unsupported record type." },
+ { ZSCANNER_EBAD_PREVIOUS_OWNER, "Previous owner is invalid." },
+ { ZSCANNER_EBAD_DNAME_CHAR, "Bad domain name character." },
+ { ZSCANNER_EBAD_OWNER, "Owner is invalid." },
+ { ZSCANNER_ELABEL_OVERFLOW, "Maximal domain name label length has exceeded." },
+ { ZSCANNER_EDNAME_OVERFLOW, "Maximal domain name length has exceeded." },
+ { ZSCANNER_EBAD_NUMBER, "Bad number." },
+ { ZSCANNER_ENUMBER64_OVERFLOW, "Number is too big." },
+ { ZSCANNER_ENUMBER32_OVERFLOW, "Number is bigger than 32 bits." },
+ { ZSCANNER_ENUMBER16_OVERFLOW, "Number is bigger than 16 bits." },
+ { ZSCANNER_ENUMBER8_OVERFLOW, "Number is bigger than 8 bits." },
+ { ZSCANNER_EFLOAT_OVERFLOW, "Float number overflow." },
+ { ZSCANNER_ERDATA_OVERFLOW, "Maximal record data length has exceeded." },
+ { ZSCANNER_EITEM_OVERFLOW, "Maximal item length has exceeded." },
+ { ZSCANNER_EBAD_ADDRESS_CHAR, "Bad address character." },
+ { ZSCANNER_EBAD_IPV4, "Bad IPv4 address." },
+ { ZSCANNER_EBAD_IPV6, "Bad IPv6 address." },
+ { ZSCANNER_EBAD_GATEWAY, "Bad gateway." },
+ { ZSCANNER_EBAD_GATEWAY_KEY, "Bad gateway key." },
+ { ZSCANNER_EBAD_APL, "Bad adress prefix list." },
+ { ZSCANNER_EBAD_RDATA, "Bad record data." },
+ { ZSCANNER_EBAD_HEX_RDATA, "Bad record data in hex format." },
+ { ZSCANNER_EBAD_HEX_CHAR, "Bad hexadecimal character." },
+ { ZSCANNER_EBAD_BASE64_CHAR, "Bad Base64 character." },
+ { ZSCANNER_EBAD_BASE32HEX_CHAR, "Bad Base32hex character." },
+ { ZSCANNER_EBAD_REST, "Unexpected data." },
+ { ZSCANNER_EBAD_TIMESTAMP_CHAR, "Bad timestamp character." },
+ { ZSCANNER_EBAD_TIMESTAMP_LENGTH, "Bad timestamp length." },
+ { ZSCANNER_EBAD_TIMESTAMP, "Bad timestamp." },
+ { ZSCANNER_EBAD_DATE, "Bad date." },
+ { ZSCANNER_EBAD_TIME, "Bad time." },
+ { ZSCANNER_EBAD_TIME_UNIT, "Bad time unit." },
+ { ZSCANNER_EBAD_BITMAP, "Bad bitmap." },
+ { ZSCANNER_ETEXT_OVERFLOW, "Text is too long." },
+ { ZSCANNER_EBAD_TEXT_CHAR, "Bad text character." },
+ { ZSCANNER_EBAD_TEXT, "Bad text string." },
+ { ZSCANNER_EBAD_DIRECTIVE, "Bad directive." },
+ { ZSCANNER_EBAD_TTL, "Bad zone TTL." },
+ { ZSCANNER_EBAD_ORIGIN, "Bad zone origin." },
+ { ZSCANNER_EBAD_INCLUDE_FILENAME, "Bad filename in include directive." },
+ { ZSCANNER_EBAD_INCLUDE_ORIGIN, "Bad origin in include directive." },
+ { ZSCANNER_EUNPROCESSED_INCLUDE, "Include file processing error." },
+ { ZSCANNER_EUNOPENED_INCLUDE, "Include file opening error." },
+ { ZSCANNER_EBAD_RDATA_LENGTH, "The rdata length statement is incorrect." },
+ { ZSCANNER_ECANNOT_TEXT_DATA, "Unable to process text form for this type." },
+ { ZSCANNER_EBAD_LOC_DATA, "Bad zone location data." },
+ { ZSCANNER_EUNKNOWN_BLOCK, "Unknown rdata block." },
+ { ZSCANNER_EBAD_ALGORITHM, "Bad algorithm." },
+ { ZSCANNER_EBAD_CERT_TYPE, "Bad certificate type." },
+ { ZSCANNER_EBAD_EUI_LENGTH, "Bad EUI length." },
+ { ZSCANNER_EBAD_L64_LENGTH, "Bad 64-bit locator." },
+ { ZSCANNER_EBAD_CHAR_COLON, "Missing colon character." },
+ { ZSCANNER_EBAD_CHAR_DASH, "Missing dash character." },
+
+ /* Encoding errors. */
+ { KNOT_BASE64_ESIZE, "Invalid base64 string length." },
+ { KNOT_BASE64_ECHAR, "Invalid base64 character." },
+ { KNOT_BASE32HEX_ESIZE, "Invalid base32hex string length." },
+ { KNOT_BASE32HEX_ECHAR, "Invalid base32hex character." },
+
+ /* Key parsing errors. */
+ { KNOT_KEY_EPUBLIC_KEY_OPEN, "Cannot open public key file." },
+ { KNOT_KEY_EPRIVATE_KEY_OPEN, "Cannot open private key file." },
+ { KNOT_KEY_EPUBLIC_KEY_INVALID, "Public key file is invalid." },
+
+ /* Key signing errors. */
+ { KNOT_DNSSEC_ENOTSUP, "Signing algorithm is not supported." },
+ { KNOT_DNSSEC_EINVALID_KEY, "The signing key is invalid." },
+ { KNOT_DNSSEC_EASSIGN_KEY, "Cannot assign the key." },
+ { KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT, "Cannot create digest context." },
+ { KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE, "Unexpected signature size." },
+ { KNOT_DNSSEC_EDECODE_RAW_SIGNATURE, "Cannot decode the raw signature." },
+ { KNOT_DNSSEC_ESIGN, "Cannot create the signature." },
+
+ { KNOT_ERROR, 0 } /* Terminator */
};
diff --git a/src/common/errcode.h b/src/common/errcode.h
index b2afae5..13d1943 100644
--- a/src/common/errcode.h
+++ b/src/common/errcode.h
@@ -1,56 +1,62 @@
/*!
- * \file errcode.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- * \author Marek Vavrusa <marek.vavrusa@nic.cz>
- *
- * \brief Error codes and function for getting error message.
- *
- * \addtogroup common_lib
- * @{
- */
+* \file errcode.h
+*
+* \author Lubos Slovak <lubos.slovak@nic.cz>
+* \author Marek Vavrusa <marek.vavrusa@nic.cz>
+*
+* \brief Error codes and function for getting error message.
+*
+* \addtogroup common_lib
+* @{
+*/
/* Copyright (C) 2011 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 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.
+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/>.
- */
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
#ifndef _KNOTD_COMMON_ERRCODE_H_
#define _KNOTD_COMMON_ERRCODE_H_
#include "common/errors.h"
+/* errno -> Knot error mapping.
+ * \note offset is required, otherwise it would interfere with TSIG errors.
+ */
+#define ERRBASE 100
+#define err2code(x) (-(ERRBASE + (x)))
+
/*! \brief Error codes used in the library. */
enum knot_error {
- KNOT_EOK = 0, /*!< OK */
-
+ KNOT_EOK = 0, /*!< OK */
+
/* TSIG errors. */
- KNOT_TSIG_EBADSIG = -16, /*!< Failed to verify TSIG MAC. */
- KNOT_TSIG_EBADKEY = -17, /*!< TSIG key not recognized or invalid. */
- KNOT_TSIG_EBADTIME = -18, /*!< TSIG signing time out of range. */
-
+ KNOT_TSIG_EBADSIG = -16, /*!< Failed to verify TSIG MAC. */
+ KNOT_TSIG_EBADKEY = -17, /*!< TSIG key not recognized or invalid. */
+ KNOT_TSIG_EBADTIME = -18, /*!< TSIG signing time out of range. */
+
/* Directly mapped error codes. */
- KNOT_ENOMEM = -ENOMEM, /*!< Out of memory. */
- KNOT_EINVAL = -EINVAL, /*!< Invalid parameter passed. */
- KNOT_ENOTSUP = -ENOTSUP, /*!< Parameter not supported. */
- KNOT_EBUSY = -EBUSY, /*!< Requested resource is busy. */
- KNOT_EAGAIN = -EAGAIN, /*!< OS lacked necessary resources. */
- KNOT_EACCES = -EACCES, /*!< Permission is denied. */
- KNOT_ECONNREFUSED = -ECONNREFUSED, /*!< Connection is refused. */
- KNOT_EISCONN = -EISCONN, /*!< Already connected. */
- KNOT_EADDRINUSE = -EADDRINUSE, /*!< Address already in use. */
- KNOT_ENOENT = -ENOENT, /*!< Resource not found. */
- KNOT_ERANGE = -ERANGE, /*!< Value is out of range. */
+ KNOT_ENOMEM = err2code(ENOMEM), /*!< Out of memory. */
+ KNOT_EINVAL = err2code(EINVAL), /*!< Invalid parameter passed. */
+ KNOT_ENOTSUP = err2code(ENOTSUP), /*!< Parameter not supported. */
+ KNOT_EBUSY = err2code(EBUSY), /*!< Requested resource is busy. */
+ KNOT_EAGAIN = err2code(EAGAIN), /*!< OS lacked necessary resources. */
+ KNOT_EACCES = err2code(EACCES), /*!< Permission is denied. */
+ KNOT_ECONNREFUSED = err2code(ECONNREFUSED), /*!< Connection is refused. */
+ KNOT_EISCONN = err2code(EISCONN), /*!< Already connected. */
+ KNOT_EADDRINUSE = err2code(EADDRINUSE), /*!< Address already in use. */
+ KNOT_ENOENT = err2code(ENOENT), /*!< Resource not found. */
+ KNOT_ERANGE = err2code(ERANGE), /*!< Value is out of range. */
/* General errors. */
KNOT_ERROR = -10000, /*!< General error. */
@@ -78,13 +84,114 @@ enum knot_error {
KNOT_ENOXFR, /*!< Transfer was not sent. */
KNOT_ENOIXFR, /*!< Transfer is not IXFR (is in AXFR format). */
KNOT_EXFRREFUSED, /*!< Zone transfer refused by the server. */
- KNOT_EXFRDENIED, /*!< Transfer not allowed. */
+ KNOT_EDENIED, /*!< Not allowed. */
KNOT_ECONN, /*!< Connection reset. */
KNOT_EIXFRSPACE, /*!< IXFR reply did not fit in. */
KNOT_ECNAME, /*!< CNAME loop found in zone. */
KNOT_ENODIFF, /*!< No zone diff can be created. */
KNOT_EDSDIGESTLEN, /*!< DS digest length does not match digest type. */
- KNOT_ELIMIT /*!< Exceeded response rate limit. */
+ KNOT_ENOTSIG, /*!< Expected a TSIG or SIG(0). */
+ KNOT_ELIMIT, /*!< Exceeded response rate limit. */
+
+ /* Control states. */
+ KNOT_CTL_STOP, /*!< Stop requested. */
+ KNOT_CTL_RESTART, /*!< Restart requested. */
+
+ /* Network errors. */
+ KNOT_NET_EADDR,
+ KNOT_NET_ESOCKET,
+ KNOT_NET_ECONNECT,
+ KNOT_NET_ESEND,
+ KNOT_NET_ERECV,
+ KNOT_NET_ETIMEOUT,
+
+ /* Zone file loader errors. */
+ FLOADER_EFSTAT,
+ FLOADER_EDIRECTORY,
+ FLOADER_EWRITABLE,
+ FLOADER_EEMPTY,
+ FLOADER_EDEFAULTS,
+ FLOADER_EMMAP,
+ FLOADER_EMUNMAP,
+ FLOADER_ESCANNER,
+
+ /* Zone scanner errors. */
+ ZSCANNER_UNCOVERED_STATE,
+ ZSCANNER_ELEFT_PARENTHESIS,
+ ZSCANNER_ERIGHT_PARENTHESIS,
+ ZSCANNER_EUNSUPPORTED_TYPE,
+ ZSCANNER_EBAD_PREVIOUS_OWNER,
+ ZSCANNER_EBAD_DNAME_CHAR,
+ ZSCANNER_EBAD_OWNER,
+ ZSCANNER_ELABEL_OVERFLOW,
+ ZSCANNER_EDNAME_OVERFLOW,
+ ZSCANNER_EBAD_NUMBER,
+ ZSCANNER_ENUMBER64_OVERFLOW,
+ ZSCANNER_ENUMBER32_OVERFLOW,
+ ZSCANNER_ENUMBER16_OVERFLOW,
+ ZSCANNER_ENUMBER8_OVERFLOW,
+ ZSCANNER_EFLOAT_OVERFLOW,
+ ZSCANNER_ERDATA_OVERFLOW,
+ ZSCANNER_EITEM_OVERFLOW,
+ ZSCANNER_EBAD_ADDRESS_CHAR,
+ ZSCANNER_EBAD_IPV4,
+ ZSCANNER_EBAD_IPV6,
+ ZSCANNER_EBAD_GATEWAY,
+ ZSCANNER_EBAD_GATEWAY_KEY,
+ ZSCANNER_EBAD_APL,
+ ZSCANNER_EBAD_RDATA,
+ ZSCANNER_EBAD_HEX_RDATA,
+ ZSCANNER_EBAD_HEX_CHAR,
+ ZSCANNER_EBAD_BASE64_CHAR,
+ ZSCANNER_EBAD_BASE32HEX_CHAR,
+ ZSCANNER_EBAD_REST,
+ ZSCANNER_EBAD_TIMESTAMP_CHAR,
+ ZSCANNER_EBAD_TIMESTAMP_LENGTH,
+ ZSCANNER_EBAD_TIMESTAMP,
+ ZSCANNER_EBAD_DATE,
+ ZSCANNER_EBAD_TIME,
+ ZSCANNER_EBAD_TIME_UNIT,
+ ZSCANNER_EBAD_BITMAP,
+ ZSCANNER_ETEXT_OVERFLOW,
+ ZSCANNER_EBAD_TEXT_CHAR,
+ ZSCANNER_EBAD_TEXT,
+ ZSCANNER_EBAD_DIRECTIVE,
+ ZSCANNER_EBAD_TTL,
+ ZSCANNER_EBAD_ORIGIN,
+ ZSCANNER_EBAD_INCLUDE_FILENAME,
+ ZSCANNER_EBAD_INCLUDE_ORIGIN,
+ ZSCANNER_EUNPROCESSED_INCLUDE,
+ ZSCANNER_EUNOPENED_INCLUDE,
+ ZSCANNER_EBAD_RDATA_LENGTH,
+ ZSCANNER_ECANNOT_TEXT_DATA,
+ ZSCANNER_EBAD_LOC_DATA,
+ ZSCANNER_EUNKNOWN_BLOCK,
+ ZSCANNER_EBAD_ALGORITHM,
+ ZSCANNER_EBAD_CERT_TYPE,
+ ZSCANNER_EBAD_EUI_LENGTH,
+ ZSCANNER_EBAD_L64_LENGTH,
+ ZSCANNER_EBAD_CHAR_COLON,
+ ZSCANNER_EBAD_CHAR_DASH,
+
+ /* Encoding errors. */
+ KNOT_BASE64_ESIZE,
+ KNOT_BASE64_ECHAR,
+ KNOT_BASE32HEX_ESIZE,
+ KNOT_BASE32HEX_ECHAR,
+
+ /* Key parsing errors. */
+ KNOT_KEY_EPUBLIC_KEY_OPEN,
+ KNOT_KEY_EPRIVATE_KEY_OPEN,
+ KNOT_KEY_EPUBLIC_KEY_INVALID,
+
+ /* Key signing errors. */
+ KNOT_DNSSEC_ENOTSUP,
+ KNOT_DNSSEC_EINVALID_KEY,
+ KNOT_DNSSEC_EASSIGN_KEY,
+ KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT,
+ KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE,
+ KNOT_DNSSEC_EDECODE_RAW_SIGNATURE,
+ KNOT_DNSSEC_ESIGN
};
/*! \brief Table linking error messages to error codes. */
diff --git a/src/common/errors.c b/src/common/errors.c
index 11aff95..73f0ce7 100644
--- a/src/common/errors.c
+++ b/src/common/errors.c
@@ -14,11 +14,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "common/errors.h"
+#include "common/errcode.h"
/*!
* \brief Looks up the given id in the lookup table.
@@ -65,7 +67,7 @@ int _map_errno(int fallback_value, int arg0, ...)
if (c == errno) {
/* Return negative value of the code. */
va_end(ap);
- return -abs(c);
+ return err2code(abs(c));
}
}
va_end(ap);
diff --git a/src/common/evqueue.c b/src/common/evqueue.c
index efd6d4d..097d177 100644
--- a/src/common/evqueue.c
+++ b/src/common/evqueue.c
@@ -14,10 +14,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
-#include <config.h>
#include "common/evqueue.h"
#include "common/fdset.h"
@@ -133,4 +133,3 @@ int evqueue_add(evqueue_t *q, const event_t *ev)
return 0;
}
-
diff --git a/src/common/evsched.c b/src/common/evsched.c
index 5e2073a..5061fe6 100644
--- a/src/common/evsched.c
+++ b/src/common/evsched.c
@@ -14,10 +14,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
-#include <config.h>
#include "common/evsched.h"
@@ -100,20 +100,21 @@ void evsched_delete(evsched_t **s)
pthread_mutex_destroy(&(*s)->mx);
pthread_cond_destroy(&(*s)->notify);
- while (! EMPTY_HEAP(&(*s)->heap)) /* FIXME: Would be faster to simply walk through the array */
+#ifndef OPENBSD_SLAB_BROKEN
+ /* Free allocator (all events at once). */
+ slab_cache_destroy(&(*s)->cache.alloc);
+#else
+ while (! EMPTY_HEAP(&(*s)->heap))
{
event_t *e = *((event_t**)(HHEAD(&(*s)->heap)));
heap_delmin(&(*s)->heap);
evsched_event_free((*s), e);
}
-
+#endif
+
free((*s)->heap.data);
(*s)->heap.data = NULL;;
-#ifndef OPENBSD_SLAB_BROKEN
- /* Free allocator. */
- slab_cache_destroy(&(*s)->cache.alloc);
-#endif
pthread_mutex_destroy(&(*s)->cache.lock);
/* Free scheduler. */
@@ -195,7 +196,7 @@ event_t* evsched_next(evsched_t *s)
pthread_mutex_lock(&s->mx);
continue;
}
-
+
return next_ev;
}
@@ -243,10 +244,10 @@ int evsched_schedule(evsched_t *s, event_t *ev, uint32_t dt)
/* Update event timer. */
evsched_settimer(ev, dt);
ev->parent = s;
-
+
/* Lock calendar. */
pthread_mutex_lock(&s->mx);
-
+
heap_insert(&s->heap, ev);
/* Unlock calendar. */
@@ -317,7 +318,7 @@ int evsched_cancel(evsched_t *s, event_t *ev)
if ((found = heap_find(&s->heap, ev))) {
heap_delete(&s->heap, found);
}
-
+
/* Check if not being processed, invalidate if yes.
* Could happen if next 'cur' was set, but
* the evsched_next() waits until we release rl.
@@ -336,4 +337,3 @@ int evsched_cancel(evsched_t *s, event_t *ev)
return found;
}
-
diff --git a/src/common/fdset.c b/src/common/fdset.c
index c304840..3b4b75a 100644
--- a/src/common/fdset.c
+++ b/src/common/fdset.c
@@ -14,16 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* Required for RTLD_DEFAULT. */
-#endif
-
+#include <config.h>
#include <dlfcn.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
-#include <config.h>
#include "common/fdset.h"
/* Workarounds for clock_gettime() not available on some platforms. */
@@ -39,6 +35,7 @@ typedef struct timeval timev_t;
#endif
struct fdset_backend_t _fdset_backend = {
+ NULL
};
/*! \brief Set backend implementation. */
@@ -146,13 +143,13 @@ int fdset_set_watchdog(fdset_t* fdset, int fd, int interval)
if (base == NULL || base->atimes == NULL) {
return -1;
}
-
+
/* Lift watchdog if interval is negative. */
if (interval < 0) {
skip_remove(base->atimes, (void*)((size_t)fd), NULL, free);
return 0;
}
-
+
/* Find if exists. */
timev_t *ts = NULL;
ts = (timev_t*)skip_find(base->atimes, (void*)((size_t)fd));
@@ -163,12 +160,12 @@ int fdset_set_watchdog(fdset_t* fdset, int fd, int interval)
}
skip_insert(base->atimes, (void*)((size_t)fd), (void*)ts, NULL);
}
-
+
/* Update clock. */
if (time_now(ts) < 0) {
return -1;
}
-
+
ts->tv_sec += interval; /* Only seconds precision. */
return 0;
}
@@ -179,19 +176,19 @@ int fdset_sweep(fdset_t* fdset, void(*cb)(fdset_t*, int, void*), void *data)
if (base == NULL || base->atimes == NULL) {
return -1;
}
-
+
/* Get time threshold. */
timev_t now;
if (time_now(&now) < 0) {
return -1;
}
-
+
/* Inspect all nodes. */
int sweeped = 0;
const skip_node_t *n = skip_first(base->atimes);
while (n != NULL) {
const skip_node_t* pnext = skip_next(n);
-
+
/* Evaluate */
timev_t *ts = (timev_t*)n->value;
if (ts->tv_sec <= now.tv_sec) {
@@ -200,7 +197,7 @@ int fdset_sweep(fdset_t* fdset, void(*cb)(fdset_t*, int, void*), void *data)
}
n = pnext;
}
-
+
return sweeped;
}
@@ -210,7 +207,7 @@ int fdset_sweep(fdset_t* fdset, void(*cb)(fdset_t*, int, void*), void *data)
* Like select(2) but set the signals to block while waiting in
* select. This version is not entirely race condition safe. Only
* operating system support can make it so.
- *
+ *
* Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
*
* This software is open source.
@@ -269,7 +266,7 @@ pselect_compat (int n,
} else {
result = select(n, readfds, writefds, exceptfds, NULL);
}
-
+
if (sigmask && sigprocmask(SIG_SETMASK, &saved_sigmask, NULL) == -1)
return -1;
diff --git a/src/common/fdset.h b/src/common/fdset.h
index a589145..e1facdb 100644
--- a/src/common/fdset.h
+++ b/src/common/fdset.h
@@ -32,7 +32,6 @@
#ifndef _KNOTD_FDSET_H_
#define _KNOTD_FDSET_H_
-#include "config.h"
#include <stddef.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
diff --git a/src/common/fdset_epoll.c b/src/common/fdset_epoll.c
index d4481b5..f889dd3 100644
--- a/src/common/fdset_epoll.c
+++ b/src/common/fdset_epoll.c
@@ -43,11 +43,11 @@ fdset_t *fdset_epoll_new()
if (set) {
/* Blank memory. */
memset(set, 0, sizeof(fdset_t));
-
+
/* Create epoll fd. */
set->epfd = epoll_create(OS_FDS_CHUNKSIZE);
}
-
+
return set;
}
@@ -110,7 +110,7 @@ int fdset_epoll_remove(fdset_t *fdset, int fd)
/* Trim excessive memory if possible (retval is not interesting). */
mreserve((char **)&fdset->events, sizeof(struct epoll_event),
fdset->nfds + 1, OS_FDS_CHUNKSIZE, &fdset->reserved);
-
+
return 0;
}
diff --git a/src/common/fdset_kqueue.c b/src/common/fdset_kqueue.c
index a45da96..7c52f71 100644
--- a/src/common/fdset_kqueue.c
+++ b/src/common/fdset_kqueue.c
@@ -47,7 +47,7 @@ fdset_t *fdset_kqueue_new()
if (set) {
/* Blank memory. */
memset(set, 0, sizeof(fdset_t));
-
+
/* Create kqueue fd. */
set->kq = kqueue();
if (set->kq < 0) {
@@ -55,7 +55,7 @@ fdset_t *fdset_kqueue_new()
set = 0;
}
}
-
+
return set;
}
@@ -106,7 +106,7 @@ int fdset_kqueue_remove(fdset_t *fdset, int fd)
if (fdset == NULL || fd < 0) {
return -1;
}
-
+
/* Find in set. */
int pos = -1;
for (int i = 0; i < fdset->nfds; ++i) {
@@ -115,11 +115,11 @@ int fdset_kqueue_remove(fdset_t *fdset, int fd)
break;
}
}
-
+
if (pos < 0) {
return -1;
}
-
+
/* Remove filters. */
EV_SET(&fdset->events[pos], fd, EVFILT_READ,
EV_DISABLE|EV_DELETE, 0, 0, 0);
@@ -127,7 +127,7 @@ int fdset_kqueue_remove(fdset_t *fdset, int fd)
/* Attempt to remove from set. */
size_t remaining = ((fdset->nfds - pos) - 1) * sizeof(struct kevent);
memmove(fdset->events + pos, fdset->events + (pos + 1), remaining);
-
+
/* Attempt to remove from revents set. */
pos = -1;
for (int i = 0; i < fdset->nfds; ++i) {
@@ -141,7 +141,7 @@ int fdset_kqueue_remove(fdset_t *fdset, int fd)
memmove(fdset->revents + pos, fdset->revents + (pos + 1), remaining);
}
-
+
/* Overwrite current item. */
--fdset->nfds;
diff --git a/src/common/fdset_poll.c b/src/common/fdset_poll.c
index 9b1c135..e16ae11 100644
--- a/src/common/fdset_poll.c
+++ b/src/common/fdset_poll.c
@@ -108,7 +108,7 @@ int fdset_poll_remove(fdset_t *fdset, int fd)
/* Trim excessive memory if possible (retval is not interesting). */
mreserve((char **)&fdset->fds, sizeof(struct pollfd), fdset->nfds,
OS_FDS_CHUNKSIZE, &fdset->reserved);
-
+
return 0;
}
diff --git a/src/common/general-tree.c b/src/common/general-tree.c
deleted file mode 100644
index 1edd0f3..0000000
--- a/src/common/general-tree.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* Copyright (C) 2011 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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include "common/general-tree.h"
-
-MOD_TREE_DEFINE(general_tree_node, avl);
-
-static void gen_rem_func(struct general_tree_node *n1)
-{
- free(n1);
-}
-
-general_tree_t *gen_tree_new(int (*comp_func)(void *, void *))
-{
- general_tree_t *ret = malloc(sizeof(general_tree_t));
- if (ret == NULL) {
- return NULL;
- }
- ret->tree = malloc(sizeof(general_avl_tree_t));
- if (ret->tree == NULL) {
- free(ret);
- return NULL;
- }
- MOD_TREE_INIT(ret->tree, comp_func);
- return ret;
-}
-
-int gen_tree_add(general_tree_t *tree,
- void *node, int (*mrg_func)(void **n1, void **n2))
-{
- struct general_tree_node *tree_node =
- malloc(sizeof(struct general_tree_node));
- if (tree_node == NULL) {
- return -1;
- }
- memset(tree_node, 0, sizeof(struct general_tree_node));
- tree_node->data = node;
- int merged = 0;
- MOD_TREE_INSERT(tree->tree, general_tree_node, avl,
- tree_node, mrg_func, &merged);
- if (merged) {
- free(tree_node);
- }
- return merged;
-}
-
-void gen_tree_remove(general_tree_t *tree,
- void *what)
-{
- struct general_tree_node tree_node;
- tree_node.data = what;
- MOD_TREE_REMOVE(tree->tree, general_tree_node, avl, &tree_node,
- gen_rem_func);
-}
-
-void *gen_tree_find(general_tree_t *tree,
- void *what)
-{
- struct general_tree_node tree_node;
- tree_node.data = what;
- struct general_tree_node *found_node =
- MOD_TREE_FIND(tree->tree, general_tree_node, avl, &tree_node);
- if (found_node) {
- return found_node->data;
- } else {
- return NULL;
- }
-}
-
-int gen_tree_find_less_or_equal(general_tree_t *tree,
- void *what,
- void **found)
-{
- if (tree == NULL || tree->tree == NULL) {
- return -1;
- }
-
- /* Check if tree is empty. */
- if (tree->tree->th_root == NULL) {
- *found = NULL;
- return 0;
- }
-
- struct general_tree_node *f = NULL, *prev = NULL;
- struct general_tree_node tree_node;
- tree_node.data = what;
- int exact_match =
- MOD_TREE_FIND_LESS_EQUAL(tree->tree, general_tree_node, avl,
- &tree_node, &f, &prev);
- if (exact_match < 0) {
- *found = NULL;
- exact_match = 0;
- } else if (exact_match == 0) {
- assert(prev != NULL);
- *found = prev->data;
- } else {
- assert(f != NULL);
- *found = f->data;
- }
-// *found = (exact_match > 0) ? f->data : prev->data;
- return exact_match;
-}
-
-void gen_tree_apply_inorder(general_tree_t *tree,
- void (*app_func)
- (void *node, void *data), void *data)
-{
- MOD_TREE_FORWARD_APPLY(tree->tree, general_tree_node, avl,
- app_func, data);
-}
-
-void gen_tree_destroy(general_tree_t **tree,
- void (*dest_func)(void *node, void *data), void *data)
-{
-// gen_tree_apply_inorder(*tree, print_node, NULL);
- MOD_TREE_DESTROY((*tree)->tree, general_tree_node, avl, dest_func,
- gen_rem_func, data);
- free((*tree)->tree);
- free(*tree);
- *tree = NULL;
-}
-
-void gen_tree_clear(general_tree_t *tree)
-{
- MOD_TREE_DESTROY(tree->tree, general_tree_node, avl, NULL,
- gen_rem_func, NULL);
- tree->tree->th_root = NULL; /* Invalidate tree root. */
-}
-
-//static void add_node_to_tree(void *n, void *data)
-//{
-// general_tree_t *tree = (general_tree_t *)data;
-// gen_tree_add(tree, n, NULL);
-//}
-
-static int gen_tree_copy_node(const struct general_tree_node *from,
- struct general_tree_node **to)
-{
- if (from == NULL) {
- return 0;
- }
-
- *to = malloc(sizeof(struct general_tree_node));
- if (*to == NULL) {
- return -1;
- }
- memset(*to, 0, sizeof(struct general_tree_node));
-
- (*to)->data = from->data;
- (*to)->avl.avl_height = from->avl.avl_height;
-
- int ret = gen_tree_copy_node(from->avl.avl_left,
- &(*to)->avl.avl_left);
- if (ret != 0) {
- return ret;
- }
-
- ret = gen_tree_copy_node(from->avl.avl_right,
- &(*to)->avl.avl_right);
- if (ret != 0) {
- /*! \todo Partially cleaunp tree! */
- (*to)->avl.avl_left = NULL;
- return ret;
- }
-
- return 0;
-}
-
-general_tree_t *gen_tree_shallow_copy(general_tree_t *tree)
-{
- general_tree_t *new_tree = malloc(sizeof(general_tree_t));
- if (new_tree == NULL) {
- return NULL;
- }
- new_tree->tree = malloc(sizeof(general_avl_tree_t));
- if (new_tree->tree == NULL) {
- free(new_tree);
- return NULL;
- }
-
- MOD_TREE_INIT(new_tree->tree, tree->tree->th_cmp);
- assert(new_tree->tree->th_cmp == tree->tree->th_cmp);
-
-// gen_tree_apply_inorder(tree, add_node_to_tree, new_tree);
-
- if (gen_tree_copy_node(tree->tree->th_root,
- &new_tree->tree->th_root) != 0) {
- free(new_tree);
- return NULL;
- }
-
- /* CLEANUP */
-// gen_tree_apply_inorder(tree, print_node, NULL);
-// printf("--------------------------\n");
-// gen_tree_apply_inorder(new_tree, print_node, NULL);
-
- return new_tree;
-}
-
diff --git a/src/common/general-tree.h b/src/common/general-tree.h
deleted file mode 100644
index 552638a..0000000
--- a/src/common/general-tree.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_COMMON_GENERAL_TREE_H_
-#define _KNOTD_COMMON_GENERAL_TREE_H_
-
-#include "common/modified_tree.h"
-
-typedef MOD_TREE_HEAD(tree, general_tree_node) general_avl_tree_t;
-
-/* Define tree with void * nodes */
-struct general_tree_node {
- MOD_TREE_ENTRY(general_tree_node) avl;
-// int (*cmp_func)(void *n1,
-// void *n2);
-// int (*mrg_func)(void **n1,
-// void **n2);
-// void (*app_func)(void *n,
-// void *data);
- void *data;
-};
-
-struct general_tree {
-// int (*cmp_func)(void *n1,
-// void *n2);
-// int (*mrg_func)(void **n1,
-// void **n2);
- general_avl_tree_t *tree;
-};
-
-typedef struct general_tree general_tree_t;
-
-general_tree_t *gen_tree_new(int (*cmp_func)(void *p1, void *p2));
-
-int gen_tree_add(general_tree_t *tree,
- void *node,
- int (*mrg_func)(void **n1, void **n2));
-
-void *gen_tree_find(general_tree_t *tree,
- void *what);
-
-void gen_tree_remove(general_tree_t *tree,
- void *what);
-
-void gen_tree_apply_inorder(general_tree_t *tree,
- void (*app_func)(void *node, void *data),
- void *data);
-
-void gen_tree_destroy(general_tree_t **tree,
- void (*dest_func)(void *node, void *data), void *data);
-
-void gen_tree_clear(general_tree_t *tree);
-
-int gen_tree_find_less_or_equal(general_tree_t *tree,
- void *what,
- void **found);
-
-general_tree_t *gen_tree_shallow_copy(general_tree_t *tree);
-
-#endif // _KNOTD_COMMON_GENERAL_TREE_H_
diff --git a/src/common/getline.c b/src/common/getline.c
new file mode 100644
index 0000000..b2fa94e
--- /dev/null
+++ b/src/common/getline.c
@@ -0,0 +1,61 @@
+/* Copyright (C) 2011 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/>.
+*/
+
+// FreeBSD POSIX2008 getline
+#ifndef _WITH_GETLINE
+#define _WITH_GETLINE
+#endif
+
+#include <config.h>
+#include "common/getline.h"
+
+#include <stdio.h> // getline or fgetln
+#include <stdlib.h> // free
+#include <string.h> // memcpy
+
+ssize_t knot_getline(char **lineptr, size_t *n, FILE *stream)
+{
+#ifdef HAVE_GETLINE
+ return getline(lineptr, n, stream);
+#else
+#ifdef HAVE_FGETLN
+ size_t length = 0;
+ char *buffer = fgetln(stream, &length);
+ if (buffer == NULL) {
+ return -1;
+ }
+
+ /* NOTE: Function fgetln doesn't return terminated string!
+ * Output buffer from the fgetln can't be freed.
+ */
+
+ // If the output buffer is not specified or is small, extend it.
+ if (*lineptr == NULL || *n <= length) {
+ char *tmp = realloc(*lineptr, length + 1);
+ if (tmp == NULL) {
+ return -1;
+ }
+ *lineptr = tmp;
+ }
+
+ memcpy(*lineptr, buffer, length);
+ (*lineptr)[length] = '\0';
+ *n = length;
+
+ return length;
+#endif
+#endif
+}
diff --git a/src/common/getline.h b/src/common/getline.h
new file mode 100644
index 0000000..8a0574a
--- /dev/null
+++ b/src/common/getline.h
@@ -0,0 +1,51 @@
+/* Copyright (C) 2011 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 getline.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief Multiplatform getline wrapper.
+ *
+ * \addtogroup common_lib
+ * @{
+ */
+
+#ifndef _GETLINE_H_
+#define _GETLINE_H_
+
+#include <stdio.h>
+#include <sys/types.h>
+
+/*!
+ * \brief Reads a line from a stream.
+ *
+ * This function has the same semantics as POSIX.1-2008 getline().
+ * If necessary, the output buffer will be allocated/reallocated.
+ *
+ * \param lineptr Output buffer.
+ * \param n Output buffer size.
+ * \param stream Input stream.
+ *
+ * \retval Number of characters read, including new line delimiter,
+ * not including terminating. -1 on error or EOF.
+ */
+ssize_t knot_getline(char **lineptr, size_t *n, FILE *stream);
+
+#endif // _GETLINE_H_
+
+/*! @} */
diff --git a/src/common/hattrie/ahtable.c b/src/common/hattrie/ahtable.c
new file mode 100644
index 0000000..e8e2b45
--- /dev/null
+++ b/src/common/hattrie/ahtable.c
@@ -0,0 +1,656 @@
+/*
+ * This file is part of hat-trie.
+ *
+ * Copyright (c) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
+ *
+ */
+
+#include <config.h>
+#include <assert.h>
+#include <string.h>
+#include "ahtable.h"
+#include "murmurhash3.h"
+
+enum {
+ AH_SORTED = 0x01,/* sorted iteration */
+ AH_INDEXED = 0x02 /* reuse index from table */
+};
+
+const size_t ahtable_max_load_factor = 10000.0; /* arbitrary large number => don't resize */
+static const uint16_t LONG_KEYLEN_MASK = 0x7fff;
+
+/* Allocate by larger chunks to avoid frequent reallocs. */
+/* http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
+static inline unsigned next_size(unsigned v) {
+ --v;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ return (++v) << 1; /* x2 */
+}
+
+static size_t keylen(slot_t s) {
+ if (0x1 & *s) {
+ return (size_t) (*((uint16_t*) s) >> 1);
+ }
+ else {
+ return (size_t) (*s >> 1);
+ }
+}
+
+static value_t* slotval(slot_t s)
+{
+ size_t k = keylen(s);
+ s += k < 128 ? 1 : 2;
+ s += k;
+ return (value_t*) s;
+}
+
+static const char* slotkey(slot_t s, size_t* len)
+{
+ *len = keylen(s);
+ return (const char*) (s + (*len < 128 ? 1 : 2));
+}
+
+static int cmpkeystr(const char* a, size_t ka, slot_t b)
+{
+ size_t kb = keylen(b);
+ b += kb < 128 ? 1 : 2;
+
+ int c = memcmp(a, b, ka < kb ? ka : kb);
+ return c == 0 ? (int) ka - (int) kb : c;
+}
+
+static int cmpkey(const void* a_, const void* b_)
+{
+ slot_t a = *(slot_t*) a_;
+ slot_t b = *(slot_t*) b_;
+
+ size_t ka = keylen(a), kb = keylen(b);
+
+ a += ka < 128 ? 1 : 2;
+ b += kb < 128 ? 1 : 2;
+
+ int c = memcmp(a, b, ka < kb ? ka : kb);
+ return c == 0 ? (int) ka - (int) kb : c;
+}
+
+ahtable_t* ahtable_create()
+{
+ return ahtable_create_n(AHTABLE_INIT_SIZE);
+}
+
+
+ahtable_t* ahtable_create_n(size_t n)
+{
+ ahtable_t* T = malloc(sizeof(ahtable_t));
+ memset(T, 0, sizeof(ahtable_t));
+
+ T->n = n;
+ T->max_m = (size_t) (ahtable_max_load_factor * (double) T->n);
+ T->slots = malloc(n * sizeof(slot_t));
+ memset(T->slots, 0, n * sizeof(slot_t));
+
+ const size_t sslen = 2 * T->n * sizeof(uint32_t); /* used | reserved */
+ T->slot_sizes = malloc(sslen);
+ memset(T->slot_sizes, 0, sslen);
+
+ return T;
+}
+
+
+void ahtable_free(ahtable_t* T)
+{
+ if (T == NULL) return;
+ size_t i;
+ for (i = 0; i < T->n; ++i) free(T->slots[i]);
+ free(T->slots);
+ free(T->slot_sizes);
+ free(T->index);
+ free(T);
+}
+
+
+size_t ahtable_size(const ahtable_t* T)
+{
+ return T->m;
+}
+
+
+void ahtable_clear(ahtable_t* T)
+{
+ size_t i;
+ for (i = 0; i < T->n; ++i) free(T->slots[i]);
+ T->n = AHTABLE_INIT_SIZE;
+ T->slots = realloc(T->slots, T->n * sizeof(slot_t));
+ memset(T->slots, 0, T->n * sizeof(slot_t));
+
+ const size_t sslen = 2 * T->n * sizeof(uint32_t); /* used | reserved */
+ T->slot_sizes = realloc(T->slot_sizes, sslen);
+ memset(T->slot_sizes, 0, sslen);
+
+ if (T->index) {
+ free(T->index);
+ T->index = NULL;
+ }
+}
+
+
+static slot_t ins_key(slot_t s, const char* key, size_t len, value_t** val)
+{
+ // key length
+ if (len < 128) {
+ s[0] = (unsigned char) (len << 1);
+ s += 1;
+ }
+ else {
+ /* The most significant bit is set to indicate that two bytes are
+ * being used to store the key length. */
+ *((uint16_t*) s) = ((uint16_t) len << 1) | 0x1;
+ s += 2;
+ }
+
+ // key
+ memcpy(s, key, len * sizeof(unsigned char));
+ s += len;
+
+ // value
+ *val = (value_t*) s;
+ **val = 0;
+ s += sizeof(value_t);
+
+ return s;
+}
+
+
+static void ahtable_expand(ahtable_t* T)
+{
+ /* Resizing a table is essentially building a brand new one.
+ * One little shortcut we can take on the memory allocation front is to
+ * figure out how much memory each slot needs in advance.
+ */
+ assert(T->n > 0);
+ size_t new_n = 2 * T->n;
+ size_t slot_scount = 2 * new_n; /* used | reserved */
+ uint32_t* slot_sizes = malloc(slot_scount * sizeof(uint32_t));
+ memset(slot_sizes, 0, slot_scount * sizeof(uint32_t));
+
+ const char* key;
+ size_t len = 0;
+ size_t m = 0;
+ size_t h;
+ ahtable_iter_t i;
+ ahtable_iter_begin(T, &i, false);
+ while (!ahtable_iter_finished(&i)) {
+ key = ahtable_iter_key(&i, &len);
+ h = hash(key, len) % new_n;
+ slot_sizes[h] +=
+ len + sizeof(value_t) + (len >= 128 ? 2 : 1);
+ slot_sizes[new_n + h] = slot_sizes[h];
+
+ ++m;
+ ahtable_iter_next(&i);
+ }
+ assert(m == T->m);
+ ahtable_iter_free(&i);
+
+
+ /* allocate slots */
+ slot_t* slots = malloc(new_n * sizeof(slot_t));
+ size_t j;
+ for (j = 0; j < new_n; ++j) {
+ if (slot_sizes[j] > 0) {
+ slots[j] = malloc(slot_sizes[j]);
+ }
+ else slots[j] = NULL;
+ }
+
+ /* rehash values. A few shortcuts can be taken here as well, as we know
+ * there will be no collisions. Instead of the regular insertion routine,
+ * we keep track of the ends of every slot and simply insert keys.
+ * */
+ slot_t* slots_next = malloc(new_n * sizeof(slot_t));
+ memcpy(slots_next, slots, new_n * sizeof(slot_t));
+ m = 0;
+ value_t* u;
+ value_t* v;
+ ahtable_iter_begin(T, &i, false);
+ while (!ahtable_iter_finished(&i)) {
+
+ key = ahtable_iter_key(&i, &len);
+ h = hash(key, len) % new_n;
+
+ slots_next[h] = ins_key(slots_next[h], key, len, &u);
+ v = ahtable_iter_val(&i);
+ *u = *v;
+
+ ++m;
+ ahtable_iter_next(&i);
+ }
+ assert(m == T->m);
+ ahtable_iter_free(&i);
+
+
+ free(slots_next);
+ for (j = 0; j < T->n; ++j) free(T->slots[j]);
+
+ free(T->slots);
+ T->slots = slots;
+
+ free(T->slot_sizes);
+ T->slot_sizes = slot_sizes;
+
+ T->n = new_n;
+ T->max_m = (size_t) (ahtable_max_load_factor * (double) T->n);
+}
+
+static value_t* insert_key(ahtable_t* T, uint32_t h, const char* key, size_t len)
+{
+ uint32_t new_size = T->slot_sizes[h];
+ new_size += (len >= 128 ? 2 : 1); // key length
+ new_size += len * sizeof(unsigned char); // key
+ new_size += sizeof(value_t); // value
+
+ /* fetch reserved size */
+ uint32_t* reserved = &T->slot_sizes[T->n + h];
+ if (*reserved < new_size) {
+ *reserved = next_size(new_size);
+ T->slots[h] = realloc(T->slots[h], *reserved);
+ }
+ ++T->m;
+
+ value_t *val = NULL;
+ ins_key(T->slots[h] + T->slot_sizes[h], key, len, &val);
+ T->slot_sizes[h] = new_size;
+
+ return val;
+}
+
+
+static value_t* find_val(ahtable_t* T, const char* key, size_t len, uint32_t i)
+{
+ size_t k = 0;
+
+ /* search the array for our key */
+ slot_t s = T->slots[i];
+ slot_t np = T->slots[i] + T->slot_sizes[i];
+ while (s < np) {
+ /* get the key length */
+ k = keylen(s);
+ s += k < 128 ? 1 : 2;
+
+ /* skip keys that are longer than ours */
+ if (k != len) {
+ s += k + sizeof(value_t);
+ continue;
+ }
+
+ /* key found. */
+ if (memcmp(s, key, len) == 0) {
+ return (value_t*) (s + len);
+ }
+ /* key not found. */
+ else {
+ s += k + sizeof(value_t);
+ continue;
+ }
+ }
+
+ return NULL;
+}
+
+
+value_t* ahtable_get(ahtable_t* T, const char* key, size_t len)
+{
+ /* if we are at capacity, preemptively resize */
+ if (T->m >= T->max_m) {
+ ahtable_expand(T);
+ }
+
+ /* attempt to find value for given key */
+ uint32_t i = hash(key, len) % T->n;
+ value_t *ret = find_val(T, key, len, i);
+ if (ret == NULL) { /* insert if not found */
+ ret = insert_key(T, i, key, len);
+ }
+
+ return ret;
+}
+
+
+value_t* ahtable_tryget(ahtable_t* T, const char* key, size_t len )
+{
+ uint32_t i = hash(key, len) % T->n;
+ return find_val(T, key, len, i);
+}
+
+value_t *ahtable_indexval(ahtable_t* T, unsigned i)
+{
+ return slotval(T->index[i]);
+}
+
+void ahtable_build_index(ahtable_t* T)
+{
+ if (T->index) {
+ free(T->index);
+ T->index = NULL;
+ }
+
+ if (T->m == 0) return;
+
+ T->index = malloc(T->m * sizeof(slot_t));
+
+ slot_t s;
+ size_t j, k, u;
+ for (j = 0, u = 0; j < T->n; ++j) {
+ s = T->slots[j];
+ while (s < T->slots[j] + T->slot_sizes[j]) {
+ T->index[u++] = s;
+ k = keylen(s);
+ s += k < 128 ? 1 : 2;
+ s += k + sizeof(value_t);
+ }
+ }
+
+ qsort(T->index, T->m, sizeof(slot_t), cmpkey);
+}
+
+int ahtable_find_leq (ahtable_t* T, const char* key, size_t len, value_t** dst)
+{
+ *dst = NULL;
+ if (T->m == 0) return 1;
+ assert(T->index != NULL);
+
+ /* the array is T->m size and sorted, use binary search */
+ int r = 0;
+ int a = 0, b = T->m - 1, k = 0;
+ while (a <= b) {
+ k = (a + b) / 2; /* divide interval */
+ r = cmpkeystr(key, len, T->index[k]);
+ if (r == 0) {
+ break;
+ }
+ if (r < 0) {
+ b = k - 1;
+ } else {
+ a = k + 1;
+ }
+
+ }
+
+
+ if (r < 0) {
+ --k; /* k is after previous node */
+ r = -1;
+ } else if (r > 0) {
+ r = -1; /* k is previous node */
+ }
+ if (k > -1) {
+ *dst = ahtable_indexval(T, k);
+ }
+
+ return r;
+}
+
+void ahtable_insert (ahtable_t* T, const char* key, size_t len, value_t val)
+{
+ /* if we are at capacity, preemptively resize */
+ if (T->m >= T->max_m) {
+ ahtable_expand(T);
+ }
+
+ uint32_t i = hash(key, len) % T->n;
+ *insert_key(T, i, key, len) = val;
+}
+
+
+int ahtable_del(ahtable_t* T, const char* key, size_t len)
+{
+ uint32_t i = hash(key, len) % T->n;
+ size_t k;
+ slot_t s;
+
+ /* search the array for our key */
+ s = T->slots[i];
+ while ((size_t) (s - T->slots[i]) < T->slot_sizes[i]) {
+ /* get the key length */
+ k = keylen(s);
+ s += k < 128 ? 1 : 2;
+
+ /* skip keys that are longer than ours */
+ if (k != len) {
+ s += k + sizeof(value_t);
+ continue;
+ }
+
+ /* key found. */
+ if (memcmp(s, key, len) == 0) {
+ /* move everything over, resize the array */
+ unsigned char* t = s + len + sizeof(value_t);
+ s -= k < 128 ? 1 : 2;
+ memmove(s, t, T->slot_sizes[i] - (size_t) (t - T->slots[i]));
+ T->slot_sizes[i] -= (size_t) (t - s);
+ --T->m;
+ return 0;
+ }
+ /* key not found. */
+ else {
+ s += k + sizeof(value_t);
+ continue;
+ }
+ }
+
+ // Key was not found. Do nothing.
+ return -1;
+}
+
+
+/* Sorted/unsorted iterators are kept private and exposed by passing the
+sorted flag to ahtable_iter_begin. */
+
+static void ahtable_sorted_iter_begin(ahtable_t* T, ahtable_iter_t *i)
+{
+ if (T->index) {
+ i->d.xs = T->index;
+ i->flags |= AH_INDEXED;
+ return;
+ }
+
+ i->d.xs = malloc(T->m * sizeof(slot_t));
+
+ slot_t s;
+ size_t j, k, u;
+ for (j = 0, u = 0; j < T->n; ++j) {
+ s = T->slots[j];
+ while (s < T->slots[j] + T->slot_sizes[j]) {
+ i->d.xs[u++] = s;
+ k = keylen(s);
+ s += k < 128 ? 1 : 2;
+ s += k + sizeof(value_t);
+ }
+ }
+
+ qsort(i->d.xs, T->m, sizeof(slot_t), cmpkey);
+}
+
+
+static inline bool ahtable_sorted_iter_finished(ahtable_iter_t* i)
+{
+ return i->i >= i->T->m;
+}
+
+
+static inline void ahtable_sorted_iter_next(ahtable_iter_t* i)
+{
+ if (ahtable_iter_finished(i)) return;
+ ++i->i;
+}
+
+static void ahtable_sorted_iter_del(ahtable_iter_t* i)
+{
+ if (ahtable_iter_finished(i)) return;
+ /*! \todo same as unsorted, but remove from iterator sorted array */
+ assert(0);
+}
+
+
+static inline void ahtable_sorted_iter_free(ahtable_iter_t* i)
+{
+ if (i == NULL) return;
+ if (!(i->flags & AH_INDEXED)) {
+ free(i->d.xs);
+ }
+}
+
+
+static const char* ahtable_sorted_iter_key(ahtable_iter_t* i, size_t* len)
+{
+ if (ahtable_iter_finished(i)) return NULL;
+ return slotkey(i->d.xs[i->i], len);
+}
+
+
+static value_t* ahtable_sorted_iter_val(ahtable_iter_t* i)
+{
+ if (ahtable_iter_finished(i)) return NULL;
+ return slotval(i->d.xs[i->i]);
+}
+
+static void ahtable_unsorted_iter_begin(ahtable_t* T, ahtable_iter_t *i)
+{
+ for (i->i = 0; i->i < i->T->n; ++i->i) {
+ i->d.s = T->slots[i->i];
+ if ((size_t) (i->d.s - T->slots[i->i]) >= T->slot_sizes[i->i]) continue;
+ break;
+ }
+}
+
+
+static inline bool ahtable_unsorted_iter_finished(ahtable_iter_t* i)
+{
+ return i->i >= i->T->n;
+}
+
+
+static void ahtable_unsorted_iter_next(ahtable_iter_t* i)
+{
+ if (ahtable_iter_finished(i)) return;
+
+ /* get the key length */
+ size_t k = keylen(i->d.s);
+ i->d.s += k < 128 ? 1 : 2;
+
+ /* skip to the next key */
+ i->d.s += k + sizeof(value_t);
+
+ if ((size_t) (i->d.s - i->T->slots[i->i]) >= i->T->slot_sizes[i->i]) {
+ do {
+ ++i->i;
+ } while(i->i < i->T->n &&
+ i->T->slot_sizes[i->i] == 0);
+
+ if (i->i < i->T->n) i->d.s = i->T->slots[i->i];
+ else i->d.s = NULL;
+ }
+}
+
+static void ahtable_unsorted_iter_del(ahtable_iter_t* i)
+{
+ /* get the entry length */
+ size_t k = keylen(i->d.s);
+ unsigned char* t = i->d.s + (k < 128 ? 1 : 2) + k + sizeof(value_t);
+ memmove(i->d.s, t, i->T->slot_sizes[i->i] - (size_t)(t - i->T->slots[i->i]));
+ i->T->slot_sizes[i->i] -= (size_t)(t - i->d.s);
+ --i->T->m;
+
+ /* find next filled slot*/
+ if ((size_t) (i->d.s - i->T->slots[i->i]) >= i->T->slot_sizes[i->i]) {
+ do {
+ ++i->i;
+ } while(i->i < i->T->n &&
+ i->T->slot_sizes[i->i] == 0);
+
+ if (i->i < i->T->n) i->d.s = i->T->slots[i->i];
+ else i->d.s = NULL;
+ }
+}
+
+static const char* ahtable_unsorted_iter_key(ahtable_iter_t* i, size_t* len)
+{
+ if (ahtable_iter_finished(i)) return NULL;
+
+ slot_t s = i->d.s;
+ size_t k;
+ if (0x1 & *s) {
+ k = (size_t) (*((uint16_t*) s)) >> 1;
+ s += 2;
+ }
+ else {
+ k = (size_t) (*s >> 1);
+ s += 1;
+ }
+
+ *len = k;
+ return (const char*) s;
+}
+
+
+static value_t* ahtable_unsorted_iter_val(ahtable_iter_t* i)
+{
+ if (ahtable_iter_finished(i)) return NULL;
+ return slotval(i->d.s);
+}
+
+
+void ahtable_iter_begin(ahtable_t* T, ahtable_iter_t* i, bool sorted) {
+ memset(i, 0, sizeof(ahtable_iter_t));
+ i->T = T;
+ if (sorted) {
+ i->flags |= AH_SORTED;
+ ahtable_sorted_iter_begin(T, i);
+ } else {
+ ahtable_unsorted_iter_begin(T, i);
+ }
+}
+
+
+void ahtable_iter_next(ahtable_iter_t* i)
+{
+ if (i->flags & AH_SORTED) ahtable_sorted_iter_next(i);
+ else ahtable_unsorted_iter_next(i);
+}
+
+void ahtable_iter_del(ahtable_iter_t* i)
+{
+ if (i->flags & AH_SORTED) ahtable_sorted_iter_del(i);
+ else ahtable_unsorted_iter_del(i);
+}
+
+
+bool ahtable_iter_finished(ahtable_iter_t* i)
+{
+ if (i->flags & AH_SORTED) return ahtable_sorted_iter_finished(i);
+ else return ahtable_unsorted_iter_finished(i);
+}
+
+void ahtable_iter_free(ahtable_iter_t* i)
+{
+ if (i == NULL) return;
+ if (i->flags & AH_SORTED) ahtable_sorted_iter_free(i);
+}
+
+
+const char* ahtable_iter_key(ahtable_iter_t* i, size_t* len)
+{
+ if (i->flags & AH_SORTED) return ahtable_sorted_iter_key(i, len);
+ else return ahtable_unsorted_iter_key(i, len);
+}
+
+
+value_t* ahtable_iter_val(ahtable_iter_t* i)
+{
+ if (i->flags & AH_SORTED) return ahtable_sorted_iter_val(i);
+ else return ahtable_unsorted_iter_val(i);
+}
diff --git a/src/common/hattrie/ahtable.h b/src/common/hattrie/ahtable.h
new file mode 100644
index 0000000..6ab25e9
--- /dev/null
+++ b/src/common/hattrie/ahtable.h
@@ -0,0 +1,120 @@
+/*
+ * This file is part of hat-trie.
+ *
+ * Copyright (c) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
+ *
+ *
+ * This is an implementation of the 'cache-conscious' hash tables described in,
+ *
+ * Askitis, N., & Zobel, J. (2005). Cache-conscious collision resolution in
+ * string hash tables. String Processing and Information Retrieval (pp.
+ * 91–102). Springer.
+ *
+ * Briefly, the idea is, as opposed to separate chaining with linked lists, to
+ * store keys contiguously in one big array, thereby improving the caching
+ * behavior, and reducing space requirments.
+ *
+ */
+
+#ifndef HATTRIE_AHTABLE_H
+#define HATTRIE_AHTABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "common.h"
+#include "hat-trie.h"
+
+typedef unsigned char* slot_t;
+
+typedef struct ahtable_t_
+{
+ /* these fields are reserved for hattrie to fiddle with */
+ uint8_t flag;
+ unsigned char c0;
+ unsigned char c1;
+
+ size_t n; // number of slots
+ size_t m; // number of key/value pairs stored
+ size_t max_m; // number of stored keys before we resize
+
+ uint32_t* slot_sizes;
+ slot_t* slots;
+ slot_t* index; // order index (optional)
+} ahtable_t;
+
+ahtable_t* ahtable_create (void); // Create an empty hash table.
+ahtable_t* ahtable_create_n (size_t n); // Create an empty hash table, with
+ // n slots reserved.
+
+void ahtable_free (ahtable_t*); // Free all memory used by a table.
+void ahtable_clear (ahtable_t*); // Remove all entries.
+size_t ahtable_size (const ahtable_t*); // Number of stored keys.
+
+
+/** Find the given key in the table, inserting it if it does not exist, and
+ * returning a pointer to its key.
+ *
+ * This pointer is not guaranteed to be valid after additional calls to
+ * ahtable_get, ahtable_del, ahtable_clear, or other functions that modifies the
+ * table.
+ */
+value_t* ahtable_get (ahtable_t*, const char* key, size_t len);
+
+/** Find a given key in the table, returning a NULL pointer if it does not
+ * exist. */
+value_t* ahtable_tryget (ahtable_t*, const char* key, size_t len);
+
+/** Return value from index.
+ */
+value_t *ahtable_indexval(ahtable_t*, unsigned i);
+
+/** Build order index for fast ordered lookup.
+ */
+void ahtable_build_index(ahtable_t*);
+
+/** Find a key that is exact match or lexicographic predecessor.
+ * \retval 0 if exact match
+ * \retval 1 if couldn't find and no predecessor is found
+ * \retval -1 if found predecessor
+ */
+int ahtable_find_leq (ahtable_t*, const char* key, size_t len, value_t** dst);
+
+
+/** Insert given key and value without checking for existence.
+ */
+void ahtable_insert (ahtable_t* T, const char* key, size_t len, value_t val);
+
+
+int ahtable_del(ahtable_t*, const char* key, size_t len);
+
+typedef struct ahtable_iter_t_
+{
+ unsigned flags;
+ ahtable_t* T; // parent
+ uint32_t i; // current key
+ union {
+ slot_t* xs; // pointers to keys
+ slot_t s; // slot position
+ } d;
+
+} ahtable_iter_t;
+
+void ahtable_iter_begin (ahtable_t*, ahtable_iter_t*, bool sorted);
+void ahtable_iter_next (ahtable_iter_t*);
+void ahtable_iter_del (ahtable_iter_t*);
+bool ahtable_iter_finished (ahtable_iter_t*);
+void ahtable_iter_free (ahtable_iter_t*);
+const char* ahtable_iter_key (ahtable_iter_t*, size_t* len);
+value_t* ahtable_iter_val (ahtable_iter_t*);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/common/hattrie/hat-trie.c b/src/common/hattrie/hat-trie.c
new file mode 100644
index 0000000..419481f
--- /dev/null
+++ b/src/common/hattrie/hat-trie.c
@@ -0,0 +1,1070 @@
+/*
+ * This file is part of hat-trie.
+ *
+ * Copyright (c) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
+ *
+ */
+
+#include <config.h>
+#include <stdint.h>
+#include <assert.h>
+#include <string.h>
+#include "hat-trie.h"
+#include "ahtable.h"
+
+/* number of child nodes for used alphabet */
+#define NODE_CHILDS (TRIE_MAXCHAR+1)
+/* initial nodestack size */
+#define NODESTACK_INIT 512
+
+static const uint8_t NODE_TYPE_TRIE = 0x1;
+static const uint8_t NODE_TYPE_PURE_BUCKET = 0x2;
+static const uint8_t NODE_TYPE_HYBRID_BUCKET = 0x4;
+static const uint8_t NODE_HAS_VAL = 0x8;
+
+
+struct trie_node_t_;
+
+/* Node's may be trie nodes or buckets. This union allows us to keep
+ * non-specific pointer. */
+typedef union node_ptr_
+{
+ ahtable_t* b;
+ struct trie_node_t_* t;
+ uint8_t* flag;
+} node_ptr;
+
+
+typedef struct trie_node_t_
+{
+ uint8_t flag;
+
+ /* the value for the key that is consumed on a trie node */
+ value_t val;
+
+ /* Map a character to either a trie_node_t or a ahtable_t. The first byte
+ * must be examined to determine which. */
+ node_ptr xs[NODE_CHILDS];
+
+} trie_node_t;
+
+struct hattrie_t_
+{
+ node_ptr root; // root node
+ size_t m; // number of stored keys
+ unsigned bsize; // bucket size
+ mm_ctx_t mm;
+};
+
+/* Create an empty trie node. */
+static trie_node_t* alloc_empty_node(hattrie_t* T)
+{
+ trie_node_t* node = T->mm.alloc(T->mm.ctx, sizeof(trie_node_t));
+ node->flag = NODE_TYPE_TRIE;
+ node->val = 0;
+
+ memset(node->xs, 0, sizeof(node_ptr) * NODE_CHILDS);
+ return node;
+}
+
+/* Create a new trie node with all pointer pointing to the given child (which
+ * can be NULL). */
+static trie_node_t* alloc_trie_node(hattrie_t* T, node_ptr child)
+{
+ trie_node_t* node = T->mm.alloc(T->mm.ctx, sizeof(trie_node_t));
+ node->flag = NODE_TYPE_TRIE;
+ node->val = 0;
+
+ size_t i;
+ for (i = 0; i < NODE_CHILDS; ++i) node->xs[i] = child;
+ return node;
+}
+
+/* iterate trie nodes until string is consumed or bucket is found */
+static node_ptr hattrie_consume_ns(node_ptr **s, size_t *sp, size_t slen,
+ const char **k, size_t *l, unsigned brk)
+{
+
+ node_ptr *bs = *s;
+ node_ptr node = bs[*sp].t->xs[(unsigned char) **k];
+ while (node.flag && *node.flag & NODE_TYPE_TRIE && *l > brk) {
+ ++*k;
+ --*l;
+ /* build node stack if slen > 0 */
+ if (slen > 0) {
+ if (*sp == slen - 1) {
+ /* switch pointers if allocating from base
+ * this is a bit ugly, but needed to avoid memory allocation
+ * most of the time
+ */
+ slen *= 2;
+ if (bs == *s) { /* points to original stack mem */
+ bs = malloc(slen * sizeof(node_ptr));
+ memcpy(bs, *s, (slen/2) * sizeof(node_ptr));
+ } else { /* points to heap memory already */
+ bs = realloc(bs, slen * sizeof(node_ptr));
+ }
+ /* update parent pointer on resize */
+ *s = bs;
+ }
+ /* increment stack pointer */
+ ++*sp;
+ }
+ bs[*sp] = node;
+ node = node.t->xs[(unsigned char) **k];
+ }
+
+ /* stack top is always parent node */
+ assert(*bs[*sp].flag & NODE_TYPE_TRIE);
+ return node;
+}
+
+static inline node_ptr hattrie_consume(node_ptr *parent, const char **k,
+ size_t *l, unsigned brk)
+{
+ size_t sp = 0;
+ return hattrie_consume_ns(&parent, &sp, 0, k, l, brk);
+}
+
+/* use node value and return pointer to it */
+static inline value_t* hattrie_useval(hattrie_t *T, node_ptr n)
+{
+ if (!(n.t->flag & NODE_HAS_VAL)) {
+ n.t->flag |= NODE_HAS_VAL;
+ ++T->m;
+ }
+ return &n.t->val;
+}
+
+/* clear node value if exists */
+static inline int hattrie_clrval(hattrie_t *T, node_ptr n)
+{
+ if (n.t->flag & NODE_HAS_VAL) {
+ n.t->flag &= ~NODE_HAS_VAL;
+ n.t->val = 0;
+ --T->m;
+ return 0;
+ }
+ return -1;
+}
+
+/* find rightmost non-empty node */
+static value_t* hattrie_find_rightmost(node_ptr node)
+{
+ /* iterate children from right */
+ value_t *ret = NULL;
+ if (*node.flag & NODE_TYPE_TRIE) {
+ for (int i = TRIE_MAXCHAR; i > -1; --i) {
+ /* skip repeated pointers to hybrid bucket */
+ if (i < TRIE_MAXCHAR && node.t->xs[i].t == node.t->xs[i + 1].t)
+ continue;
+ /* nest if trie */
+ ret = hattrie_find_rightmost(node.t->xs[i]);
+ if (ret) {
+ return ret;
+ }
+ }
+ /* use trie node value if no children found */
+ if (node.t->flag & NODE_HAS_VAL) {
+ return &node.t->val;
+ }
+
+ /* no non-empty children? */
+ return NULL;
+ }
+
+ /* node is ahtable */
+ if (node.b->m == 0) {
+ return NULL;
+ }
+ /* return rightmost value */
+ assert(node.b->index);
+ return ahtable_indexval(node.b, node.b->m - 1);
+}
+
+/* find node in trie and keep node stack (if slen > 0) */
+static node_ptr hattrie_find_ns(node_ptr **s, size_t *sp, size_t slen,
+ const char **key, size_t *len)
+{
+ assert(*(*s)[*sp].flag & NODE_TYPE_TRIE);
+
+ if (*len == 0) return (*s)[*sp]; /* parent, as sp == 0 */
+
+ node_ptr node = hattrie_consume_ns(s, sp, slen, key, len, 1);
+
+ /* using pure trie and couldn't find the key, return stack top */
+ if (node.flag == NULL) {
+ node = (*s)[*sp];
+ }
+
+ /* if the trie node consumes value, use it */
+ if (*node.flag & NODE_TYPE_TRIE) {
+ if (!(node.t->flag & NODE_HAS_VAL)) {
+ node.flag = NULL;
+ }
+ return node;
+ }
+
+ /* pure bucket holds only key suffixes, skip current char */
+ if (*node.flag & NODE_TYPE_PURE_BUCKET) {
+ ++*key;
+ --*len;
+ }
+
+ /* do not scan bucket, it's not needed for this operation */
+ return node;
+}
+
+/* find node in trie */
+static inline node_ptr hattrie_find(node_ptr *parent, const char **key, size_t *len)
+{
+ size_t sp = 0;
+ return hattrie_find_ns(&parent, &sp, 0, key, len);
+}
+
+static inline value_t hattrie_setval(value_t v) {
+ return v;
+}
+
+/* initialize root node */
+static void hattrie_initroot(hattrie_t *T)
+{
+ node_ptr node;
+ if (T->bsize > 0) {
+ node.b = ahtable_create();
+ node.b->flag = NODE_TYPE_HYBRID_BUCKET;
+ node.b->c0 = 0x00;
+ node.b->c1 = TRIE_MAXCHAR;
+ T->root.t = alloc_trie_node(T, node);
+ } else {
+ T->root.t = alloc_empty_node(T);
+ }
+}
+
+/* Free hat-trie nodes recursively. */
+static void hattrie_free_node(node_ptr node, mm_free_t free_cb)
+{
+ if (*node.flag & NODE_TYPE_TRIE) {
+ size_t i;
+ for (i = 0; i < NODE_CHILDS; ++i) {
+ if (i > 0 && node.t->xs[i].t == node.t->xs[i - 1].t)
+ continue;
+
+ /* XXX: recursion might not be the best choice here. It is possible
+ * to build a very deep trie. */
+ if (node.t->xs[i].t)
+ hattrie_free_node(node.t->xs[i], free_cb);
+ }
+ if (free_cb)
+ free_cb(node.t);
+ }
+ else {
+ ahtable_free(node.b);
+ }
+}
+
+/* Initialize hat-trie. */
+static void hattrie_init(hattrie_t * T, unsigned bucket_size)
+{
+ T->m = 0;
+ T->bsize = bucket_size;
+ hattrie_initroot(T);
+}
+
+/* Deinitialize hat-trie. */
+static void hattrie_deinit(hattrie_t * T)
+{
+ if (T->bsize > 0 || T->mm.free)
+ hattrie_free_node(T->root, T->mm.free);
+}
+
+hattrie_t* hattrie_create()
+{
+ mm_ctx_t mm;
+ mm_ctx_init(&mm);
+ return hattrie_create_n(TRIE_BUCKET_SIZE, &mm);
+}
+
+void hattrie_free(hattrie_t* T)
+{
+ if (T == NULL) {
+ return;
+ }
+ hattrie_deinit(T);
+ if (T->mm.free)
+ T->mm.free(T);
+}
+
+void hattrie_clear(hattrie_t* T)
+{
+ if (T == NULL) {
+ return;
+ }
+
+ hattrie_deinit(T);
+ hattrie_init(T, T->bsize);
+}
+
+hattrie_t* hattrie_dup(const hattrie_t* T, value_t (*nval)(value_t))
+{
+ hattrie_t *N = hattrie_create_n(T->bsize, &T->mm);
+
+ /* assignment */
+ if (!nval) nval = hattrie_setval;
+
+ /*! \todo could be probably implemented faster */
+
+ size_t l = 0;
+ const char *k = 0;
+ hattrie_iter_t *i = hattrie_iter_begin(T, false);
+ while (!hattrie_iter_finished(i)) {
+ k = hattrie_iter_key(i, &l);
+ *hattrie_get(N, k, l) = nval(*hattrie_iter_val(i));
+ hattrie_iter_next(i);
+ }
+ hattrie_iter_free(i);
+ return N;
+}
+
+size_t hattrie_weight (hattrie_t* T)
+{
+ return T->m;
+}
+
+hattrie_t* hattrie_create_n(unsigned bucket_size, const mm_ctx_t *mm)
+{
+ hattrie_t* T = mm->alloc(mm->ctx, sizeof(hattrie_t));
+ memcpy(&T->mm, mm, sizeof(mm_ctx_t));
+ hattrie_init(T, bucket_size);
+ return T;
+}
+
+static void node_build_index(node_ptr node)
+{
+ /* build index on all ahtable nodes */
+ if (*node.flag & NODE_TYPE_TRIE) {
+ size_t i;
+ for (i = 0; i < NODE_CHILDS; ++i) {
+ if (i > 0 && node.t->xs[i].t == node.t->xs[i - 1].t) continue;
+ if (node.t->xs[i].t) node_build_index(node.t->xs[i]);
+ }
+ }
+ else {
+ ahtable_build_index(node.b);
+ }
+}
+
+void hattrie_build_index(hattrie_t *T)
+{
+ node_build_index(T->root);
+}
+
+static void node_apply(node_ptr node, void (*f)(value_t*,void*), void* d)
+{
+ if (*node.flag & NODE_TYPE_TRIE) {
+ size_t i;
+ for (i = 0; i < NODE_CHILDS; ++i) {
+ if (i > 0 && node.t->xs[i].t == node.t->xs[i - 1].t) continue;
+ if (node.t->xs[i].t) node_apply(node.t->xs[i], f, d);
+ if (*node.flag & NODE_HAS_VAL) {
+ f(&node.t->val, d);
+ }
+ }
+ }
+ else {
+ ahtable_iter_t i;
+ ahtable_iter_begin(node.b, &i, false);
+ while (!ahtable_iter_finished(&i)) {
+ f(ahtable_iter_val(&i), d);
+ ahtable_iter_next(&i);
+ }
+ ahtable_iter_free(&i);
+ }
+}
+
+static void node_apply_ahtable(node_ptr node, void (*f)(void*,void*), void* d)
+{
+ if (*node.flag & NODE_TYPE_TRIE) {
+ size_t i;
+ for (i = 0; i < NODE_CHILDS; ++i) {
+ if (i > 0 && node.t->xs[i].t == node.t->xs[i - 1].t) continue;
+ if (node.t->xs[i].t) node_apply_ahtable(node.t->xs[i], f, d);
+ }
+ }
+ else {
+ f(node.b, d);
+ }
+}
+
+void hattrie_apply_rev(hattrie_t* T, void (*f)(value_t*,void*), void* d)
+{
+ node_apply(T->root, f, d);
+}
+
+void hattrie_apply_rev_ahtable(hattrie_t* T, void (*f)(void*,void*), void* d)
+{
+ node_apply_ahtable(T->root, f, d);
+}
+
+int hattrie_split_mid(node_ptr node, unsigned *left_m, unsigned *right_m)
+{
+ /* count the number of occourances of every leading character */
+ unsigned int cs[NODE_CHILDS]; // occurance count for leading chars
+ memset(cs, 0, NODE_CHILDS * sizeof(unsigned int));
+ size_t len;
+ const char* key;
+
+ /*! \todo expensive, maybe some heuristics or precalc would be better */
+ ahtable_iter_t i;
+ ahtable_iter_begin(node.b, &i, false);
+ while (!ahtable_iter_finished(&i)) {
+ key = ahtable_iter_key(&i, &len);
+ assert(len > 0);
+ cs[(unsigned char) key[0]] += 1;
+ ahtable_iter_next(&i);
+ }
+ ahtable_iter_free(&i);
+
+ /* choose a split point */
+ unsigned int all_m;
+ unsigned char j = node.b->c0;
+ all_m = ahtable_size(node.b);
+ *left_m = cs[j];
+ *right_m = all_m - *left_m;
+ int d;
+
+ while (j + 1 < node.b->c1) {
+ d = abs((int) (*left_m + cs[j + 1]) - (int) (*right_m - cs[j + 1]));
+ if (d <= abs(*left_m - *right_m) && *left_m + cs[j + 1] < all_m) {
+ j += 1;
+ *left_m += cs[j];
+ *right_m -= cs[j];
+ }
+ else break;
+ }
+
+ return j;
+}
+
+static void hattrie_split_fill(node_ptr src, node_ptr left, node_ptr right, uint8_t split)
+{
+ /* right should be most of the time hybrid */
+
+ /* keep or distribute keys to the new right node */
+ value_t* u;
+ const char* key;
+ size_t len;
+ ahtable_iter_t i;
+ ahtable_iter_begin(src.b, &i, false);
+ while (!ahtable_iter_finished(&i)) {
+ key = ahtable_iter_key(&i, &len);
+ u = ahtable_iter_val(&i);
+ assert(len > 0);
+
+ /* first char > split_point, move to the right */
+ if ((unsigned char) key[0] > split) {
+ if (src.b != right.b) {
+ /* insert to right (new bucket) */
+ if (*right.flag & NODE_TYPE_PURE_BUCKET) {
+ ahtable_insert(right.b, key + 1, len - 1, *u);
+ }
+ else {
+ ahtable_insert(right.b, key, len, *u);
+ }
+ /* transferred to right (from reused) */
+ if (src.b == left.b) {
+ ahtable_iter_del(&i);
+ continue;
+ }
+ } /* keep the node in right */
+ } else {
+ if (src.b != left.b) {
+ /* insert to left (new bucket) */
+ if (*left.flag & NODE_TYPE_PURE_BUCKET) {
+ ahtable_insert(left.b, key + 1, len - 1, *u);
+ }
+ else {
+ ahtable_insert(left.b, key, len, *u);
+ }
+ /* transferred to left (from reused) */
+ if (src.b == right.b) {
+ ahtable_iter_del(&i);
+ continue;
+ }
+ } /* keep the node in left */
+ }
+
+ ahtable_iter_next(&i);
+ }
+
+ ahtable_iter_free(&i);
+}
+
+/* Split hybrid node - this is similar operation to burst. */
+static void hattrie_split_h(node_ptr parent, node_ptr node)
+{
+ /* Find split point. */
+ unsigned left_m, right_m;
+ unsigned char j = hattrie_split_mid(node, &left_m, &right_m);
+
+ /* now split into two node cooresponding to ranges [0, j] and
+ * [j + 1, TRIE_MAXCHAR], respectively. */
+
+ /* create new left and right nodes
+ * one node may reuse existing if it keeps hybrid flag
+ * hybrid -> pure always needs a new table
+ */
+ unsigned char c0 = node.b->c0, c1 = node.b->c1;
+ node_ptr left, right;
+ if (j + 1 == c1) { /* right will be pure */
+ right.b = ahtable_create();
+ if (j == c0) { /* left will be pure as well */
+ left.b = ahtable_create();
+ } else { /* left will be hybrid */
+ left.b = node.b;
+ }
+ } else { /* right will be hybrid */
+ right.b = node.b;
+ left.b = ahtable_create();
+ }
+
+ /* setup created nodes */
+ left.b->c0 = c0;
+ left.b->c1 = j;
+ left.b->flag = c0 == j ? NODE_TYPE_PURE_BUCKET : NODE_TYPE_HYBRID_BUCKET; // need to force it
+ right.b->c0 = j + 1;
+ right.b->c1 = c1;
+ right.b->flag = right.b->c0 == right.b->c1 ?
+ NODE_TYPE_PURE_BUCKET : NODE_TYPE_HYBRID_BUCKET;
+
+
+ /* update the parent's pointer */
+ unsigned int c;
+ for (c = c0; c <= j; ++c) parent.t->xs[c] = left;
+ for (; c <= c1; ++c) parent.t->xs[c] = right;
+
+
+ /* fill new tables */
+ hattrie_split_fill(node, left, right, j);
+ if (node.b != left.b && node.b != right.b) {
+ ahtable_free(node.b);
+ }
+}
+
+/* Perform one split operation on the given node with the given parent.
+ */
+static void hattrie_split(hattrie_t* T, node_ptr parent, node_ptr node)
+{
+ /* only buckets may be split */
+ assert(*node.flag & NODE_TYPE_PURE_BUCKET ||
+ *node.flag & NODE_TYPE_HYBRID_BUCKET);
+
+ assert(*parent.flag & NODE_TYPE_TRIE);
+
+ if (*node.flag & NODE_TYPE_PURE_BUCKET) {
+ /* turn the pure bucket into a hybrid bucket */
+ parent.t->xs[node.b->c0].t = alloc_trie_node(T, node);
+
+ /* if the bucket had an empty key, move it to the new trie node */
+ value_t* val = ahtable_tryget(node.b, NULL, 0);
+ if (val) {
+ parent.t->xs[node.b->c0].t->val = *val;
+ parent.t->xs[node.b->c0].t->flag |= NODE_HAS_VAL;
+ *val = 0;
+ ahtable_del(node.b, NULL, 0);
+ }
+
+ node.b->c0 = 0x00;
+ node.b->c1 = TRIE_MAXCHAR;
+ node.b->flag = NODE_TYPE_HYBRID_BUCKET;
+
+ return;
+ }
+
+ /* This is a hybrid bucket. Perform a proper split. */
+ hattrie_split_h(parent, node);
+}
+
+value_t* hattrie_get(hattrie_t* T, const char* key, size_t len)
+{
+ node_ptr parent = T->root;
+ assert(*parent.flag & NODE_TYPE_TRIE);
+
+ if (len == 0) return &parent.t->val;
+
+ /* consume all trie nodes, now parent must be trie and child anything */
+ node_ptr node = hattrie_consume(&parent, &key, &len, 0);
+ assert(*parent.flag & NODE_TYPE_TRIE);
+
+ /* key wasn't consumed and using pure tries */
+ if (T->bsize == 0) {
+ node.t = parent.t;
+ while (len > 0) {
+ node.t->xs[(unsigned char) *key].t = alloc_empty_node(T);
+ node = node.t->xs[(unsigned char) *key];
+ ++key;
+ --len;
+ }
+
+ return hattrie_useval(T, node);
+ }
+
+ /* if the key has been consumed on a trie node, use its value */
+ if (len == 0) {
+ if (*node.flag & NODE_TYPE_TRIE) {
+ return hattrie_useval(T, node);
+ }
+ else if (*node.flag & NODE_TYPE_HYBRID_BUCKET) {
+ return hattrie_useval(T, parent);
+ }
+ }
+
+ /* preemptively split the bucket if it is full */
+ while (ahtable_size(node.b) >= T->bsize) {
+ hattrie_split(T, parent, node);
+
+ /* after the split, the node pointer is invalidated, so we search from
+ * the parent again. */
+ node = hattrie_consume(&parent, &key, &len, 0);
+
+ /* if the key has been consumed on a trie node, use its value */
+ if (len == 0) {
+ if (*node.flag & NODE_TYPE_TRIE) {
+ return hattrie_useval(T, node);
+ }
+ else if (*node.flag & NODE_TYPE_HYBRID_BUCKET) {
+ return hattrie_useval(T, parent);
+ }
+ }
+ }
+
+ assert(*node.flag & NODE_TYPE_PURE_BUCKET || *node.flag & NODE_TYPE_HYBRID_BUCKET);
+
+ assert(len > 0);
+ size_t m_old = node.b->m;
+ value_t* val;
+ if (*node.flag & NODE_TYPE_PURE_BUCKET) {
+ val = ahtable_get(node.b, key + 1, len - 1);
+ }
+ else {
+ val = ahtable_get(node.b, key, len);
+ }
+ T->m += (node.b->m - m_old);
+
+ return val;
+}
+
+
+value_t* hattrie_tryget(hattrie_t* T, const char* key, size_t len)
+{
+ /* find node for given key */
+ node_ptr parent = T->root;
+ node_ptr node = hattrie_find(&parent, &key, &len);
+ if (node.flag == NULL) {
+ return NULL;
+ }
+
+ /* if the trie node consumes value, use it */
+ if (*node.flag & NODE_TYPE_TRIE) {
+ return &node.t->val;
+ }
+
+ return ahtable_tryget(node.b, key, len);
+}
+
+static value_t* hattrie_walk(node_ptr* s, size_t sp,
+ const char* key, value_t* (*f)(node_ptr))
+{
+ value_t *r = NULL;
+ while (r == NULL) {
+ /* if not found prev in table, it should be
+ * the rightmost of the nodes left of the current
+ */
+ node_ptr visited = s[sp].t->xs[(unsigned char)*key];
+ for (int i = *key - 1; i > -1; --i) {
+ if (s[sp].t->xs[i].flag == visited.flag)
+ continue; /* skip pointers to visited container */
+ r = f(s[sp].t->xs[i]);
+ if (r) {
+ return r;
+ }
+ }
+
+ /* use trie node value if possible */
+ if (s[sp].t->flag & NODE_HAS_VAL) {
+ return &s[sp].t->val;
+ }
+
+ /* consumed whole stack */
+ if (sp == 0) {
+ break;
+ }
+
+ /* pop stack */
+ --key;
+ --sp;
+ }
+
+ return NULL;
+}
+
+int hattrie_find_leq (hattrie_t* T, const char* key, size_t len, value_t** dst)
+{
+ /* create node stack for traceback */
+ size_t sp = 0;
+ node_ptr bs[NODESTACK_INIT]; /* base stack (will be enough mostly) */
+ node_ptr *ns = bs; /* generic ptr, could point to new mem */
+ ns[sp] = T->root;
+
+ /* find node for given key */
+ int ret = 1; /* no node on the left matches */
+ node_ptr node = hattrie_find_ns(&ns, &sp, NODESTACK_INIT, &key, &len);
+ if (node.flag == NULL) {
+ *dst = hattrie_walk(ns, sp, key, hattrie_find_rightmost);
+ if (ns != bs) free(ns);
+ if (*dst) {
+ return -1; /* found previous */
+ }
+ return 1; /* no previous key found */
+ }
+
+ /* assign value from trie or find in table */
+ if (*node.flag & NODE_TYPE_TRIE) {
+ *dst = &node.t->val;
+ ret = 0; /* found exact match */
+ } else {
+ *dst = ahtable_tryget(node.b, key, len);
+ if (*dst) {
+ ret = 0; /* found exact match */
+ } else { /* look for previous in ahtable */
+ ret = ahtable_find_leq(node.b, key, len, dst);
+ }
+ }
+
+ /* return if found equal or left in ahtable */
+ if (*dst == 0) {
+ *dst = hattrie_walk(ns, sp, key, hattrie_find_rightmost);
+ if (*dst) {
+ ret = -1; /* found previous */
+ } else {
+ ret = 1; /* no previous key found */
+ }
+ }
+
+ if (ns != bs) free(ns);
+ return ret;
+}
+
+int hattrie_find_lpr (hattrie_t* T, const char* key, size_t len, value_t** dst)
+{
+ /* create node stack for traceback */
+ int ret = -1;
+ size_t sp = 0;
+ node_ptr bs[NODESTACK_INIT]; /* base stack (will be enough mostly) */
+ node_ptr *ns = bs; /* generic ptr, could point to new mem */
+ ns[sp] = T->root;
+ *dst = NULL;
+
+ /* consume trie nodes for key (thus building prefix chain) */
+ node_ptr node = hattrie_find_ns(&ns, &sp, NODESTACK_INIT, &key, &len);
+ if (node.flag == NULL) {
+ if (sp == 0) { /* empty trie, no prefix match */
+ if (ns != bs) free(ns);
+ return -1;
+ }
+ node = ns[--sp]; /* dead end, pop node */
+ }
+
+ /* search for suffix in current node */
+ size_t suffix = len; /* suffix length */
+ if (*node.flag & NODE_TYPE_TRIE) {
+ *dst = &node.t->val; /* use current trie node value */
+ } else {
+ while (*dst == NULL) { /* find remainder in current ahtable */
+ *dst = ahtable_tryget(node.b, key, suffix);
+ if (suffix == 0)
+ break;
+ --suffix;
+ }
+ }
+
+ /* not in current node, need to traceback node stack */
+ while (*dst == NULL) {
+ node = ns[sp]; /* parent node, always a trie node type */
+ if (*node.flag & NODE_HAS_VAL)
+ *dst = &node.t->val;
+ if (sp == 0)
+ break;
+ --sp;
+ }
+
+ if (*dst) { /* prefix found? */
+ ret = 0;
+ }
+
+ if (ns != bs) free(ns);
+ return ret;
+}
+
+
+int hattrie_del(hattrie_t* T, const char* key, size_t len)
+{
+ node_ptr parent = T->root;
+ assert(*parent.flag & NODE_TYPE_TRIE);
+
+ /* find node for deletion */
+ node_ptr node = hattrie_find(&parent, &key, &len);
+ if (node.flag == NULL) {
+ return -1;
+ }
+
+ /* if consumed on a trie node, clear the value */
+ if (*node.flag & NODE_TYPE_TRIE) {
+ return hattrie_clrval(T, node);
+ }
+
+ /* remove from bucket */
+ size_t m_old = ahtable_size(node.b);
+ int ret = ahtable_del(node.b, key, len);
+ T->m -= (m_old - ahtable_size(node.b));
+
+ /* merge empty buckets */
+ /*! \todo */
+
+ return ret;
+}
+
+
+/* plan for iteration:
+ * This is tricky, as we have no parent pointers currently, and I would like to
+ * avoid adding them. That means maintaining a stack
+ *
+ */
+
+typedef struct hattrie_node_stack_t_
+{
+ unsigned char c;
+ size_t level;
+
+ node_ptr node;
+ struct hattrie_node_stack_t_* next;
+
+} hattrie_node_stack_t;
+
+
+struct hattrie_iter_t_
+{
+ char* key;
+ size_t keysize; // space reserved for the key
+ size_t level;
+
+ /* keep track of keys stored in trie nodes */
+ bool has_nil_key;
+ value_t nil_val;
+
+ const hattrie_t* T;
+ bool sorted;
+ ahtable_iter_t* i;
+ hattrie_node_stack_t* stack;
+};
+
+
+static void hattrie_iter_pushchar(hattrie_iter_t* i, size_t level, char c)
+{
+ if (i->keysize < level) {
+ i->keysize *= 2;
+ i->key = realloc(i->key, i->keysize * sizeof(char));
+ }
+
+ if (level > 0) {
+ i->key[level - 1] = c;
+ }
+
+ i->level = level;
+}
+
+
+static void hattrie_iter_nextnode(hattrie_iter_t* i)
+{
+ if (i->stack == NULL) return;
+
+ /* pop the stack */
+ node_ptr node;
+ hattrie_node_stack_t* next;
+ unsigned char c;
+ size_t level;
+
+ node = i->stack->node;
+ next = i->stack->next;
+ c = i->stack->c;
+ level = i->stack->level;
+
+ free(i->stack);
+ i->stack = next;
+
+ if (*node.flag & NODE_TYPE_TRIE) {
+ hattrie_iter_pushchar(i, level, c);
+
+ if(node.t->flag & NODE_HAS_VAL) {
+ i->has_nil_key = true;
+ i->nil_val = node.t->val;
+ }
+
+ /* push all child nodes from right to left */
+ int j;
+ for (j = TRIE_MAXCHAR; j >= 0; --j) {
+
+ /* skip repeated pointers to hybrid bucket */
+ if (j < TRIE_MAXCHAR && node.t->xs[j].t == node.t->xs[j + 1].t) continue;
+
+ // push stack
+ next = i->stack;
+ i->stack = malloc(sizeof(hattrie_node_stack_t));
+ i->stack->node = node.t->xs[j];
+ i->stack->next = next;
+ i->stack->level = level + 1;
+ i->stack->c = (unsigned char) j;
+ }
+ }
+ else {
+ if (*node.flag & NODE_TYPE_PURE_BUCKET) {
+ hattrie_iter_pushchar(i, level, c);
+ }
+ else {
+ i->level = level - 1;
+ }
+
+ i->i = malloc(sizeof(ahtable_iter_t));
+ ahtable_iter_begin(node.b, i->i, i->sorted);
+ }
+}
+
+
+hattrie_iter_t* hattrie_iter_begin(const hattrie_t* T, bool sorted)
+{
+ hattrie_iter_t* i = malloc(sizeof(hattrie_iter_t));
+ i->T = T;
+ i->sorted = sorted;
+ i->i = NULL;
+ i->keysize = 16;
+ i->key = malloc(i->keysize * sizeof(char));
+ i->level = 0;
+ i->has_nil_key = false;
+ i->nil_val = 0;
+
+ i->stack = malloc(sizeof(hattrie_node_stack_t));
+ i->stack->next = NULL;
+ i->stack->node = T->root;
+ i->stack->c = '\0';
+ i->stack->level = 0;
+
+
+ while (((i->i == NULL || ahtable_iter_finished(i->i)) && !i->has_nil_key) &&
+ i->stack != NULL ) {
+
+ ahtable_iter_free(i->i);
+ free(i->i);
+ i->i = NULL;
+ hattrie_iter_nextnode(i);
+ }
+
+ if (i->i != NULL && ahtable_iter_finished(i->i)) {
+ ahtable_iter_free(i->i);
+ free(i->i);
+ i->i = NULL;
+ }
+
+ return i;
+}
+
+
+void hattrie_iter_next(hattrie_iter_t* i)
+{
+ if (hattrie_iter_finished(i)) return;
+
+ if (i->i != NULL && !ahtable_iter_finished(i->i)) {
+ ahtable_iter_next(i->i);
+ }
+ else if (i->has_nil_key) {
+ i->has_nil_key = false;
+ i->nil_val = 0;
+ hattrie_iter_nextnode(i);
+ }
+
+ while (((i->i == NULL || ahtable_iter_finished(i->i)) && !i->has_nil_key) &&
+ i->stack != NULL ) {
+
+ ahtable_iter_free(i->i);
+ free(i->i);
+ i->i = NULL;
+ hattrie_iter_nextnode(i);
+ }
+
+ if (i->i != NULL && ahtable_iter_finished(i->i)) {
+ ahtable_iter_free(i->i);
+ free(i->i);
+ i->i = NULL;
+ }
+}
+
+
+bool hattrie_iter_finished(hattrie_iter_t* i)
+{
+ return i->stack == NULL && i->i == NULL && !i->has_nil_key;
+}
+
+
+void hattrie_iter_free(hattrie_iter_t* i)
+{
+ if (i == NULL) return;
+ if (i->i) {
+ ahtable_iter_free(i->i);
+ free(i->i);
+ }
+
+ hattrie_node_stack_t* next;
+ while (i->stack) {
+ next = i->stack->next;
+ free(i->stack);
+ i->stack = next;
+ }
+
+ free(i->key);
+ free(i);
+}
+
+
+const char* hattrie_iter_key(hattrie_iter_t* i, size_t* len)
+{
+ if (hattrie_iter_finished(i)) return NULL;
+
+ size_t sublen;
+ const char* subkey;
+
+ if (i->has_nil_key) {
+ subkey = NULL;
+ sublen = 0;
+ }
+ else subkey = ahtable_iter_key(i->i, &sublen);
+
+ if (i->keysize < i->level + sublen + 1) {
+ while (i->keysize < i->level + sublen + 1) i->keysize *= 2;
+ i->key = realloc(i->key, i->keysize * sizeof(char));
+ }
+
+ memcpy(i->key + i->level, subkey, sublen);
+ i->key[i->level + sublen] = '\0';
+
+ *len = i->level + sublen;
+ return i->key;
+}
+
+
+value_t* hattrie_iter_val(hattrie_iter_t* i)
+{
+ if (i->has_nil_key) return &i->nil_val;
+
+ if (hattrie_iter_finished(i)) return NULL;
+
+ return ahtable_iter_val(i->i);
+}
diff --git a/src/common/hattrie/hat-trie.h b/src/common/hattrie/hat-trie.h
new file mode 100644
index 0000000..6214575
--- /dev/null
+++ b/src/common/hattrie/hat-trie.h
@@ -0,0 +1,97 @@
+/*
+ * This file is part of hat-trie
+ *
+ * Copyright (c) 2011 by Daniel C. Jones <dcjones@cs.washington.edu>
+ *
+ *
+ * This is an implementation of the HAT-trie data structure described in,
+ *
+ * Askitis, N., & Sinha, R. (2007). HAT-trie: a cache-conscious trie-based data
+ * structure for strings. Proceedings of the thirtieth Australasian conference on
+ * Computer science-Volume 62 (pp. 97–105). Australian Computer Society, Inc.
+ *
+ * The HAT-trie is in essence a hybrid data structure, combining tries and hash
+ * tables in a clever way to try to get the best of both worlds.
+ *
+ */
+
+#ifndef HATTRIE_HATTRIE_H
+#define HATTRIE_HATTRIE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "common.h"
+#include "common/mempattern.h"
+
+/* Hat-trie defines. */
+typedef void* value_t; /* User pointers as value. */
+#define AHTABLE_INIT_SIZE 1024
+#define TRIE_ZEROBUCKETS 0 /* Do not use hash buckets (pure trie). */
+#define TRIE_BUCKET_SIZE 1536 /* Reasonably low for ordered search perf. */
+#define TRIE_MAXCHAR 0xff /* Use 7-bit ASCII alphabet. */
+
+typedef struct hattrie_t_ hattrie_t;
+
+hattrie_t* hattrie_create (void); //< Create an empty hat-trie.
+void hattrie_free (hattrie_t*); //< Free all memory used by a trie.
+void hattrie_clear (hattrie_t*); //< Remove all entries.
+size_t hattrie_weight (hattrie_t*); //< Number of entries
+
+/** Create new trie with custom bucket size and memory management.
+ */
+hattrie_t* hattrie_create_n (unsigned, const mm_ctx_t *);
+
+/** Duplicate an existing trie.
+ */
+hattrie_t* hattrie_dup (const hattrie_t*, value_t (*nval)(value_t));
+
+/** Build order index on all ahtable nodes in trie.
+ */
+void hattrie_build_index (hattrie_t*);
+
+void hattrie_apply_rev (hattrie_t*, void (*f)(value_t*,void*), void* d);
+void hattrie_apply_rev_ahtable(hattrie_t* T, void (*f)(void*,void*), void* d);
+
+/** Find the given key in the trie, inserting it if it does not exist, and
+ * returning a pointer to it's key.
+ *
+ * This pointer is not guaranteed to be valid after additional calls to
+ * hattrie_get, hattrie_del, hattrie_clear, or other functions that modifies the
+ * trie.
+ */
+value_t* hattrie_get (hattrie_t*, const char* key, size_t len);
+
+/** Find a given key in the table, returning a NULL pointer if it does not
+ * exist. */
+value_t* hattrie_tryget (hattrie_t*, const char* key, size_t len);
+
+/** Find a given key in the table, returning a NULL pointer if it does not
+ * exist. Also set prev to point to previous node. */
+int hattrie_find_leq (hattrie_t*, const char* key, size_t len, value_t** dst);
+
+/** Find a longest prefix match. */
+int hattrie_find_lpr (hattrie_t*, const char* key, size_t len, value_t** dst);
+
+
+/** Delete a given key from trie. Returns 0 if successful or -1 if not found.
+ */
+int hattrie_del(hattrie_t* T, const char* key, size_t len);
+
+typedef struct hattrie_iter_t_ hattrie_iter_t;
+
+hattrie_iter_t* hattrie_iter_begin (const hattrie_t*, bool sorted);
+void hattrie_iter_next (hattrie_iter_t*);
+bool hattrie_iter_finished (hattrie_iter_t*);
+void hattrie_iter_free (hattrie_iter_t*);
+const char* hattrie_iter_key (hattrie_iter_t*, size_t* len);
+value_t* hattrie_iter_val (hattrie_iter_t*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/common/hattrie/murmurhash3.c b/src/common/hattrie/murmurhash3.c
index cb24c8f..73de0ae 100644
--- a/src/common/hattrie/murmurhash3.c
+++ b/src/common/hattrie/murmurhash3.c
@@ -1,6 +1,7 @@
/* This is MurmurHash3. The original C++ code was placed in the public domain
* by its author, Austin Appleby. */
+#include <config.h>
#include "murmurhash3.h"
static inline uint32_t fmix(uint32_t h)
@@ -74,4 +75,3 @@ uint32_t hash(const char* data, size_t len_)
return h1;
}
-
diff --git a/src/common/hattrie/murmurhash3.h b/src/common/hattrie/murmurhash3.h
index ada7e47..d0e5812 100644
--- a/src/common/hattrie/murmurhash3.h
+++ b/src/common/hattrie/murmurhash3.h
@@ -8,4 +8,3 @@
uint32_t hash(const char* data, size_t len);
#endif
-
diff --git a/src/common/heap.c b/src/common/heap.c
index 27b82da..c8c7921 100644
--- a/src/common/heap.c
+++ b/src/common/heap.c
@@ -37,6 +37,7 @@
* ------
***/
+#include <config.h>
#include "heap.h"
#include <string.h>
#include <stdlib.h>
@@ -60,7 +61,7 @@ int heap_init(struct heap *h, int (*cmp)(void *, void *), int init_size)
h->data = malloc((isize + 1) * sizeof(heap_val_t)); /* Temp element unused. */
return h->data ? 1 : 0;
-};
+}
static inline void _heap_bubble_down(struct heap *h, int e)
{
@@ -86,7 +87,7 @@ static inline void _heap_bubble_up(struct heap *h, int e)
heap_swap(HELEMENT(h,e),HELEMENT(h,e1));
e = e1;
}
-
+
}
void heap_delmin(struct heap *h)
@@ -106,13 +107,15 @@ int heap_insert(struct heap *h, void *e)
{
h->max_size = h->max_size * HEAP_INCREASE_STEP;
h->data = realloc(h->data, (h->max_size + 1) * sizeof(heap_val_t));
+ if (!h->data) {
+ return 0;
+ }
}
h->num++;
*HELEMENT(h,h->num) = e;
_heap_bubble_up(h,h->num);
-
- return h->data ? 1 : 0;
+ return 1;
}
int heap_find(struct heap *h, void *elm) /* FIXME - very slow */
@@ -140,4 +143,3 @@ void heap_delete(struct heap *h, int e)
h->data = realloc(h->data, (h->max_size + 1) * sizeof(heap_val_t));
}
}
-
diff --git a/src/common/heap.h b/src/common/heap.h
index 6fe355c..5be7cfa 100644
--- a/src/common/heap.h
+++ b/src/common/heap.h
@@ -40,7 +40,7 @@ struct heap {
#define INITIAL_HEAP_SIZE 512 /* initial heap size */
#define HEAP_INCREASE_STEP 2 /* multiplier for each inflation, keep conservative */
#define HEAP_DECREASE_THRESHOLD 2 /* threshold for deflation, keep conservative */
-#define HELEMENT(h,num) ((h)->data + (num))
+#define HELEMENT(h,num) ((h)->data + (num))
#define HHEAD(h) HELEMENT((h),1)
#define EMPTY_HEAP(h) ((h)->num == 0) /* h->num == 0 */
diff --git a/src/common/latency.c b/src/common/latency.c
deleted file mode 100644
index 7f5f5f8..0000000
--- a/src/common/latency.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifdef PROF_LATENCY
-
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <pthread.h>
-
-
-/*! \brief Profiler statistics. */
-typedef struct pstat_t {
- double M; /*!< \brief Mean value. */
- unsigned long min, max; /*!< \brief Minimum, maximum. */
- unsigned long total; /*!< \brief Total profiled time. */
- unsigned long count; /*!< \brief Number of profiled calls. */
-} pstat_t;
-
-/*! \brief Function call profile. */
-typedef struct profile_t {
- const char* call;
- pstat_t stat;
-} profile_t;
-
-/*! \brief Observed function call codes. */
-enum pcall_code_t {
- PF_RECVFROM = 0,
- PF_SENDTO,
- PF_PTHREAD_MUTEX_LOCK,
- PF_PTHREAD_MUTEX_UNLOCK,
- PF_CALL_SIZE
-} pcall_code_t;
-
-/*! \brief Table of observed function calls. */
-static profile_t table[] = {
- { "recvfrom", {0} },
- { "sendto", {0} },
- { "pthread_mutex_lock", {0} },
- { "pthread_mutex_unlock", {0} },
- { "NULL", {0} }
-};
-
-
-/*! \brief Add value to statistics. */
-static inline void add_stat(pstat_t *stat, unsigned long val) {
-
- if (val < stat->min) {
- stat->min = val;
- }
- if (val > stat->max) {
- stat->max = val;
- }
-
- stat->total += val;
-
- double Mprev = stat->M, M = stat->M;
- M += (val - M)/((double)stat->count + 1);
- stat->M = M;
- //S += (val - M)*(x[i] - Mprev);
-
- ++stat->count;
-}
-
-/*! \brief Call profiler table initialization (automatically called on load). */
-void __attribute__ ((constructor)) profiler_init()
-{
- for (int i = 0; i < PF_CALL_SIZE; ++i) {
- pstat_t* stat = &table[i].stat;
- stat->M = 0;
- stat->max = 0;
- stat->min = (unsigned long)~0;
- stat->total = 0;
- stat->count = 0;
- }
-}
-
-/*! \brief Call profiler table evaluation (automatically called on exit). */
-void __attribute__ ((destructor)) profiler_deinit()
-{
-
- /* Get resource usage. */
- struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage) < 0) {
- memset(&usage, 0, sizeof(struct rusage));
- }
-
- fprintf(stderr, "\nStatistics:");
- fprintf(stderr, "\n==================\n");
-
- fprintf(stderr, "User time: %.03lf ms\nSystem time: %.03lf ms\n",
- usage.ru_utime.tv_sec * (double) 1000.0
- + usage.ru_utime.tv_usec / (double)1000.0,
- usage.ru_stime.tv_sec * (double) 1000.0
- + usage.ru_stime.tv_usec / (double)1000.0);
- fprintf(stderr, "Voluntary context switches: %lu\nInvoluntary context switches: %lu\n",
- usage.ru_nvcsw,
- usage.ru_nivcsw);
- fprintf(stderr, "==================\n");
- fprintf(stderr, "\n");
-
- /* Callers statistics. */
- for (int i = 0; i < PF_CALL_SIZE; ++i) {
- pstat_t* stat = &table[i].stat;
- fprintf(stderr, "%s: M=%lf min=%lu,max=%lu (total=%lu, %lu times) (usec)\n",
- table[i].call, stat->M, stat->min, stat->max, stat->total,
- stat->count);
- }
-
-}
-
-ssize_t pf_recvfrom(int socket, void *buf, size_t len, int flags,
- struct sockaddr *from, socklen_t *fromlen,
- const char* caller, const char* file, int line)
-{
- unsigned long elapsed = 0;
- int ret = 0;
- perf_begin();
- ret = recvfrom(socket, buf, len, flags, from, fromlen);
- perf_end(elapsed);
-
- /* Discard wakeup delays, count statistics otherwise. */
- if (elapsed < 200000) {
- add_stat(&table[PF_RECVFROM].stat, elapsed);
- }
- return ret;
-}
-
-ssize_t pf_sendto(int socket, const void *buf, size_t len, int flags,
- const struct sockaddr *to, socklen_t tolen,
- const char* caller, const char* file, int line)
-{
- unsigned long elapsed = 0;
- int ret = 0;
- perf_begin();
- ret = sendto(socket, buf, len, flags, to, tolen);
- perf_end(elapsed);
-
- /* Discard wakeup delays, count statistics otherwise. */
- if (elapsed < 200000) {
- add_stat(&table[PF_SENDTO].stat, elapsed);
- }
- return ret;
-}
-
-/* Pthreads */
-int pf_pthread_mutex_lock(pthread_mutex_t *mutex,
- const char* caller, const char* file, int line)
-{
- unsigned long elapsed = 0;
- int ret = 0;
- perf_begin();
- ret = pthread_mutex_lock(mutex);
- perf_end(elapsed);
-
- /* Discard wakeup delays, count statistics otherwise. */
- if (elapsed < 200000) {
- add_stat(&table[PF_PTHREAD_MUTEX_LOCK].stat, elapsed);
- }
-
- return ret;
-}
-
-int pf_pthread_mutex_unlock(pthread_mutex_t *mutex,
- const char* caller, const char* file, int line)
-{
- unsigned long elapsed = 0;
- int ret = 0;
- perf_begin();
- ret = pthread_mutex_unlock(mutex);
- perf_end(elapsed);
-
- /* Discard wakeup delays, count statistics otherwise. */
- if (elapsed < 200000) {
- add_stat(&table[PF_PTHREAD_MUTEX_UNLOCK].stat, elapsed);
- }
-
- return ret;
-}
-
-#endif // PROF_LATENCY
diff --git a/src/common/latency.h b/src/common/latency.h
deleted file mode 100644
index 39c3093..0000000
--- a/src/common/latency.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (C) 2011 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 latency.h
- *
- * \author Marek Vavrusa <marek.vavrusa@nic.cz>
- *
- * \brief Utilities for latency profiling.
- *
- * Selected calls latency profiler is enabled with PROF_LATENCY define.
- * You can roughly profile own code with perf_begin() and perf_end() macros.
- *
- * \addtogroup common_lib
- * @{
- */
-
-#ifndef _KNOTD_COMMON_LATENCY_H_
-#define _KNOTD_COMMON_LATENCY_H_
-
-/* Optional. */
-#ifdef PROF_LATENCY
-
-/* Do not include from latency.c */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <pthread.h>
-
-/* Profiler tools */
-
-/*! \brief Time profile begin macro. */
-#define perf_begin() \
-do { \
- struct timeval __begin; \
- gettimeofday(&__begin, 0)
-
-/*! \brief Time profile end macro
- * \param d Will contain the number of microseconds passed from perf_begin().
- */
-#define perf_end(d) \
- struct timeval __end; \
- gettimeofday(&__end, 0); \
- unsigned long __us = (__end.tv_sec - __begin.tv_sec) * 1000L * 1000L; \
- __us += (__end.tv_usec - __begin.tv_usec); \
- (d) = __us; \
-} while(0)
-
-/* Prototypes. */
-
-/*! \brief Profiled recvfrom(). */
-ssize_t pf_recvfrom(int socket, void *buf, size_t len, int flags,
- struct sockaddr *from, socklen_t *fromlen,
- const char* caller, const char* file, int line);
-
-/*! \brief Profiled sendto(). */
-ssize_t pf_sendto(int socket, const void *buf, size_t len, int flags,
- const struct sockaddr *to, socklen_t tolen,
- const char* caller, const char* file, int line);
-
-/*! \brief Profiled pthread_mutex_lock(). */
-int pf_pthread_mutex_lock(pthread_mutex_t *mutex,
- const char* caller, const char* file, int line);
-
-/*! \brief Profiled pthread_mutex_unlock(). */
-int pf_pthread_mutex_unlock(pthread_mutex_t *mutex,
- const char* caller, const char* file, int line);
-
-/*
- * Sockets.
- */
-
-/*! \brief Rerouted recvfrom(). */
-#define recvfrom(s, buf, len, flags, from, fromlen) \
- pf_recvfrom((s), (buf), (len), (flags), (from), (fromlen), \
- __FUNCTION__, __FILE__, __LINE__)
-
-/*! \brief Rerouted sendto(). */
-#define sendto(s, buf, len, flags, to, tolen) \
- pf_sendto((s), (buf), (len), (flags), (to), (tolen), \
- __FUNCTION__, __FILE__, __LINE__)
-
-/*
- * Pthreads.
- */
-
-/*! \brief Rerouted pthread_mutex_lock(). */
-#define pthread_mutex_lock(m) \
- pf_pthread_mutex_lock(m, __FUNCTION__, __FILE__, __LINE__)
-
-/*! \brief Rerouted pthread_mutex_unlock(). */
-#define pthread_mutex_unlock(m) \
- pf_pthread_mutex_unlock(m, __FUNCTION__, __FILE__, __LINE__)
-
-#else // PROF_LATENCY
-
-/* Profiler tools */
-#define perf_begin()
-#define perf_end(d)
-
-#endif // PROF_LATENCY
-#endif // _KNOTD_COMMON_LATENCY_H_
-
-/*! @} */
diff --git a/src/common/libtap/README b/src/common/libtap/README
deleted file mode 100644
index d57b81d..0000000
--- a/src/common/libtap/README
+++ /dev/null
@@ -1,231 +0,0 @@
-NAME
-====
-
-libtap - Write tests in C
-
-SYNOPSIS
-========
-
- #include <tap.h>
-
- int foo () {return 3;}
- char *bar () {return "fnord";}
-
- int main () {
- plan(5);
- ok(foo() == 3);
- is(bar(), "eek");
- ok(foo() <= 8732, "foo <= %d", 8732);
- like(bar(), "f(yes|no)r*[a-f]$", "is like");
- cmp_ok(foo(), ">=", 10, "foo is greater than ten");
- return exit_status();
- }
-
-results in:
-
- 1..5
- ok 1
- not ok 2
- # Failed test at synopsis.c line 9.
- # got: 'fnord'
- # expected: 'eek'
- ok 3 - foo <= 8732
- ok 4 - is like
- not ok 5 - foo is greater than ten
- # Failed test 'foo is greater than ten'
- # at synopsis.c line 12.
- # 3
- # >=
- # 10
- # Looks like you failed 2 tests of 5 run.
-
-DESCRIPTION
-===========
-
-tap is an easy to read and easy to write way of creating tests for your
-software. This library creates functions that can be used to generate it for
-your C programs. It is mostly based on the Test::More Perl module.
-
-FUNCTIONS
-=========
-
-- plan(tests)
-- plan(NO_PLAN)
-
- Use this to start a series of tests. When you know how many tests there
- will be, you can put a number as a number of tests you expect to run. If
- you do not know how many tests there will be, you can use plan(NO_PLAN)
- or not call this function. When you pass it a number of tests to run, a
- message similar to the following will appear in the output:
-
- 1..5
-
-- ok(test)
-- ok(test, fmt, ...)
-
- Specify a test. the test can be any statement returning a true or false
- value. You may optionally pass a format string describing the test.
-
- ok(r = reader_new("Of Mice and Men"), "create a new reader");
- ok(reader_go_to_page(r, 55), "can turn the page");
- ok(r->page == 55, "page turned to the right one");
-
- Should print out:
-
- ok 1 - create a new reader
- ok 2 - can turn the page
- ok 3 - page turned to the right one
-
- On failure, a diagnostic message will be printed out.
-
- not ok 3 - page turned to the right one
- # Failed test 'page turned to the right one'
- # at reader.c line 13.
-
-- is(got, expected)
-- is(got, expected, fmt, ...)
-- isnt(got, expected)
-- isnt(got, expected, fmt, ...)
-
- Tests that the string you got is what you expected. with isnt, it is the
- reverse.
-
- is("this", "that", "this is that");
-
- prints:
-
- not ok 1 - this is that
- # Failed test 'this is that'
- # at is.c line 6.
- # got: 'this'
- # expected: 'that'
-
-- cmp_ok(a, op, b)
-- cmp_ok(a, op, b, fmt, ...)
-
- Compares two ints with any binary operator that doesn't require an lvalue.
- This is nice to use since it provides a better error message than an
- equivalent ok.
-
- cmp_ok(420, ">", 666);
-
- prints:
-
- not ok 1
- # Failed test at cmpok.c line 5.
- # 420
- # >
- # 666
-
-- like(got, expected)
-- like(got, expected, fmt, ...)
-- unlike(got, expected)
-- unlike(got, expected, fmt, ...)
-
- Tests that the string you got matches the expected extended POSIX regex.
- unlike is the reverse. These macros are the equivalent of a skip on
- Windows.
-
- like("stranger", "^s.(r).*\\1$", "matches the regex");
-
- prints:
-
- ok 1 - matches the regex
-
-- pass()
-- pass(fmt, ...)
-- fail()
-- fail(fmt, ...)
-
- Speciy that a test succeeded or failed. Use these when the statement is
- longer than you can fit into the argument given to an ok() test.
-
-- dies_ok(code)
-- dies_ok(code, fmt, ...)
-- lives_ok(code)
-- lives_ok(code, fmt, ...)
-
- Tests whether the given code causes your program to exit. The code gets
- passed to a macro that will test it in a forked process. If the code
- succeeds it will be executed in the parent process. You can test things
- like passing a function a null pointer and make sure it doesnt
- dereference it and crash.
-
- dies_ok({abort();}, "abort does close your program");
- dies_ok({int x = 0/0;}, "divide by zero crash");
- lives ok({pow(3.0, 5.0)}, "nothing wrong with taking 3**5");
-
- On Windows, these macros are the equivalent of a skip.
-
-- exit_status()
-
- Summarizes the tests that occurred. If there was no plan, it will print
- out the number of tests as.
-
- 1..5
-
- It will also print a diagnostic message about how many
- failures there were.
-
- # Looks like you failed 2 tests of 3 run.
-
- If all planned tests were successful, it will return 0. If any test fails,
- it will return the number of failed tests (including ones that were
- missing). If they all passed, but there were missing tests, it will return
- 255.
-
-- note(fmt, ...)
-- diag(fmt, ...)
-
- print out a message to the tap output. note prints to stdout and diag
- prints to stderr. Each line is preceeded by a "# " so that you know its a
- diagnostic message.
-
- note("This is\na note\nto describe\nsomething.");
-
- prints:
-
- # This is
- # a note
- # to describe
- # something
-
- ok() and these functions return ints so you can use them like:
-
- ok(1) && note("yo!");
- ok(0) || diag("I have no idea what just happened");
-
-- skip(test, n)
-- skip(test, n, fmt, ...)
-- endskip
-
- Skip a series of n tests if test is true. You may give a reason why you are
- skipping them or not. The (possibly) skipped tests must occur between the
- skip and endskip macros.
-
- skip(TRUE, 2);
- ok(1);
- ok(0);
- endskip;
-
- prints:
-
- ok 1 # skip
- ok 2 # skip
-
-- todo()
-- todo(fmt, ...)
-- endtodo
-
- Specifies a series of tests that you expect to fail because they are not
- yet implemented.
-
- todo()
- ok(0);
- endtodo;
-
- prints:
-
- not ok 1 # TODO
- # Failed (TODO) test at todo.c line 7
-
diff --git a/src/common/libtap/tap.c b/src/common/libtap/tap.c
index d6bb995..e89948b 100644
--- a/src/common/libtap/tap.c
+++ b/src/common/libtap/tap.c
@@ -9,6 +9,7 @@ This file is licensed under the GPL v3
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include "common.h"
#include "tap.h"
static int expected_tests = NO_PLAN;
@@ -26,7 +27,7 @@ vstrdupf (const char *fmt, va_list args) {
fmt = "";
size = vsnprintf(NULL, 0, fmt, args2) + 2;
str = malloc(size);
- vsprintf(str, fmt, args);
+ vsnprintf(str, size, fmt, args);
va_end(args2);
return str;
}
@@ -226,6 +227,7 @@ exit_status () {
int
bail_out (int ignore, const char *fmt, ...) {
+ UNUSED(ignore);
va_list args;
va_start(args, fmt);
printf("Bail out! ");
@@ -252,6 +254,7 @@ skippy (int n, const char *fmt, ...) {
void
ctodo (int ignore, const char *fmt, ...) {
+ UNUSED(ignore);
va_list args;
va_start(args, fmt);
todo_mesg = vstrdupf(fmt, args);
@@ -322,4 +325,3 @@ like_at_loc (int for_match, const char *file, int line, const char *got,
return test;
}
#endif
-
diff --git a/src/common/libtap/tap.h b/src/common/libtap/tap.h
index 89484f4..40e7bf3 100644
--- a/src/common/libtap/tap.h
+++ b/src/common/libtap/tap.h
@@ -111,4 +111,3 @@ int tap_test_died (int status);
#endif
#endif
-
diff --git a/src/common/libtap/tap_unit.h b/src/common/libtap/tap_unit.h
index c248fde..8cd20ad 100644
--- a/src/common/libtap/tap_unit.h
+++ b/src/common/libtap/tap_unit.h
@@ -91,4 +91,3 @@ typedef struct {
#endif // _TAP_UNIT_H_
/*! @} */
-
diff --git a/src/common/lists.c b/src/common/lists.c
index 9a93733..e629e9d 100644
--- a/src/common/lists.c
+++ b/src/common/lists.c
@@ -26,6 +26,7 @@
#define _BIRD_LISTS_C_
+#include <config.h>
#include <stdlib.h>
#include <string.h>
#include "common/lists.h"
@@ -158,3 +159,21 @@ void list_dup(list *dst, list *src, size_t itemsz)
add_tail(dst, i);
}
}
+
+/**
+ * list_size - gets number of nodes
+ * @l: list
+ *
+ * This function counts nodes in list @l and returns this number.
+ */
+size_t list_size(const list *l)
+{
+ size_t count = 0;
+
+ node *n = 0;
+ WALK_LIST(n, *l) {
+ count++;
+ }
+
+ return count;
+}
diff --git a/src/common/lists.h b/src/common/lists.h
index 897b1a9..392f75d 100644
--- a/src/common/lists.h
+++ b/src/common/lists.h
@@ -81,6 +81,7 @@ void add_tail_list(list *, list *);
void init_list(list *);
void insert_node(node *, node *);
void list_dup(list *dst, list *src, size_t itemsz);
+size_t list_size(const list *);
/*!
* \brief List item for string lists.
diff --git a/src/common/log.c b/src/common/log.c
index ff6475e..2301e19 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -25,7 +25,6 @@
#include "common/log.h"
#include "common/lists.h"
-#include "knot/common.h"
#include "knot/conf/conf.h"
/*! Log source table. */
@@ -210,19 +209,31 @@ static int _log_msg(logsrc_t src, int level, const char *msg)
// Convert level to mask
level = LOG_MASK(level);
-
+
/* Prefix date and time. */
char tstr[128] = {0};
int tlen = 0;
struct tm lt;
struct timeval tv;
gettimeofday(&tv, NULL);
- if (localtime_r(&tv.tv_sec, &lt) != NULL) {
- tlen = strftime(tstr, sizeof(tstr) - 1,
- "%Y-%m-%dT%H:%M:%S", &lt);
- if (tlen > 0) {
- char pm = (lt.tm_gmtoff > 0)?'+':'-';
- snprintf(tstr+tlen, 128-tlen-1, ".%.6lu%c%.2u:%.2u ", (unsigned long)tv.tv_usec, pm, (unsigned int)lt.tm_gmtoff/3600, (unsigned int)(lt.tm_gmtoff/60)%60);
+ time_t sec = tv.tv_sec;
+ if (localtime_r(&sec, &lt) != NULL) {
+ bool precise = false;
+
+#ifdef ENABLE_MICROSECONDS_LOG
+ precise = true;
+#endif /* ENABLE_MICROSECONDS_LOG */
+
+ tlen = strftime(tstr, sizeof(tstr),
+ "%Y-%m-%dT%H:%M:%S ", &lt);
+
+ if (precise && tlen > 0) {
+ char pm = (lt.tm_gmtoff > 0) ? '+' : '-';
+ snprintf(tstr + tlen - 1, sizeof(tstr) - tlen + 1,
+ ".%.6lu%c%.2u:%.2u ",
+ (unsigned long)tv.tv_usec, pm,
+ (unsigned int)lt.tm_gmtoff / 3600,
+ (unsigned int)(lt.tm_gmtoff / 60) % 60);
}
}
@@ -273,7 +284,7 @@ int log_msg(logsrc_t src, int level, const char *msg, ...)
case LOG_FATAL: prefix = "[fatal] "; break;
default: break;
}
-
+
/* Prepend prefix. */
int plen = strlen(prefix);
if (plen > buflen) {
@@ -323,9 +334,12 @@ void hex_log(int source, const char *data, int length)
log_msg(source, LOG_DEBUG, "%s\n", lbuf);
llen = 0;
}
- int n = sprintf(lbuf + llen, "0x%02x ",
- (unsigned char)*(data + ptr));
- llen += n;
+ int ret = snprintf(lbuf + llen, sizeof(lbuf) - llen, "0x%02x ",
+ (unsigned char)*(data + ptr));
+ if (ret < 0 || ret >= sizeof(lbuf) - llen) {
+ return;
+ }
+ llen += ret;
}
if (llen > 0) {
log_msg(source, LOG_DEBUG, "%s\n", lbuf);
@@ -338,7 +352,7 @@ int log_update_privileges(int uid, int gid)
if (fchown(fileno(LOG_FDS[i]), uid, gid) < 0) {
return KNOT_ERROR;
}
-
+
}
return KNOT_EOK;
}
diff --git a/src/common/mempattern.c b/src/common/mempattern.c
index acf6eac..2ea7e50 100644
--- a/src/common/mempattern.c
+++ b/src/common/mempattern.c
@@ -14,15 +14,51 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/resource.h>
-#include <config.h>
#include <stdarg.h>
+#include "mempattern.h"
+#include "common/log.h"
#include "common/slab/alloc-common.h"
+static void *mm_malloc(void *ctx, size_t n)
+{
+ UNUSED(ctx);
+ return malloc(n);
+}
+
+void mm_ctx_init(mm_ctx_t *mm)
+{
+ mm->ctx = NULL;
+ mm->alloc = mm_malloc;
+ mm->free = free;
+}
+
+void* xmalloc(size_t l)
+{
+ void *p = malloc(l);
+ if (p == NULL) {
+ log_server_fatal("Failed to allocate %zu bytes.\n", l);
+ abort();
+ }
+ return p;
+}
+
+void *xrealloc(void *p, size_t l)
+{
+ p = realloc(p, l);
+ if (p == NULL) {
+ log_server_fatal("Failed to reallocate to %zu bytes from %p.\n",
+ l, p);
+ abort();
+ }
+ return p;
+}
+
int mreserve(char **p, size_t tlen, size_t min, size_t allow, size_t *reserved)
{
@@ -31,7 +67,7 @@ int mreserve(char **p, size_t tlen, size_t min, size_t allow, size_t *reserved)
if (maxlen < min) {
return -2; /* size_t overflow */
}
-
+
/* Meet target size but trim excessive amounts. */
if (*reserved < min || *reserved > maxlen) {
void *trimmed = realloc(*p, maxlen * tlen);
@@ -42,7 +78,7 @@ int mreserve(char **p, size_t tlen, size_t min, size_t allow, size_t *reserved)
return -1;
}
}
-
+
return 0;
}
@@ -51,21 +87,21 @@ char* sprintf_alloc(const char *fmt, ...)
int size = 100;
char *p = NULL, *np = NULL;
va_list ap;
-
+
if ((p = malloc(size)) == NULL)
return NULL;
-
+
while (1) {
-
+
/* Try to print in the allocated space. */
va_start(ap, fmt);
int n = vsnprintf(p, size, fmt, ap);
va_end(ap);
-
+
/* If that worked, return the string. */
if (n > -1 && n < size)
return p;
-
+
/* Else try again with more space. */
if (n > -1) { /* glibc 2.1 */
size = n+1; /* precisely what is needed */
@@ -79,11 +115,30 @@ char* sprintf_alloc(const char *fmt, ...)
p = np;
}
}
-
+
/* Should never get here. */
return p;
}
+char* strcdup(const char *s1, const char *s2)
+{
+ if (!s1 || !s2) {
+ return NULL;
+ }
+
+ size_t slen = strlen(s1);
+ size_t s2len = strlen(s2);
+ size_t nlen = slen + s2len + 1;
+ char* dst = malloc(nlen);
+ if (dst == NULL) {
+ return NULL;
+ }
+
+ memcpy(dst, s1, slen);
+ strncpy(dst + slen, s2, s2len + 1); // With trailing '\0'
+ return dst;
+}
+
#ifdef MEM_DEBUG
/*
* ((destructor)) attribute executes this function after main().
diff --git a/src/common/mempattern.h b/src/common/mempattern.h
index ebfe4ae..7bef851 100644
--- a/src/common/mempattern.h
+++ b/src/common/mempattern.h
@@ -27,6 +27,29 @@
#ifndef _KNOTD_COMMON_MALLOC_H_
#define _KNOTD_COMMON_MALLOC_H_
+#include <stddef.h>
+
+/* Memory allocation function prototypes. */
+typedef void* (*mm_alloc_t)(void* ctx, size_t len);
+typedef void (*mm_free_t)(void *p);
+typedef void (*mm_flush_t)(void *p);
+
+/* Memory allocation context. */
+typedef struct mm_ctx {
+ void *ctx; /* \note Must be first */
+ mm_alloc_t alloc;
+ mm_free_t free;
+} mm_ctx_t;
+
+/*! \brief Initialize default memory allocation context. */
+void mm_ctx_init(mm_ctx_t *mm);
+
+/*! \brief Allocate memory or die. */
+void* xmalloc(size_t l);
+
+/*! \brief Reallocate memory or die. */
+void *xrealloc(void *p, size_t l);
+
/*!
* \brief Reserve new or trim excessive memory.
*
@@ -64,6 +87,17 @@ int mreserve(char **p, size_t tlen, size_t min, size_t allow, size_t *reserved);
*/
char* sprintf_alloc(const char *fmt, ...);
+/*!
+ * \brief Create new string from a concatenation of s1 and s2.
+ *
+ * \param s1 First string.
+ * \param s2 Second string.
+ *
+ * \retval Newly allocated string on success.
+ * \retval NULL on error.
+ */
+char* strcdup(const char *s1, const char *s2);
+
/*! \brief Print usage statistics.
*
* \note This function has destructor attribute set if MEM_DEBUG is enabled.
diff --git a/src/common/mempool.c b/src/common/mempool.c
new file mode 100644
index 0000000..049b016
--- /dev/null
+++ b/src/common/mempool.c
@@ -0,0 +1,330 @@
+/*
+ * UCW Library -- Memory Pools (One-Time Allocation)
+ *
+ * (c) 1997--2001 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 <config.h>
+
+#undef LOCAL_DEBUG
+
+#include "mempool.h"
+#include "common/mempattern.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+/** \todo This shouldn't be precalculated, but computed on load. */
+#define CPU_PAGE_SIZE 4096
+/** 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))
+#define MP_CHUNK_TAIL ALIGN_TO(sizeof(struct mempool_chunk), CPU_STRUCT_ALIGN)
+#define MP_SIZE_MAX (~0U - MP_CHUNK_TAIL - CPU_PAGE_SIZE)
+#ifndef MAX
+#define MAX(a, b) \
+ ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })
+#endif
+#define DBG(s...)
+
+struct mempool_chunk {
+ struct mempool_chunk *next;
+ unsigned size;
+};
+
+static unsigned
+mp_align_size(unsigned size)
+{
+#ifdef CONFIG_UCW_POOL_IS_MMAP
+ return ALIGN_TO(size + MP_CHUNK_TAIL, CPU_PAGE_SIZE) - MP_CHUNK_TAIL;
+#else
+ return ALIGN_TO(size, CPU_STRUCT_ALIGN);
+#endif
+}
+
+void
+mp_init(struct mempool *pool, unsigned chunk_size)
+{
+ chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
+ *pool = (struct mempool) {
+ .chunk_size = chunk_size,
+ .threshold = chunk_size >> 1,
+ .last_big = &pool->last_big };
+}
+
+static void *
+mp_new_big_chunk(unsigned size)
+{
+ struct mempool_chunk *chunk;
+ chunk = xmalloc(size + MP_CHUNK_TAIL) + size;
+ chunk->size = size;
+ return chunk;
+}
+
+static void
+mp_free_big_chunk(struct mempool_chunk *chunk)
+{
+ free((void *)chunk - chunk->size);
+}
+
+static void *
+mp_new_chunk(unsigned size)
+{
+#ifdef CONFIG_UCW_POOL_IS_MMAP
+ struct mempool_chunk *chunk;
+ chunk = page_alloc(size + MP_CHUNK_TAIL) + size;
+ chunk->size = size;
+ return chunk;
+#else
+ return mp_new_big_chunk(size);
+#endif
+}
+
+static void
+mp_free_chunk(struct mempool_chunk *chunk)
+{
+#ifdef CONFIG_UCW_POOL_IS_MMAP
+ page_free((void *)chunk - chunk->size, chunk->size + MP_CHUNK_TAIL);
+#else
+ mp_free_big_chunk(chunk);
+#endif
+}
+
+struct mempool *
+mp_new(unsigned chunk_size)
+{
+ chunk_size = mp_align_size(MAX(sizeof(struct mempool), chunk_size));
+ struct mempool_chunk *chunk = mp_new_chunk(chunk_size);
+ struct mempool *pool = (void *)chunk - chunk_size;
+ DBG("Creating mempool %p with %u bytes long chunks", pool, chunk_size);
+ chunk->next = NULL;
+ *pool = (struct mempool) {
+ .state = { .free = { chunk_size - sizeof(*pool) }, .last = { chunk } },
+ .chunk_size = chunk_size,
+ .threshold = chunk_size >> 1,
+ .last_big = &pool->last_big };
+ return pool;
+}
+
+static void
+mp_free_chain(struct mempool_chunk *chunk)
+{
+ while (chunk)
+ {
+ struct mempool_chunk *next = chunk->next;
+ mp_free_chunk(chunk);
+ chunk = next;
+ }
+}
+
+static void
+mp_free_big_chain(struct mempool_chunk *chunk)
+{
+ while (chunk)
+ {
+ struct mempool_chunk *next = chunk->next;
+ mp_free_big_chunk(chunk);
+ chunk = next;
+ }
+}
+
+void
+mp_delete(struct mempool *pool)
+{
+ DBG("Deleting mempool %p", pool);
+ mp_free_big_chain(pool->state.last[1]);
+ mp_free_chain(pool->unused);
+ mp_free_chain(pool->state.last[0]); // can contain the mempool structure
+}
+
+void
+mp_flush(struct mempool *pool)
+{
+ mp_free_big_chain(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_chunk *chunk, struct mempool_stats *stats, unsigned idx)
+{
+ while (chunk)
+ {
+ stats->chain_size[idx] += chunk->size + sizeof(*chunk);
+ stats->chain_count[idx]++;
+ 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->state.last[0], stats, 0);
+ mp_stats_chain(pool->state.last[1], stats, 1);
+ mp_stats_chain(pool->unused, stats, 2);
+}
+
+uint64_t
+mp_total_size(struct mempool *pool)
+{
+ struct mempool_stats stats;
+ mp_stats(pool, &stats);
+ return stats.total_size;
+}
+
+void *
+mp_alloc_internal(struct mempool *pool, unsigned 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->chunk_size);
+ 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 (size <= MP_SIZE_MAX)
+ {
+ pool->idx = 1;
+ unsigned aligned = ALIGN_TO(size, CPU_STRUCT_ALIGN);
+ chunk = mp_new_big_chunk(aligned);
+ chunk->next = pool->state.last[1];
+ pool->state.last[1] = chunk;
+ pool->state.free[1] = aligned - size;
+ return pool->last_big = (void *)chunk - aligned;
+ }
+ else {
+ fprintf(stderr, "Cannot allocate %u bytes from a mempool", size);
+ assert(0);
+ return NULL;
+ }
+}
+
+void *
+mp_alloc(struct mempool *pool, unsigned size)
+{
+ return mp_alloc_fast(pool, size);
+}
+
+void *
+mp_alloc_noalign(struct mempool *pool, unsigned size)
+{
+ return mp_alloc_fast_noalign(pool, size);
+}
+
+void *
+mp_alloc_zero(struct mempool *pool, unsigned size)
+{
+ void *ptr = mp_alloc_fast(pool, size);
+ bzero(ptr, size);
+ return ptr;
+}
+
+void *
+mp_start_internal(struct mempool *pool, unsigned size)
+{
+ void *ptr = mp_alloc_internal(pool, size);
+ pool->state.free[pool->idx] += size;
+ return ptr;
+}
+
+void *
+mp_start(struct mempool *pool, unsigned size)
+{
+ return mp_start_fast(pool, size);
+}
+
+void *
+mp_start_noalign(struct mempool *pool, unsigned size)
+{
+ return mp_start_fast_noalign(pool, size);
+}
+
+void *
+mp_grow_internal(struct mempool *pool, unsigned size)
+{
+ if (size > MP_SIZE_MAX) {
+ fprintf(stderr, "Cannot allocate %u bytes of memory", size);
+ assert(0);
+ }
+ unsigned avail = mp_avail(pool);
+ void *ptr = mp_ptr(pool);
+ if (pool->idx)
+ {
+ unsigned amortized = (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;
+ ptr = xrealloc(ptr, amortized + MP_CHUNK_TAIL);
+ 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;
+ }
+}
+
+unsigned
+mp_open(struct mempool *pool, void *ptr)
+{
+ return mp_open_fast(pool, ptr);
+}
+
+void *
+mp_realloc(struct mempool *pool, void *ptr, unsigned size)
+{
+ return mp_realloc_fast(pool, ptr, size);
+}
+
+void *
+mp_realloc_zero(struct mempool *pool, void *ptr, unsigned size)
+{
+ unsigned 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, unsigned size)
+{
+ void *old = mp_ptr(pool);
+ void *new = mp_grow_internal(pool, p-old+size);
+ return p-old+new;
+}
diff --git a/src/common/mempool.h b/src/common/mempool.h
new file mode 100644
index 0000000..af457b3
--- /dev/null
+++ b/src/common/mempool.h
@@ -0,0 +1,345 @@
+/*
+ * UCW Library -- Memory Pools
+ *
+ * (c) 1997--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.
+ */
+
+#ifndef _UCW_POOLS_H
+#define _UCW_POOLS_H
+
+#include <string.h>
+#include <stdint.h>
+
+#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
+
+#define CPU_STRUCT_ALIGN (sizeof(void*))
+
+/***
+ * [[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 {
+ unsigned 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 mempool_state state;
+ void *unused, *last_big;
+ unsigned chunk_size, threshold, idx;
+};
+
+struct mempool_stats { /** Mempool statistics. See @mp_stats(). **/
+ uint64_t total_size; /* Real allocated size in bytes */
+ unsigned chain_count[3]; /* Number of allocated chunks in small/big/unused chains */
+ unsigned 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, UINT_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, unsigned 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(unsigned 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>>.
+ **/
+void mp_stats(struct mempool *pool, struct mempool_stats *stats);
+uint64_t mp_total_size(struct mempool *pool); /** How many bytes were allocated by the pool. **/
+
+
+/***
+ * [[alloc]]
+ * Allocation routines
+ * -------------------
+ ***/
+
+/* For internal use only, do not call directly */
+void *mp_alloc_internal(struct mempool *pool, unsigned 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, unsigned size);
+
+/**
+ * The same as @mp_alloc(), but the result may be unaligned.
+ **/
+void *mp_alloc_noalign(struct mempool *pool, unsigned size);
+
+/**
+ * The same as @mp_alloc(), but fills the newly allocated memory with zeroes.
+ **/
+void *mp_alloc_zero(struct mempool *pool, unsigned size);
+
+/**
+ * Inlined version of @mp_alloc().
+ **/
+static inline void *mp_alloc_fast(struct mempool *pool, unsigned size)
+{
+ unsigned avail = pool->state.free[0] & ~(CPU_STRUCT_ALIGN - 1);
+ if (size <= avail)
+ {
+ pool->state.free[0] = avail - size;
+ return (uint8_t*)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, unsigned size)
+{
+ if (size <= pool->state.free[0])
+ {
+ void *ptr = (uint8_t*)pool->state.last[0] - pool->state.free[0];
+ pool->state.free[0] -= size;
+ return ptr;
+ }
+ else
+ return mp_alloc_internal(pool, size);
+}
+
+/***
+ * [[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, unsigned size) LIKE_MALLOC;
+void *mp_grow_internal(struct mempool *pool, unsigned size);
+void *mp_spread_internal(struct mempool *pool, void *p, unsigned size);
+
+static inline unsigned
+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, unsigned size);
+void *mp_start_noalign(struct mempool *pool, unsigned size);
+
+/**
+ * Inlined version of @mp_start().
+ **/
+static inline void *mp_start_fast(struct mempool *pool, unsigned size)
+{
+ unsigned avail = pool->state.free[0] & ~(CPU_STRUCT_ALIGN - 1);
+ if (size <= avail)
+ {
+ pool->idx = 0;
+ pool->state.free[0] = avail;
+ return (uint8_t*)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, unsigned size)
+{
+ if (size <= pool->state.free[0])
+ {
+ pool->idx = 0;
+ return (uint8_t*)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 (uint8_t*)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 unsigned 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, unsigned size)
+{
+ return (size <= mp_avail(pool)) ? mp_ptr(pool) : mp_grow_internal(pool, size);
+}
+
+/**
+ * Grow the buffer by at least one uint8_t-- 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, unsigned size)
+{
+ return (((unsigned)((uint8_t*)pool->state.last[pool->idx] - (uint8_t*)p) >= size) ? p : mp_spread_internal(pool, p, size));
+}
+
+/**
+ * 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] = (uint8_t*)pool->state.last[pool->idx] - (uint8_t*)end;
+ return p;
+}
+
+/**
+ * Return size in bytes of the last allocated memory block (with @mp_alloc() or @mp_end()).
+ **/
+static inline unsigned mp_size(struct mempool *pool, void *ptr)
+{
+ unsigned idx = mp_idx(pool, ptr);
+ return ((uint8_t*)pool->state.last[idx] - (uint8_t*)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.
+ **/
+unsigned mp_open(struct mempool *pool, void *ptr);
+
+/**
+ * Inlined version of mp_open().
+ **/
+static inline unsigned mp_open_fast(struct mempool *pool, void *ptr)
+{
+ pool->idx = mp_idx(pool, ptr);
+ unsigned size = ((uint8_t*)pool->state.last[pool->idx] - (uint8_t*)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, unsigned size);
+
+/**
+ * The same as @mp_realloc(), but fills the additional bytes (if any) with zeroes.
+ **/
+void *mp_realloc_zero(struct mempool *pool, void *ptr, unsigned size);
+
+/**
+ * Inlined version of mp_realloc().
+ **/
+static inline void *mp_realloc_fast(struct mempool *pool, void *ptr, unsigned size)
+{
+ mp_open_fast(pool, ptr);
+ ptr = mp_grow(pool, size);
+ mp_end(pool, (uint8_t*)ptr + size);
+ return ptr;
+}
+
+#endif
diff --git a/src/common/modified_tree.h b/src/common/modified_tree.h
deleted file mode 100644
index 9ceddd1..0000000
--- a/src/common/modified_tree.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/* tree.h -- AVL trees (in the spirit of BSD's 'queue.h') -*- C -*- */
-
-/* Copyright (c) 2005 Ian Piumarta
- *
- * 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, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * provided that the above copyright notice(s) and this permission notice appear
- * in all copies of the Software and that both the above copyright notice(s) and
- * this permission notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
- */
-
-/* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
- * Evgenii M. Landis, 'An algorithm for the organization of information',
- * Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian). Also in Myron
- * J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
- *
- * An AVL tree is headed by pointers to the root node and to a function defining
- * the ordering relation between nodes. Each node contains an arbitrary payload
- * plus three fields per tree entry: the depth of the subtree for which it forms
- * the root and two pointers to child nodes (singly-linked for minimum space, at
- * the expense of direct access to the parent node given a pointer to one of the
- * children). The tree is rebalanced after every insertion or removal. The
- * tree may be traversed in two directions: forward (in-order left-to-right) and
- * reverse (in-order, right-to-left).
- *
- * Because of the recursive nature of many of the operations on trees it is
- * necessary to define a number of helper functions for each type of tree node.
- * The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
- * unique names according to the node_tag. This macro should be invoked,
- * thereby defining the necessary functions, once per node tag in the program.
- *
- * For details on the use of these macros, see the tree(3) manual page.
- */
-
-#ifndef _modified_tree_h
-#define _modified_tree_h
-
-
-#define MOD_TREE_DELTA_MAX 1
-
-#define MOD_TREE_ENTRY(type) \
- struct { \
- struct type *avl_left; \
- struct type *avl_right; \
- int avl_height; \
- }
-
-#define MOD_TREE_HEAD(name, type) \
- struct name { \
- struct type *th_root; \
- int (*th_cmp)(void *lhs, void *rhs); \
- }
-
-#define MOD_TREE_INITIALIZER(cmp) { 0, cmp}
-
-#define MOD_TREE_DELTA(self, field) \
- (( (((self)->field.avl_left) ? (self)->field.avl_left->field.avl_height : 0)) \
- - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
-
-/* Recursion prevents the following from being defined as macros. */
-
-#define MOD_TREE_DEFINE(node, field) \
- \
- struct node *MOD_TREE_BALANCE_##node##_##field(struct node *); \
- \
- struct node *MOD_TREE_ROTL_##node##_##field(struct node *self) \
- { \
- struct node *r= self->field.avl_right; \
- self->field.avl_right= r->field.avl_left; \
- r->field.avl_left= MOD_TREE_BALANCE_##node##_##field(self); \
- return MOD_TREE_BALANCE_##node##_##field(r); \
- } \
- \
- struct node *MOD_TREE_ROTR_##node##_##field(struct node *self) \
- { \
- struct node *l= self->field.avl_left; \
- self->field.avl_left= l->field.avl_right; \
- l->field.avl_right= MOD_TREE_BALANCE_##node##_##field(self); \
- return MOD_TREE_BALANCE_##node##_##field(l); \
- } \
- \
- struct node *MOD_TREE_BALANCE_##node##_##field(struct node *self) \
- { \
- int delta= MOD_TREE_DELTA(self, field); \
- \
- if (delta < -MOD_TREE_DELTA_MAX) \
- { \
- if (MOD_TREE_DELTA(self->field.avl_right, field) > 0) \
- self->field.avl_right= MOD_TREE_ROTR_##node##_##field(self->field.avl_right); \
- return MOD_TREE_ROTL_##node##_##field(self); \
- } \
- else if (delta > MOD_TREE_DELTA_MAX) \
- { \
- if (MOD_TREE_DELTA(self->field.avl_left, field) < 0) \
- self->field.avl_left= MOD_TREE_ROTL_##node##_##field(self->field.avl_left); \
- return MOD_TREE_ROTR_##node##_##field(self); \
- } \
- self->field.avl_height= 0; \
- if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height)) \
- self->field.avl_height= self->field.avl_left->field.avl_height; \
- if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height)) \
- self->field.avl_height= self->field.avl_right->field.avl_height; \
- self->field.avl_height += 1; \
- return self; \
- } \
- \
- struct node *MOD_TREE_INSERT_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(void *lhs, void *rhs), int (*merge)(void **lhs, void **rhs), int *merged)\
- { \
- if (!self) { \
- *merged = 0; \
- return elm; } \
- int cmp = compare(elm->data, self->data); \
- if (cmp < 0) \
- self->field.avl_left= MOD_TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare, merge, merged); \
- else if (cmp > 0) \
- self->field.avl_right= MOD_TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare, merge, merged); \
- else if (merge) { \
- merge(&(self->data), &(elm->data)); \
- *merged = 1; } \
- else \
- self->field.avl_right= MOD_TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare, merge, merged); \
- return MOD_TREE_BALANCE_##node##_##field(self); \
- } \
- \
- struct node *MOD_TREE_FIND_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(void *lhs, void *rhs)) \
- { \
- if (!compare) \
- return 0; \
- if (!self) \
- return 0; \
- if (compare(elm->data, self->data) == 0) \
- return self; \
- if (compare(elm->data, self->data) < 0) \
- return MOD_TREE_FIND_##node##_##field(self->field.avl_left, elm, compare); \
- else \
- return MOD_TREE_FIND_##node##_##field(self->field.avl_right, elm, compare); \
- } \
- \
- int MOD_TREE_FIND_LESS_EQUAL_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(void *lhs, void *rhs), struct node **found, struct node **prev) \
- { \
- if (!self) \
- return 0; \
- if (compare(elm->data, self->data) == 0) { \
- *found = self; \
- return 1; \
- } \
- if (compare(elm->data, self->data) < 0) { \
- int ret = MOD_TREE_FIND_LESS_EQUAL_##node##_##field(self->field.avl_left, elm, compare, found, prev); \
- if (ret == 0 && *prev == NULL) { \
- *prev = self; \
- ret = -1; \
- } \
- return ret; \
- } else { \
- *found = self; \
- *prev = self; \
- return MOD_TREE_FIND_LESS_EQUAL_##node##_##field(self->field.avl_right, elm, compare, found, prev); \
- } \
- } \
- \
- struct node *MOD_TREE_MOVE_RIGHT_##node##_##field(struct node *self, struct node *rhs) \
- { \
- if (!self) \
- return rhs; \
- self->field.avl_right= MOD_TREE_MOVE_RIGHT_##node##_##field(self->field.avl_right, rhs); \
- return MOD_TREE_BALANCE_##node##_##field(self); \
- } \
- \
- struct node *MOD_TREE_REMOVE_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(void *lhs, void *rhs), void (*del)(struct node *lhs)) \
- { \
- if (!self) return 0; \
- \
- if (compare(elm->data, self->data) == 0) \
- { \
- struct node *tmp= MOD_TREE_MOVE_RIGHT_##node##_##field(self->field.avl_left, self->field.avl_right); \
- self->field.avl_left= 0; \
- self->field.avl_right= 0; \
- del(self); \
- return tmp; \
- } \
- if (compare(elm->data, self->data) < 0) \
- self->field.avl_left= MOD_TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare, del); \
- else \
- self->field.avl_right= MOD_TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare, del); \
- return MOD_TREE_BALANCE_##node##_##field(self); \
- } \
- \
- void MOD_TREE_FORWARD_APPLY_ALL_##node##_##field \
- (struct node *self, void (*function)(void *node, void *data), void *data) \
- { \
- if (self) \
- { \
- MOD_TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
- function(self->data, data); \
- MOD_TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
- } \
- } \
- \
- void MOD_TREE_REVERSE_APPLY_ALL_##node##_##field \
- (struct node *self, void (*function)(struct node *node, void *data), void *data) \
- { \
- if (self) \
- { \
- MOD_TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
- function(self, data); \
- MOD_TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
- } \
- } \
- \
- void MOD_TREE_POST_ORDER_APPLY_ALL_##node##_##field \
- (struct node *self, void (*function)(struct node *node, void *data), void *data) \
- { \
- if (self) \
- { \
- MOD_TREE_POST_ORDER_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
- MOD_TREE_POST_ORDER_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
- function(self, data); \
- } \
- } \
- \
-void MOD_TREE_DESTROY_ALL_##node##_##field \
- (struct node *self, void (*function)(void *node, void *data), void(*dest)(struct node *node), void *data) \
-{ \
- if (self) \
- { \
- MOD_TREE_DESTROY_ALL_##node##_##field(self->field.avl_left, function, dest, data); \
- MOD_TREE_DESTROY_ALL_##node##_##field(self->field.avl_right, function, dest, data); \
- if (function != NULL) \
- function(self->data, data); \
- dest(self); \
- } \
-} \
- \
- void MOD_TREE_REVERSE_APPLY_POST_ALL_##node##_##field \
- (struct node *self, void (*function)(struct node *node, void *data), void *data) \
- { \
- if (self) \
- { \
- MOD_TREE_REVERSE_APPLY_POST_ALL_##node##_##field(self->field.avl_right, function, data); \
- MOD_TREE_REVERSE_APPLY_POST_ALL_##node##_##field(self->field.avl_left, function, data); \
- function(self, data); \
- } \
-}
-
-#define MOD_TREE_INSERT(head, node, field, elm, merge, merged) \
- ((head)->th_root= MOD_TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp, merge, merged))
-
-#define MOD_TREE_FIND(head, node, field, elm) \
- (MOD_TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
-
-#define MOD_TREE_FIND_LESS_EQUAL(head, node, field, elm, found, prev) \
- (MOD_TREE_FIND_LESS_EQUAL_##node##_##field((head)->th_root, (elm), (head)->th_cmp, found, prev))
-
-#define MOD_TREE_REMOVE(head, node, field, elm, rem) \
- ((head)->th_root= MOD_TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp, (rem)))
-
-#define MOD_TREE_DEPTH(head, field) \
- ((head)->th_root->field.avl_height)
-
-#define MOD_TREE_FORWARD_APPLY(head, node, field, function, data) \
- MOD_TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
-
-#define MOD_TREE_REVERSE_APPLY(head, node, field, function, data) \
- MOD_TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
-
-#define MOD_TREE_POST_ORDER_APPLY(head, node, field, function, data) \
- MOD_TREE_POST_ORDER_APPLY_ALL_##node##_##field((head)->th_root, function, data)
-
-#define MOD_TREE_DESTROY(head, node, field, function, dest, data) \
- MOD_TREE_DESTROY_ALL_##node##_##field((head)->th_root, function, dest, data)
-
-#define MOD_TREE_REVERSE_APPLY_POST(head, node, field, function, data) \
- MOD_TREE_REVERSE_APPLY_POST_ALL_##node##_##field((head)->th_root, function, data)
-
-#define MOD_TREE_INIT(head, cmp) do { \
- (head)->th_root= 0; \
- (head)->th_cmp= (cmp); \
- } while (0)
-
-
-#endif /* __MOD_TREE_h */
diff --git a/src/common/print.c b/src/common/print.c
index 9764568..4735e54 100644
--- a/src/common/print.c
+++ b/src/common/print.c
@@ -16,29 +16,54 @@
#include <config.h>
#include <stdio.h>
-
+#include <ctype.h>
#include "print.h"
-void hex_printf(const char *data, int length, printf_t print_handler)
+void array_printf(const uint8_t *data, const unsigned length,
+ printf_t print_handler, const char type)
{
- int ptr = 0;
- for (; ptr < length; ptr++) {
- print_handler("0x%02x ", (unsigned char)*(data + ptr));
+ for (unsigned i = 0; i < length; i++) {
+ uint8_t ch = data[i];
+
+ switch (type) {
+ case 't':
+ if (isprint(ch) != 0) {
+ print_handler("%c ", ch);
+ } else {
+ print_handler(" ");
+ }
+ break;
+ case 'x':
+ print_handler("%02X ", ch);
+ break;
+ default:
+ print_handler("0x%02X ", ch);
+ }
}
print_handler("\n");
}
-void hex_print(const char *data, int length)
+void hex_print(const uint8_t *data, unsigned length)
+{
+ array_printf(data, length, &printf, 0);
+}
+
+void short_hex_print(const uint8_t *data, unsigned length)
{
- hex_printf(data, length, &printf);
+ array_printf(data, length, &printf, 'x');
}
-void bit_printf(const char *data, int length, printf_t print_handler)
+void txt_print(const uint8_t *data, unsigned length)
+{
+ array_printf(data, length, &printf, 't');
+}
+
+void bit_printf(const uint8_t *data, unsigned length, printf_t print_handler)
{
unsigned char mask = 0x01;
- int ptr = 0;
+ unsigned ptr;
int bit = 0;
- for (; ptr < length; ptr++) {
+ for (ptr = 0; ptr < length; ptr++) {
for (bit = 7; bit >= 0; bit--) {
if ((mask << bit) & (unsigned char)*(data + ptr)) {
print_handler("1");
@@ -51,7 +76,14 @@ void bit_printf(const char *data, int length, printf_t print_handler)
print_handler("\n");
}
-void bit_print(const char *data, int length)
+void bit_print(const uint8_t *data, unsigned length)
{
bit_printf(data, length, &printf);
}
+
+float time_diff(struct timeval *begin, struct timeval *end)
+{
+ return (end->tv_sec - begin->tv_sec) * 1000 +
+ (end->tv_usec - begin->tv_usec) / 1000.0;
+
+}
diff --git a/src/common/print.h b/src/common/print.h
index 482f55e..bd67610 100644
--- a/src/common/print.h
+++ b/src/common/print.h
@@ -30,42 +30,75 @@
#ifndef _KNOTD_COMMON_PRINT_H_
#define _KNOTD_COMMON_PRINT_H_
+#include <sys/time.h>
+#include <stdint.h>
+
typedef int (*printf_t)(const char *fmt, ...);
/*!
- * \brief Prints the given data as hexadecimal characters.
+ * \brief Prints the given data as hexadecimal character string. Each hexa-pair
+ * contains leading 0x string.
+ *
+ * \param data Data to print.
+ * \param length Size of the \a data array.
+ */
+void hex_print(const uint8_t *data, unsigned length);
+
+/*!
+ * \brief Prints the given data as hexadecimal character string.
+ *
+ * \param data Data to print.
+ * \param length Size of the \a data array.
+ */
+void short_hex_print(const uint8_t *data, unsigned length);
+
+/*!
+ * \brief Prints the given data as text character string. Unprintable characters
+ * are replaced with a space.
*
- * \param data Data to print.
- * \param length Size of the \a data array.
+ * \param data Data to print.
+ * \param length Size of the \a data array.
*/
-void hex_print(const char *data, int length);
+void txt_print(const uint8_t *data, unsigned length);
/*!
- * \brief Prints the given data as hexadecimal characters using the given
- * handler.
+ * \brief Prints the given data array as a specified character string using
+ * the given handler.
*
- * \param data Data to print.
- * \param length Size of the \a data array.
- * \param print_handler Handler for printing.
+ * \param data Data to print.
+ * \param length Size of the \a data array.
+ * \param print_handler Handler for printing.
+ * \param type Character type ('x': hex, 't': txt, otherwise: 0xXX).
*/
-void hex_printf(const char *data, int length, printf_t print_handler);
+void array_printf(const uint8_t *data, const unsigned length,
+ printf_t print_handler, const char type);
/*!
* \brief Prints the given data as a bitmap.
*
- * \param data Data to print.
- * \param length Size of the \a data array.
+ * \param data Data to print.
+ * \param length Size of the \a data array.
*/
-void bit_print(const char *data, int length);
+void bit_print(const uint8_t *data, unsigned length);
/*!
* \brief Prints the given data as a bitmap using the given handler.
*
- * \param data Data to print.
- * \param length Size of the \a data array.
- * \param print_handler Handler for printing.
+ * \param data Data to print.
+ * \param length Size of the \a data array.
+ * \param print_handler Handler for printing.
+ */
+void bit_printf(const uint8_t *data, unsigned length, printf_t print_handler);
+
+/*!
+ * \brief Get time diff in miliseconds.
+ *
+ * \param begin
+ * \param end
+ *
+ * \return time diff
*/
-void bit_printf(const char *data, int length, printf_t print_handler);
+float time_diff(struct timeval *begin, struct timeval *end);
#endif /* _KNOTD_COMMON_PRINT_H_ */
diff --git a/src/common/prng.c b/src/common/prng.c
index 250a506..c94bd25 100644
--- a/src/common/prng.c
+++ b/src/common/prng.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -21,10 +22,11 @@
#include <time.h>
#include <sys/time.h>
#include <config.h>
-#ifdef HAVE_MEMALIGN
-#include <malloc.h>
+#ifdef HAVE_POSIX_MEMALIGN
+#include <stdlib.h>
#endif
+#include "common.h"
#include "prng.h"
#include "dSFMT.h"
@@ -40,18 +42,19 @@ static void tls_prng_deinit(void *ptr)
static void tls_prng_deinit_main()
{
tls_prng_deinit(pthread_getspecific(tls_prng_key));
+ UNUSED(pthread_setspecific(tls_prng_key, NULL));
}
static void tls_prng_init()
{
- (void) pthread_key_create(&tls_prng_key, tls_prng_deinit);
+ UNUSED(pthread_key_create(&tls_prng_key, tls_prng_deinit));
atexit(tls_prng_deinit_main); // Main thread cleanup
}
double tls_rand()
{
/* Setup PRNG state for current thread. */
- (void)pthread_once(&tls_prng_once, tls_prng_init);
+ UNUSED(pthread_once(&tls_prng_once, tls_prng_init));
/* Create PRNG state if not exists. */
dsfmt_t* s = pthread_getspecific(tls_prng_key);
@@ -83,19 +86,19 @@ double tls_rand()
}
/* Initialize PRNG state. */
-#ifdef HAVE_MEMALIGN
- s = memalign(16, sizeof(dsfmt_t));
+#ifdef HAVE_POSIX_MEMALIGN
+ if (posix_memalign((void **)&s, 16, sizeof(dsfmt_t)) != 0) {
+ fprintf(stderr, "error: PRNG: not enough memory\n");
+ return .0;
+ }
#else
- s = malloc(sizeof(dsfmt_t));
-#endif
- if (s == NULL) {
+ if ((s = malloc(sizeof(dsfmt_t))) == NULL) {
fprintf(stderr, "error: PRNG: not enough memory\n");
return .0;
- } else {
- dsfmt_init_gen_rand(s, seed);
- (void)pthread_setspecific(tls_prng_key, s);
}
-
+#endif
+ dsfmt_init_gen_rand(s, seed);
+ UNUSED(pthread_setspecific(tls_prng_key, s));
}
return dsfmt_genrand_close_open(s);
diff --git a/src/common/ref.c b/src/common/ref.c
index 3b9c033..a042665 100644
--- a/src/common/ref.c
+++ b/src/common/ref.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdio.h>
#include "ref.h"
diff --git a/src/common/slab/slab.c b/src/common/slab/slab.c
index 83d7ac5..e5f9f9a 100644
--- a/src/common/slab/slab.c
+++ b/src/common/slab/slab.c
@@ -12,7 +12,7 @@
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 <config.h>
#include <stdio.h>
@@ -71,7 +71,7 @@ static slab_depot_t _depot_g; /*! \brief Global slab depot. */
*/
static void* slab_depot_alloc(size_t bufsize)
{
- void *page = 0;
+ void *page = 0;
#ifdef MEM_SLAB_DEPOT
if (_depot_g.available) {
for (int i = _depot_g.available - 1; i > -1 ; --i) {
@@ -91,12 +91,14 @@ static void* slab_depot_alloc(size_t bufsize)
}
#else // MEM_SLAB_DEPOT
- if(posix_memalign(&page, SLAB_SZ, SLAB_SZ) == 0) {
- ((slab_t*)page)->bufsize = 0;
- } else {
- page = 0;
- }
+ UNUSED(bufsize);
+ if(posix_memalign(&page, SLAB_SZ, SLAB_SZ) == 0) {
+ ((slab_t*)page)->bufsize = 0;
+ } else {
+ page = 0;
+ }
#endif // MEM_SLAB_DEPOT
+ UNUSED(bufsize);
return page;
}
@@ -148,14 +150,14 @@ void __attribute__ ((constructor)) slab_init()
if (slab_size < 0) {
slab_size = SLAB_MINSIZE;
}
-
+
// Fetch page size
SLAB_SZ = (size_t)slab_size;
unsigned slab_logsz = fastlog2(SLAB_SZ);
// Compute slab page mask
SLAB_MASK = 0;
- for (int i = 0; i < slab_logsz; ++i) {
+ for (unsigned i = 0; i < slab_logsz; ++i) {
SLAB_MASK |= 1 << i;
}
SLAB_MASK = ~SLAB_MASK;
@@ -463,14 +465,8 @@ int slab_cache_init(slab_cache_t* cache, size_t bufsize)
return -1;
}
- cache->empty = 0;
+ memset(cache, 0, sizeof(slab_cache_t));
cache->bufsize = bufsize;
- cache->slabs_free = cache->slabs_full = 0;
- cache->color = 0;
-
- /* Initialize stats */
- cache->stat_allocs = cache->stat_frees = 0;
-
dbg_mem("%s: created cache of size %zu\n",
__func__, bufsize);
@@ -527,5 +523,3 @@ int slab_cache_reap(slab_cache_t* cache)
cache->empty = 0;
return count;
}
-
-
diff --git a/src/common/sockaddr.c b/src/common/sockaddr.c
index b4e75ee..4444343 100644
--- a/src/common/sockaddr.c
+++ b/src/common/sockaddr.c
@@ -14,10 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
#include "common/sockaddr.h"
@@ -26,7 +28,6 @@ int sockaddr_init(sockaddr_t *addr, int af)
{
/* Reset pointer. */
memset(addr, 0, sizeof(sockaddr_t));
- addr->family = -1;
/* Initialize address size. */
switch(af) {
@@ -44,42 +45,21 @@ int sockaddr_init(sockaddr_t *addr, int af)
return -1;
}
- /* Update pointer. */
- addr->family = af;
- return sockaddr_update(addr);
+ return 0;
}
int sockaddr_isvalid(sockaddr_t *addr)
{
- return addr && addr->family > -1;
+ return addr && (addr->len > 0);
}
int sockaddr_copy(sockaddr_t *dst, const sockaddr_t *src)
{
if (memcpy(dst, src, sizeof(sockaddr_t)) != NULL) {
- return sockaddr_update(dst);
+ return 0;
}
-
- return -1;
-}
-int sockaddr_update(sockaddr_t *addr)
-{
- /* Update internal pointer. */
- switch(addr->len) {
- case sizeof(struct sockaddr_in):
- addr->ptr = (struct sockaddr*)&addr->addr4;
- break;
-#ifndef DISABLE_IPV6
- case sizeof(struct sockaddr_in6):
- addr->ptr = (struct sockaddr*)&addr->addr6;
- break;
-#endif
- default:
- return -1;
- }
-
- return 0;
+ return -1;
}
int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port)
@@ -89,8 +69,6 @@ int sockaddr_set(sockaddr_t *dst, int family, const char* addr, int port)
}
/* Initialize. */
- dst->family = -1;
- dst->ptr = 0;
dst->len = 0;
sockaddr_init(dst, family);
@@ -127,7 +105,7 @@ int sockaddr_setprefix(sockaddr_t *dst, int prefix)
if (dst == NULL || prefix < 0) {
return -1;
}
-
+
return dst->prefix = prefix;
}
@@ -141,11 +119,7 @@ int sockaddr_tostr(const sockaddr_t *addr, char *dst, size_t size)
size_t minlen = INET_ADDRSTRLEN;
/* Check unsupported IPv6. */
-#ifdef DISABLE_IPV6
- if (addr->family == AF_INET6) {
- return -1;
- }
-#else
+#ifndef DISABLE_IPV6
minlen = INET6_ADDRSTRLEN;
#endif
@@ -159,15 +133,13 @@ int sockaddr_tostr(const sockaddr_t *addr, char *dst, size_t size)
dst[0] = '\0';
#else
/* Load IPv6 addr if default. */
- if (addr->family == AF_INET6) {
- inet_ntop(addr->family, &addr->addr6.sin6_addr,
- dst, size);
+ if (addr->len == sizeof(struct sockaddr_in6)) {
+ inet_ntop(AF_INET6, &addr->addr6.sin6_addr, dst, size);
}
#endif
/* Load IPv4 if set. */
- if (addr->family == AF_INET) {
- inet_ntop(addr->family, &addr->addr4.sin_addr,
- dst, size);
+ if (addr->len == sizeof(struct sockaddr_in)) {
+ inet_ntop(AF_INET, &addr->addr4.sin_addr, dst, size);
}
return 0;
@@ -179,16 +151,16 @@ int sockaddr_portnum(const sockaddr_t *addr)
return -1;
}
- switch(addr->family) {
+ switch(addr->len) {
/* IPv4 */
- case AF_INET:
+ case sizeof(struct sockaddr_in):
return ntohs(addr->addr4.sin_port);
break;
/* IPv6 */
#ifndef DISABLE_IPV6
- case AF_INET6:
+ case sizeof(struct sockaddr_in6):
return ntohs(addr->addr6.sin6_port);
break;
#endif
@@ -199,3 +171,23 @@ int sockaddr_portnum(const sockaddr_t *addr)
break;
}
}
+
+int sockaddr_family(const sockaddr_t *addr)
+{
+ switch(addr->len) {
+ case sizeof(struct sockaddr_in): return AF_INET; break;
+#ifndef DISABLE_IPV6
+ case sizeof(struct sockaddr_in6): return AF_INET6; break;
+#endif
+ default: return 0; break;
+ }
+}
+
+void sockaddr_prep(sockaddr_t *addr)
+{
+#ifndef DISABLE_IPV6
+ addr->len = sizeof(struct sockaddr_in6);
+#else
+ addr->len = sizeof(struct sockaddr_in);
+#endif
+}
diff --git a/src/common/sockaddr.h b/src/common/sockaddr.h
index 52e621c..84e2b70 100644
--- a/src/common/sockaddr.h
+++ b/src/common/sockaddr.h
@@ -37,16 +37,14 @@
/*! \brief Universal socket address. */
typedef struct sockaddr_t {
- int family; /*!< Address family. */
- short prefix; /*!< Address prefix. */
- struct sockaddr* ptr; /*!< Pointer to used sockaddr. */
- socklen_t len; /*!< Length of used sockaddr. */
union {
struct sockaddr_in addr4; /*!< IPv4 sockaddr. */
#ifndef DISABLE_IPV6
struct sockaddr_in6 addr6; /*!< IPv6 sockaddr. */
#endif
};
+ socklen_t len; /*!< Length of used sockaddr. */
+ short prefix; /*!< Address prefix. */
} sockaddr_t;
/* Subnet maximum prefix length. */
@@ -84,16 +82,6 @@ int sockaddr_init(sockaddr_t *addr, int af);
int sockaddr_isvalid(sockaddr_t *addr);
/*!
- * \brief Update internal pointers according to length.
- *
- * \param addr Socket address structure.
- *
- * \retval 0 on success.
- * \retval -1 on invalid size.
- */
-int sockaddr_update(sockaddr_t *addr);
-
-/*!
* \brief Copy socket address structure.
*
* \param dst Target address structure.
@@ -152,6 +140,19 @@ int sockaddr_tostr(const sockaddr_t *addr, char *dst, size_t size);
*/
int sockaddr_portnum(const sockaddr_t *addr);
+/*!
+ * \brief Return socket address family.
+ * \param addr Socket address structure.
+ * \return address family
+ */
+int sockaddr_family(const sockaddr_t *addr);
+
+/*!
+ * \brief Prepare to maximum largest size.
+ * \return KNOT_EOK
+ */
+void sockaddr_prep(sockaddr_t *addr);
+
#endif /* _KNOTD_SOCKADDR_H_ */
/*! @} */
diff --git a/src/common/tree.h b/src/common/tree.h
deleted file mode 100644
index efea65b..0000000
--- a/src/common/tree.h
+++ /dev/null
@@ -1,268 +0,0 @@
-/* tree.h -- AVL trees (in the spirit of BSD's 'queue.h') -*- C -*- */
-
-/* Copyright (c) 2005 Ian Piumarta
- *
- * 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, and/or sell copies of the
- * Software, and to permit persons to whom the Software is furnished to do so,
- * provided that the above copyright notice(s) and this permission notice appear
- * in all copies of the Software and that both the above copyright notice(s) and
- * this permission notice appear in supporting documentation.
- *
- * THE SOFTWARE IS PROVIDED 'AS IS'. USE ENTIRELY AT YOUR OWN RISK.
- */
-
-/* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
- * Evgenii M. Landis, 'An algorithm for the organization of information',
- * Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian). Also in Myron
- * J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
- *
- * An AVL tree is headed by pointers to the root node and to a function defining
- * the ordering relation between nodes. Each node contains an arbitrary payload
- * plus three fields per tree entry: the depth of the subtree for which it forms
- * the root and two pointers to child nodes (singly-linked for minimum space, at
- * the expense of direct access to the parent node given a pointer to one of the
- * children). The tree is rebalanced after every insertion or removal. The
- * tree may be traversed in two directions: forward (in-order left-to-right) and
- * reverse (in-order, right-to-left).
- *
- * Because of the recursive nature of many of the operations on trees it is
- * necessary to define a number of helper functions for each type of tree node.
- * The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
- * unique names according to the node_tag. This macro should be invoked,
- * thereby defining the necessary functions, once per node tag in the program.
- *
- * For details on the use of these macros, see the tree(3) manual page.
- */
-
-/* Downloaded from http://piumarta.com/software/tree/ */
-
-#ifndef __tree_h
-#define __tree_h
-
-
-#define TREE_DELTA_MAX 1
-
-#define TREE_ENTRY(type) \
- struct { \
- struct type *avl_left; \
- struct type *avl_right; \
- int avl_height; \
- }
-
-#define TREE_HEAD(name, type) \
- struct name { \
- struct type *th_root; \
- int (*th_cmp)(struct type *lhs, struct type *rhs); \
- }
-
-#define TREE_INITIALIZER(cmp) { 0, cmp }
-
-#define TREE_DELTA(self, field) \
- (( (((self)->field.avl_left) ? (self)->field.avl_left->field.avl_height : 0)) \
- - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
-
-/* Recursion prevents the following from being defined as macros. */
-
-#define TREE_DEFINE(node, field) \
- \
- struct node *TREE_BALANCE_##node##_##field(struct node *); \
- \
- struct node *TREE_ROTL_##node##_##field(struct node *self) \
- { \
- struct node *r= self->field.avl_right; \
- self->field.avl_right= r->field.avl_left; \
- r->field.avl_left= TREE_BALANCE_##node##_##field(self); \
- return TREE_BALANCE_##node##_##field(r); \
- } \
- \
- struct node *TREE_ROTR_##node##_##field(struct node *self) \
- { \
- struct node *l= self->field.avl_left; \
- self->field.avl_left= l->field.avl_right; \
- l->field.avl_right= TREE_BALANCE_##node##_##field(self); \
- return TREE_BALANCE_##node##_##field(l); \
- } \
- \
- struct node *TREE_BALANCE_##node##_##field(struct node *self) \
- { \
- int delta= TREE_DELTA(self, field); \
- \
- if (delta < -TREE_DELTA_MAX) \
- { \
- if (TREE_DELTA(self->field.avl_right, field) > 0) \
- self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right); \
- return TREE_ROTL_##node##_##field(self); \
- } \
- else if (delta > TREE_DELTA_MAX) \
- { \
- if (TREE_DELTA(self->field.avl_left, field) < 0) \
- self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left); \
- return TREE_ROTR_##node##_##field(self); \
- } \
- self->field.avl_height= 0; \
- if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height)) \
- self->field.avl_height= self->field.avl_left->field.avl_height; \
- if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height)) \
- self->field.avl_height= self->field.avl_right->field.avl_height; \
- self->field.avl_height += 1; \
- return self; \
- } \
- \
- struct node *TREE_INSERT_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
- { \
- if (!self) \
- return elm; \
- if (compare(elm, self) < 0) \
- self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare); \
- else \
- self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare); \
- return TREE_BALANCE_##node##_##field(self); \
- } \
- \
- struct node *TREE_FIND_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
- { \
- if (!self) \
- return 0; \
- if (compare(elm, self) == 0) \
- return self; \
- if (compare(elm, self) < 0) \
- return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare); \
- else \
- return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare); \
- } \
- \
- int TREE_FIND_LESS_EQUAL_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs), struct node **found, struct node **prev) \
- { \
- if (!self) \
- return 0; \
- if (compare(elm, self) == 0) { \
- *found = self; \
- return 1; \
- } \
- if (compare(elm, self) < 0) { \
- int ret = TREE_FIND_LESS_EQUAL_##node##_##field(self->field.avl_left, elm, compare, found, prev); \
- if (ret == 0 && *prev == NULL) { \
- *prev = self; \
- ret = -1; \
- } \
- return ret; \
- } else { \
- *found = self; \
- *prev = self; \
- return TREE_FIND_LESS_EQUAL_##node##_##field(self->field.avl_right, elm, compare, found, prev); \
- } \
- } \
- \
- struct node *TREE_MOVE_RIGHT_##node##_##field(struct node *self, struct node *rhs) \
- { \
- if (!self) \
- return rhs; \
- self->field.avl_right= TREE_MOVE_RIGHT_##node##_##field(self->field.avl_right, rhs); \
- return TREE_BALANCE_##node##_##field(self); \
- } \
- \
- struct node *TREE_REMOVE_##node##_##field \
- (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs)) \
- { \
- if (!self) return 0; \
- \
- if (compare(elm, self) == 0) \
- { \
- struct node *tmp= TREE_MOVE_RIGHT_##node##_##field(self->field.avl_left, self->field.avl_right); \
- self->field.avl_left= 0; \
- self->field.avl_right= 0; \
- return tmp; \
- } \
- if (compare(elm, self) < 0) \
- self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare); \
- else \
- self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare); \
- return TREE_BALANCE_##node##_##field(self); \
- } \
- \
- void TREE_FORWARD_APPLY_ALL_##node##_##field \
- (struct node *self, void (*function)(struct node *node, void *data), void *data) \
- { \
- if (self) \
- { \
- TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
- function(self, data); \
- TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
- } \
- } \
- \
- void TREE_REVERSE_APPLY_ALL_##node##_##field \
- (struct node *self, void (*function)(struct node *node, void *data), void *data) \
- { \
- if (self) \
- { \
- TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
- function(self, data); \
- TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
- } \
- } \
- \
- void TREE_POST_ORDER_APPLY_ALL_##node##_##field \
- (struct node *self, void (*function)(struct node *node, void *data), void *data) \
- { \
- if (self) \
- { \
- TREE_POST_ORDER_APPLY_ALL_##node##_##field(self->field.avl_left, function, data); \
- TREE_POST_ORDER_APPLY_ALL_##node##_##field(self->field.avl_right, function, data); \
- function(self, data); \
- } \
- } \
- \
- void TREE_REVERSE_APPLY_POST_ALL_##node##_##field \
- (struct node *self, void (*function)(struct node *node, void *data), void *data) \
- { \
- if (self) \
- { \
- TREE_REVERSE_APPLY_POST_ALL_##node##_##field(self->field.avl_right, function, data); \
- TREE_REVERSE_APPLY_POST_ALL_##node##_##field(self->field.avl_left, function, data); \
- function(self, data); \
- } \
-}
-
-#define TREE_INSERT(head, node, field, elm) \
- ((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
-
-#define TREE_FIND(head, node, field, elm) \
- (TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
-
-#define TREE_FIND_LESS_EQUAL(head, node, field, elm, found, prev) \
- (TREE_FIND_LESS_EQUAL_##node##_##field((head)->th_root, (elm), (head)->th_cmp, found, prev))
-
-#define TREE_REMOVE(head, node, field, elm) \
- ((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
-
-#define TREE_DEPTH(head, field) \
- ((head)->th_root->field.avl_height)
-
-#define TREE_FORWARD_APPLY(head, node, field, function, data) \
- TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
-
-#define TREE_REVERSE_APPLY(head, node, field, function, data) \
- TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
-
-#define TREE_POST_ORDER_APPLY(head, node, field, function, data) \
- TREE_POST_ORDER_APPLY_ALL_##node##_##field((head)->th_root, function, data)
-
-#define TREE_REVERSE_APPLY_POST(head, node, field, function, data) \
- TREE_REVERSE_APPLY_POST_ALL_##node##_##field((head)->th_root, function, data)
-
-#define TREE_INIT(head, cmp) do { \
- (head)->th_root= 0; \
- (head)->th_cmp= (cmp); \
- } while (0)
-
-
-#endif /* __tree_h */
diff --git a/src/config.h.in b/src/config.h.in
index a6f0975..656c8ef 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -9,15 +9,15 @@
/* Enable verbose debugging messages. */
#undef DEBUG_ENABLE_VERBOSE
-/* DSFMT parameters. */
+/* DSFMT parameters */
#undef DSFMT_MEXP
+/* microseconds in log messages */
+#undef ENABLE_MICROSECONDS_LOG
+
/* recvmmsg enabled */
#undef ENABLE_RECVMMSG
-/* Define to 1 if you have the <arpa/inet.h> header file. */
-#undef HAVE_ARPA_INET_H
-
/* Define to 1 if you have the <arpa/nameser.h> header file. */
#undef HAVE_ARPA_NAMESER_H
@@ -42,20 +42,11 @@
/* Define to 1 if you have the `epoll_wait' function. */
#undef HAVE_EPOLL_WAIT
-/* Define to 1 if you have the <ev.h> header file. */
-#undef HAVE_EV_H
-
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
+/* Define to 1 if you have the `fgetln' function. */
+#undef HAVE_FGETLN
-/* Define to 1 if you have the `fork' function. */
-#undef HAVE_FORK
-
-/* Define to 1 if you have the `gethostbyname' function. */
-#undef HAVE_GETHOSTBYNAME
-
-/* Define to 1 if you have the `getpagesize' function. */
-#undef HAVE_GETPAGESIZE
+/* Define to 1 if you have the `getline' function. */
+#undef HAVE_GETLINE
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
@@ -66,39 +57,15 @@
/* Define to 1 if you have the `kqueue' function. */
#undef HAVE_KQUEUE
-/* ldns present */
-#undef HAVE_LDNS
-
-/* Define to 1 if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
-
/* Define to 1 if you have the `madvise' function. */
#undef HAVE_MADVISE
-/* Define to 1 if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
-/* Define to 1 if you have the `memalign' function. */
-#undef HAVE_MEMALIGN
-
-/* Define to 1 if you have the `memmove' function. */
-#undef HAVE_MEMMOVE
-
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
-/* Define to 1 if you have the `memset' function. */
-#undef HAVE_MEMSET
-
-/* Define to 1 if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
/* Support mmx instructions */
#undef HAVE_MMX
-/* Define to 1 if you have the `munmap' function. */
-#undef HAVE_MUNMAP
-
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
@@ -111,6 +78,9 @@
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
+/* Define to 1 if you have the `posix_memalign' function. */
+#undef HAVE_POSIX_MEMALIGN
+
/* Define to 1 if you have the `pselect' function. */
#undef HAVE_PSELECT
@@ -138,12 +108,6 @@
/* Define to 1 if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
-/* Define to 1 if you have the `socket' function. */
-#undef HAVE_SOCKET
-
-/* Define to 1 if you have the `sqrt' function. */
-#undef HAVE_SQRT
-
/* Support SSE (Streaming SIMD Extensions) instructions */
#undef HAVE_SSE
@@ -156,54 +120,21 @@
/* Support SSSE3 (Supplemental Streaming SIMD Extensions 3) instructions */
#undef HAVE_SSSE3
-/* Define to 1 if stdbool.h conforms to C99. */
-#undef HAVE_STDBOOL_H
-
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
-/* Define to 1 if you have the `strcasecmp' function. */
-#undef HAVE_STRCASECMP
-
-/* Define to 1 if you have the `strchr' function. */
-#undef HAVE_STRCHR
-
-/* Define to 1 if you have the `strdup' function. */
-#undef HAVE_STRDUP
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
-/* Define to 1 if you have the `strncasecmp' function. */
-#undef HAVE_STRNCASECMP
-
-/* Define to 1 if you have the `strtol' function. */
-#undef HAVE_STRTOL
-
-/* Define to 1 if you have the `strtoul' function. */
-#undef HAVE_STRTOUL
-
-/* Define to 1 if you have the <syslog.h> header file. */
-#undef HAVE_SYSLOG_H
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#undef HAVE_SYS_PARAM_H
-
/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
-/* Define to 1 if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
@@ -213,29 +144,18 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
-/* Define to 1 if you have the <urcu.h> header file. */
-#undef HAVE_URCU_H
-
-/* Define to 1 if you have the `vfork' function. */
-#undef HAVE_VFORK
-
-/* Define to 1 if you have the <vfork.h> header file. */
-#undef HAVE_VFORK_H
-
-/* Define to 1 if `fork' works. */
-#undef HAVE_WORKING_FORK
-
-/* Define to 1 if `vfork' works. */
-#undef HAVE_WORKING_VFORK
-
-/* Define to 1 if the system has the type `_Bool'. */
-#undef HAVE__BOOL
+/* Define to 1 or 0, depending whether the compiler supports simple visibility
+ declarations. */
+#undef HAVE_VISIBILITY
/* Server debug. */
#undef KNOTD_SERVER_DEBUG
@@ -271,6 +191,9 @@
*/
#undef LT_OBJDIR
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
/* Name of package */
#undef PACKAGE
@@ -334,31 +257,12 @@
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
-/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
- <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
- #define below would cause a syntax error. */
-#undef _UINT32_T
-
-/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
- <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
- #define below would cause a syntax error. */
-#undef _UINT64_T
-
-/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
- <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
- #define below would cause a syntax error. */
-#undef _UINT8_T
-
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif
-/* Define to the type of a signed integer type of width exactly 64 bits if
- such a type exists and the standard includes do not define it. */
-#undef int64_t
-
/* Define to `int' if <sys/types.h> does not define. */
#undef pid_t
@@ -367,22 +271,3 @@
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
-
-/* Define to the type of an unsigned integer type of width exactly 16 bits if
- such a type exists and the standard includes do not define it. */
-#undef uint16_t
-
-/* Define to the type of an unsigned integer type of width exactly 32 bits if
- such a type exists and the standard includes do not define it. */
-#undef uint32_t
-
-/* Define to the type of an unsigned integer type of width exactly 64 bits if
- such a type exists and the standard includes do not define it. */
-#undef uint64_t
-
-/* Define to the type of an unsigned integer type of width exactly 8 bits if
- such a type exists and the standard includes do not define it. */
-#undef uint8_t
-
-/* Define as `fork' if `vfork' does not work. */
-#undef vfork
diff --git a/src/knot.service b/src/knot.service
deleted file mode 100644
index 36864d0..0000000
--- a/src/knot.service
+++ /dev/null
@@ -1,13 +0,0 @@
-[Unit]
-Description=Knot DNS daemon
-After=syslog.target network.target auditd.service
-
-[Service]
-EnvironmentFile=/etc/sysconfig/knot
-ExecReload=/usr/sbin/knotc reload
-ExecStart=/usr/sbin/knotd $KNOTARGS
-Restart=on-abort
-
-[Install]
-WantedBy=multi-user.target
-
diff --git a/src/knot.spec b/src/knot.spec
deleted file mode 100644
index 5856aab..0000000
--- a/src/knot.spec
+++ /dev/null
@@ -1,91 +0,0 @@
-Summary: KNOT DNS daemon
-Name: knot
-Version: 0.9.1
-Release: 1
-License: GPL
-Group: Networking/Daemons
-Source: http://public.nic.cz/files/knot-dns/knot-%{version}.tar.gz
-Source1: %{name}.sysconfig
-Source2: %{name}.service
-Patch: %{name}.diff
-Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-build
-Url: http://www.knot-dns.cz
-BuildRequires: flex userspace-rcu-devel openssl-devel bison
-
-%description
-KNOT DNS is a high-performance authoritative DNS server implementation.
-
-%prep
-%setup -n %{name}-%{version}
-%patch -p1
-
-
-%build
-./configure --prefix=%{_prefix} --sysconfdir=%{_sysconfdir}/%{name} --localstatedir=%{_var}/lib --libexecdir=%{_libexecdir}/%{name}
-make -C samples %{name}.sample.conf
-make
-
-
-%install
-rm -rf %{buildroot}/*
-make install prefix=%{buildroot}/%{_prefix} sysconfdir=%{buildroot}/%{_sysconfdir}/%{name} localstatedir=%{buildroot}/%{_var}/lib mandir=%{buildroot}/%{_mandir} libexecdir=%{buildroot}/%{_libexecdir}/%{name}
-
-install -d %{buildroot}/%{_sysconfdir}/sysconfig
-install $RPM_SOURCE_DIR/%{name}.sysconfig %{buildroot}/%{_sysconfdir}/sysconfig/%{name}
-install -d %{buildroot}/%{_var}/lib/%{name}
-install -d %{buildroot}/lib/systemd/system/
-install $RPM_SOURCE_DIR/%{name}.service %{buildroot}/lib/systemd/system/%{name}.service
-
-%post
-# run after an installation
-if [ $1 -eq 1 ] ; then
- # Initial installation
- /bin/systemctl daemon-reload >/dev/null 2>&1 || :
-fi
-
-%preun
-# run before a package is removed
-if [ $1 -eq 0 ]; then
- /bin/systemctl --no-reload disable %{name}.service >/dev/null 2>&1 || :
- /bin/systemctl stop %{name}.service > /dev/null 2>&1 || :
-fi
-
-%postun
-# run after a package is removed
-/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-if [ $1 -ge 1 ]; then
- /bin/systemctl try-restart %{name}.service >/dev/null 2>&1 || :
-fi
-
-%triggerun -- knot < 0.9
-# Save the current service runlevel info
-# User must manually run systemd-sysv-convert --apply %{name}
-# to migrate them to systemd targets
-/usr/bin/systemd-sysv-convert --save %{name}
-
-/sbin/chkconfig --del %{name} >/dev/null 2>&1 || :
-/bin/systemctl try-restart %{name}.service >/dev/null 2>&1 || :
-/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-
-
-
-%files
-%defattr(-,root,root,-)
-%config %attr(644,root,root) %{_sysconfdir}/%{name}/*
-%{_sbindir}/*
-%{_libexecdir}/%{name}/*
-%dir %{_var}/lib/%{name}/
-%doc %{_mandir}/man8/*
-%attr(0644,root,root) /lib/systemd/system/%{name}.service
-%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
-
-
-
-%changelog
-* Mon Jan 16 2012 - feela@network.cz
-- Support for systemd.
-- Specfile cleanup
-
-* Thu Nov 3 2011 - feela@network.cz
-- Initial version
-
diff --git a/src/knot.sysconfig b/src/knot.sysconfig
deleted file mode 100644
index 99daeba..0000000
--- a/src/knot.sysconfig
+++ /dev/null
@@ -1,4 +0,0 @@
-# Settings for the KNOT DNS daemon.
-# KNOTARGS= : any extra command-line startup arguments for knot dns
-KNOTARGS=
-
diff --git a/src/knot/common.h b/src/knot/common.h
deleted file mode 100644
index ec70f4a..0000000
--- a/src/knot/common.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright (C) 2011 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 common.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Common macros, includes and utilities.
- *
- * \addtogroup utils
- * @{
- */
-
-#ifndef _KNOTD_COMMON_H_
-#define _KNOTD_COMMON_H_
-
-#include <signal.h>
-#include <stdint.h>
-#include <config.h>
-
-/*
- * Common types and constants.
- */
-
-#ifndef UINT_DEFINED
-typedef unsigned int uint; /*!< \brief Unsigned. */
-#define UINT_DEFINED
-#endif
-
-#define PROJECT_EXEC SBINDIR "/" "knotd" /*!< \brief Project executable. */
-#define ZONEPARSER_EXEC LIBEXECDIR "/" "knot-zcompile" /*!< \brief Zoneparser executable. */
-#define PID_FILE "knot.pid" /*!< \brief Server PID file name. */
-
-/*
- * Server.
- */
-
-#define CPU_ESTIMATE_MAGIC 0 /*!< \brief Extra threads to the number of cores.*/
-#define DEFAULT_THR_COUNT 2 /*!< \brief Default thread count. */
-#define DEFAULT_PORT 53531 /*!< \brief Default interface port. */
-#define TCP_BACKLOG_SIZE 5 /*!< \brief TCP listen backlog size. */
-#define XFR_THREADS_COUNT 3 /*!< \brief Number of threads for XFR handler. */
-#define RECVMMSG_BATCHLEN 32 /*!< \brief Define for recvmmsg() batch size. */
-
-///*! \brief If defined, zone structures will use hash table for lookup. */
-//#define COMPRESSION_PEDANTIC
-
-///*!
-// * \brief If defined, tests will use ldns library to parse sample data.
-// *
-// * If not defined, some tests will be disabled.
-// */
-//#define TEST_WITH_LDNS
-
-///*! \brief If defined, the statistics module will be enabled. */
-//#define STAT_COMPILE
-
-
-#ifdef HAVE_LDNS
-#define TEST_WITH_LDNS
-#endif
-
-/*
- * Common includes.
- */
-
-#include "common/latency.h"
-#include "common/print.h"
-#include "common/log.h"
-#include "common/errcode.h"
-#include "knot/other/debug.h"
-
-/*! \brief Eliminate compiler warning with unused parameters. */
-#define UNUSED(param) (void)(param)
-
-/* Optimisation macros. */
-#ifndef knot_likely
-/*! \brief Optimize for x to be true value. */
-#define knot_likely(x) __builtin_expect((x),1)
-#endif
-#ifndef knot_unlikely
-/*! \brief Optimize for x to be false value. */
-#define knot_unlikely(x) __builtin_expect((x),0)
-#endif
-
-/*! \todo Refactor theese. We should have an allocator function handling this.*/
-#ifndef ERR_ALLOC_FAILED
-#define ERR_ALLOC_FAILED fprintf(stderr, "Allocation failed at %s:%d (%s)\n", \
- __FILE__, __LINE__, PACKAGE_STRING)
-#endif
-
-#ifndef CHECK_ALLOC_LOG
-#define CHECK_ALLOC_LOG(var, ret) \
- do { \
- if ((var) == NULL) { \
- ERR_ALLOC_FAILED; \
- return (ret); \
- } \
- } while (0)
-#endif
-
-#ifndef CHECK_ALLOC
-#define CHECK_ALLOC(var, ret) \
- do { \
- if ((var) == NULL) { \
- return (ret); \
- } \
- } while (0)
-#endif
-
-/* Workarounds for clock_gettime() not available on some platforms. */
-#ifdef HAVE_CLOCK_GETTIME
-#define time_now(x) clock_gettime(CLOCK_MONOTONIC, (x))
-typedef struct timespec timev_t;
-#elif HAVE_GETTIMEOFDAY
-#define time_now(x) gettimeofday((x), NULL)
-typedef struct timeval timev_t;
-#else
-#error Neither clock_gettime() nor gettimeofday() found. At least one is required.
-#endif
-
-#endif /* _KNOTD_COMMON_H_ */
-
-/*! @} */
diff --git a/src/knot/conf/cf-lex.l b/src/knot/conf/cf-lex.l
index 5a53917..20bdcc3 100644
--- a/src/knot/conf/cf-lex.l
+++ b/src/knot/conf/cf-lex.l
@@ -1,3 +1,18 @@
+/* Copyright (C) 2011 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 cf-lex.l
*
@@ -9,18 +24,22 @@
*/
%{
+#include <config.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <stdbool.h>
#include "common/sockaddr.h"
#include "knot/conf/conf.h"
+#include "knot/conf/includes.h"
+#include "knot/conf/extra.h"
#include "common/log.h"
#include "libknotd_la-cf-parse.h" /* Automake generated header. */
/* Imported symbols. */
#define lval (yylval->tok)
-extern void cf_error(void *scanner, const char *msg);
+extern void cf_error(void *scanner, const char *format, ...);
extern int (*cf_read_hook)(char *buf, size_t nbytes);
void switch_input(const char *str, void *scanner)
{
@@ -55,6 +74,9 @@ int hex2bin(const char* src, char *dst, size_t len) {
%option yylineno
%option prefix = "cf_"
%option outfile = "lex.yy.c"
+%option extra-type = "conf_extra_t *"
+
+%x include
ALPHA [a-zA-Z_]
DIGIT [0-9]
@@ -66,14 +88,16 @@ BLANK [ \t\n]
\#.*\n /* Ignore comments */;
{BLANK}+ /* Ignore whitespace */;
[\!\$\%\^\&\*\(\)\/\+\-\@\{\}\;\,] { return yytext[0]; }
-system { lval.t = yytext; return SYSTEM; }
+system { lval.t = yytext; return SYSTEM; }
identity { lval.t = yytext; return IDENTITY; }
+hostname { lval.t = yytext; return HOSTNAME; }
version { lval.t = yytext; return SVERSION; }
nsid { lval.t = yytext; return NSID; }
storage { lval.t = yytext; return STORAGE; }
key { lval.t = yytext; return KEY; }
keys { lval.t = yytext; return KEYS; }
remotes { lval.t = yytext; return REMOTES; }
+groups { lval.t = yytext; return GROUPS; }
zones { lval.t = yytext; return ZONES; }
file { lval.t = yytext; return FILENAME; }
@@ -91,6 +115,7 @@ notify-out { lval.t = yytext; return NOTIFY_OUT; }
workers { lval.t = yytext; return WORKERS; }
user { lval.t = yytext; return USER; }
pidfile { lval.t = yytext; return PIDFILE; }
+rundir { lval.t = yytext; return RUNDIR; }
ixfr-from-differences { lval.t = yytext; return BUILD_DIFFS; }
max-conn-idle { lval.t = yytext; return MAX_CONN_IDLE; }
max-conn-handshake { lval.t = yytext; return MAX_CONN_HS; }
@@ -98,6 +123,7 @@ max-conn-reply { lval.t = yytext; return MAX_CONN_REPLY; }
rate-limit { lval.t = yytext; return RATE_LIMIT; }
rate-limit-size { lval.t = yytext; return RATE_LIMIT_SIZE; }
rate-limit-slip { lval.t = yytext; return RATE_LIMIT_SLIP; }
+transfers { lval.t = yytext; return TRANSFERS; }
interfaces { lval.t = yytext; return INTERFACES; }
address { lval.t = yytext; return ADDRESS; }
@@ -133,6 +159,8 @@ on|off {
return BOOL;
}
+include BEGIN(include);
+
{DIGIT}+[smhd] {
size_t mpos = strlen(yytext) - 1;
char multiplier = yytext[mpos];
@@ -242,7 +270,7 @@ on|off {
}
}
}
-
+
return HEXSTR;
}
@@ -268,7 +296,49 @@ hmac-sha512 { lval.alg = KNOT_TSIG_ALG_HMAC_SHA512; return TSIG_ALGO_NAME; }
}
: /* Optional : in assignments. */;
-<<EOF>> return END;
-%%
+<<EOF>> {
+ char *name = conf_includes_pop(yyextra->includes);
+ free(name);
+ yypop_buffer_state(yyscanner);
+ if (!YY_CURRENT_BUFFER)
+ return END;
+}
+
+<include>{BLANK}+
+<include>["][^"\n]*["] {
+ BEGIN(INITIAL);
+
+ // silently skip includes if there was a former error
+ if (yyextra->error) {
+ return END;
+ }
+ // remove quotes
+ yytext += 1;
+ yyleng -= 2;
+ yytext[yyleng] = '\0';
+
+ if (!conf_includes_push(yyextra->includes, yytext)) {
+ cf_error(yyscanner, "includes nested too deeply");
+ return END;
+ }
+
+ // retrieved relative to previous config
+ char *filename = conf_includes_top(yyextra->includes);
+
+ FILE *included = fopen(filename, "r");
+ if (!included) {
+ cf_error(yyscanner, "cannot open file '%s'", filename);
+ conf_includes_pop(yyextra->includes);
+ free(filename);
+ return END;
+ }
+
+ YY_BUFFER_STATE bs = yy_create_buffer(included, YY_BUF_SIZE, yyscanner);
+ yypush_buffer_state(bs, yyscanner);
+}
+
+<include>["][^"\n]*\n cf_error(yyscanner, "Unterminated string.");
+
+%%
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index ad5659e..663adad 100644
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -1,3 +1,18 @@
+/* Copyright (C) 2011 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 cf-parse.y
*
@@ -7,6 +22,7 @@
*/
%{
/* Headers */
+#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -14,15 +30,17 @@
#include <grp.h>
#include "common/sockaddr.h"
#include "libknot/dname.h"
+#include "libknot/binary.h"
#include "knot/conf/conf.h"
#include "libknotd_la-cf-parse.h" /* Automake generated header. */
extern int cf_lex (YYSTYPE *lvalp, void *scanner);
-extern void cf_error(void *scanner, const char *msg);
+extern void cf_error(void *scanner, const char *format, ...);
extern conf_t *new_config;
static conf_iface_t *this_iface = 0;
static conf_iface_t *this_remote = 0;
static conf_zone_t *this_zone = 0;
+static conf_group_t *this_group = 0;
static list *this_list = 0;
static conf_log_t *this_log = 0;
static conf_log_map_t *this_logmap = 0;
@@ -47,14 +65,31 @@ static void conf_start_iface(void *scanner, char* ifname)
++new_config->ifaces_count;
}
+static conf_iface_t *conf_get_remote(const char *name)
+{
+ conf_iface_t *remote;
+ WALK_LIST (remote, new_config->remotes) {
+ if (strcmp(remote->name, name) == 0) {
+ return remote;
+ }
+ }
+
+ return NULL;
+}
+
static void conf_start_remote(void *scanner, char *remote)
{
+ if (conf_get_remote(remote) != NULL) {
+ cf_error(scanner, "remote '%s' already defined", remote);
+ return;
+ }
+
this_remote = malloc(sizeof(conf_iface_t));
if (this_remote == NULL) {
cf_error(scanner, "not enough memory when allocating remote");
return;
}
-
+
memset(this_remote, 0, sizeof(conf_iface_t));
this_remote->name = remote;
add_tail(&new_config->remotes, &this_remote->n);
@@ -71,67 +106,168 @@ static void conf_remote_set_via(void *scanner, char *item) {
break;
}
}
-
+
/* Check */
if (!found) {
- char buf[512];
- snprintf(buf, sizeof(buf), "interface '%s' is not defined", item);
- cf_error(scanner, buf);
+ cf_error(scanner, "interface '%s' is not defined", item);
} else {
sockaddr_set(&this_remote->via, found->family, found->address, 0);
}
}
-static void conf_acl_item(void *scanner, char *item)
+static conf_group_t *conf_get_group(const char *name)
{
- /* Find existing node in remotes. */
- node* r = 0; conf_iface_t* found = 0;
- WALK_LIST (r, new_config->remotes) {
- if (strcmp(((conf_iface_t*)r)->name, item) == 0) {
- found = (conf_iface_t*)r;
- break;
- }
- }
+ conf_group_t *group;
+ WALK_LIST (group, new_config->groups) {
+ if (strcmp(group->name, name) == 0) {
+ return group;
+ }
+ }
- /* Append to list if found. */
- if (!found) {
- char buf[512];
- snprintf(buf, sizeof(buf), "remote '%s' is not defined", item);
- cf_error(scanner, buf);
- } else {
- /* check port if xfrin/notify-out */
- if (this_list == &this_zone->acl.xfr_in ||
- this_list == &this_zone->acl.notify_out) {
- if (found->port == 0) {
- cf_error(scanner, "remote specified for XFR/IN or NOTIFY/OUT "
- " needs to have valid port!");
- free(item);
- return;
- }
+ return NULL;
+}
+
+static void conf_start_group(void *scanner, char *name)
+{
+ conf_group_t *group = conf_get_group(name);
+ if (group) {
+ cf_error(scanner, "group '%s' already defined", name);
+ return;
+ }
+
+ if (conf_get_remote(name) != NULL) {
+ cf_error(scanner, "group name '%s' conflicts with remote name",
+ name);
+ free(name);
+ return;
+ }
+
+ /* Add new group. */
+
+ group = calloc(1, sizeof(conf_group_t));
+ if (!group) {
+ cf_error(scanner, "out of memory");
+ free(name);
+ return;
+ }
+
+ group->name = name;
+ init_list(&group->remotes);
+
+ add_tail(&new_config->groups, &group->n);
+ this_group = group;
+}
+
+static void conf_add_member_into_group(void *scanner, char *name)
+{
+ if (!this_group) {
+ cf_error(scanner, "parser error, variable 'this_group' null");
+ free(name);
+ return;
+ }
+
+ if (conf_get_remote(name) == NULL) {
+ cf_error(scanner, "remote '%s' is not defined", name);
+ free(name);
+ return;
+ }
+
+ // add the remote into the group while silently ignoring duplicates
+
+ conf_group_remote_t *remote;
+ node *n;
+ WALK_LIST (n, this_group->remotes) {
+ remote = (conf_group_remote_t *)n;
+ if (strcmp(remote->name, name) == 0) {
+ free(name);
+ return;
+ }
}
- conf_remote_t *remote = malloc(sizeof(conf_remote_t));
+
+ remote = calloc(1, sizeof(conf_group_remote_t));
+ remote->name = name;
+ add_tail(&this_group->remotes, &remote->n);
+}
+
+static bool set_remote_or_group(void *scanner, char *name,
+ void (*install)(void *, conf_iface_t *))
+{
+ // search remotes
+
+ conf_iface_t *remote = conf_get_remote(name);
+ if (remote) {
+ install(scanner, remote);
+ return true;
+ }
+
+ // search groups
+
+ conf_group_t *group = conf_get_group(name);
+ if (group) {
+ conf_group_remote_t *group_remote;
+ WALK_LIST (group_remote, group->remotes) {
+ remote = conf_get_remote(group_remote->name);
+ if (!remote)
+ continue;
+ install(scanner, remote);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+static void conf_acl_item_install(void *scanner, conf_iface_t *found)
+{
+ // silently skip duplicates
+
+ conf_remote_t *remote;
+ WALK_LIST (remote, *this_list) {
+ if (remote->remote == found) {
+ return;
+ }
+ }
+
+ // additional check for transfers
+
+ if ((this_list == &this_zone->acl.xfr_in ||
+ this_list == &this_zone->acl.notify_out) && found->port == 0)
+ {
+ cf_error(scanner, "remote specified for XFR/IN or "
+ "NOTIFY/OUT needs to have valid port!");
+ return;
+ }
+
+ // add into the list
+
+ remote = malloc(sizeof(conf_remote_t));
if (!remote) {
- cf_error(scanner, "out of memory");
- } else {
- remote->remote = found;
- add_tail(this_list, &remote->n);
+ cf_error(scanner, "out of memory");
+ return;
}
- }
- /* Free text token. */
- free(item);
- }
+ remote->remote = found;
+ add_tail(this_list, &remote->n);
+}
+
+static void conf_acl_item(void *scanner, char *item)
+{
+ if (!set_remote_or_group(scanner, item, conf_acl_item_install)) {
+ cf_error(scanner, "remote or group '%s' not defined", item);
+ }
+
+ free(item);
+}
static int conf_key_exists(void *scanner, char *item)
{
/* Find existing node in keys. */
knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item), 0);
- char buf[512];
conf_key_t* r = 0;
WALK_LIST (r, new_config->keys) {
if (knot_dname_compare(r->k.name, sample) == 0) {
- snprintf(buf, sizeof(buf), "key '%s' is already defined", item);
- cf_error(scanner, buf);
+ cf_error(scanner, "key '%s' is already defined", item);
knot_dname_free(&sample);
return 1;
}
@@ -141,14 +277,14 @@ static int conf_key_exists(void *scanner, char *item)
return 0;
}
-static int conf_key_add(void *scanner, knot_key_t **key, char *item)
+static int conf_key_add(void *scanner, knot_tsig_key_t **key, char *item)
{
/* Reset */
*key = 0;
-
+
/* Find in keys */
knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item), 0);
-
+
conf_key_t* r = 0;
WALK_LIST (r, new_config->keys) {
if (knot_dname_compare(r->k.name, sample) == 0) {
@@ -158,9 +294,7 @@ static int conf_key_add(void *scanner, knot_key_t **key, char *item)
}
}
- char buf[512];
- snprintf(buf, sizeof(buf), "key '%s' is not defined", item);
- cf_error(scanner, buf);
+ cf_error(scanner, "key '%s' is not defined", item);
knot_dname_free(&sample);
return 1;
}
@@ -194,8 +328,14 @@ static void conf_zone_start(void *scanner, char *name) {
this_zone->name = name; /* Already FQDN */
}
+ /* Initialize ACL lists. */
+ init_list(&this_zone->acl.xfr_in);
+ init_list(&this_zone->acl.xfr_out);
+ init_list(&this_zone->acl.notify_in);
+ init_list(&this_zone->acl.notify_out);
+ init_list(&this_zone->acl.update_in);
+
/* Check domain name. */
- char buf[512];
knot_dname_t *dn = NULL;
if (this_zone->name != NULL) {
dn = knot_dname_new_from_str(this_zone->name, nlen, 0);
@@ -207,40 +347,30 @@ static void conf_zone_start(void *scanner, char *name) {
cf_error(scanner, "invalid zone origin");
} else {
/* Check for duplicates. */
- if (gen_tree_find(new_config->zone_tree, dn) != NULL) {
- snprintf(buf, sizeof(buf), "zone '%s' is already present, "
- "refusing to duplicate", this_zone->name);
+ if (hattrie_tryget(new_config->names, (const char*)dn->name, dn->size) != NULL) {
+ cf_error(scanner, "zone '%s' is already present, refusing to "
+ "duplicate", this_zone->name);
knot_dname_free(&dn);
free(this_zone->name);
this_zone->name = NULL;
/* Must not free, some versions of flex might continue after error and segfault.
* free(this_zone); this_zone = NULL;
*/
- cf_error(scanner, buf);
return;
}
/* Directly discard dname, won't be needed. */
add_tail(&new_config->zones, &this_zone->n);
- gen_tree_add(new_config->zone_tree, dn, NULL); /* Will hold reference. */
+ *hattrie_get(new_config->names, (const char*)dn->name, dn->size) = (void *)1;
++new_config->zones_count;
-
- /* Initialize ACL lists. */
- init_list(&this_zone->acl.xfr_in);
- init_list(&this_zone->acl.xfr_out);
- init_list(&this_zone->acl.notify_in);
- init_list(&this_zone->acl.notify_out);
- init_list(&this_zone->acl.update_in);
+ knot_dname_free(&dn);
}
}
static int conf_mask(void* scanner, int nval, int prefixlen) {
if (nval < 0 || nval > prefixlen) {
- char buf[512];
- snprintf(buf, sizeof(buf), "IPv%c subnet prefix '%d' is "
- "out of range <0,%d>",
+ cf_error(scanner, "IPv%c subnet prefix '%d' is out of range <0,%d>",
prefixlen == IPV4_PREFIXLEN ? '4' : '6', nval, prefixlen);
- cf_error(scanner, buf);
return prefixlen; /* single host */
}
return nval;
@@ -258,7 +388,7 @@ static int conf_mask(void* scanner, int nval, int prefixlen) {
char *t;
long i;
size_t l;
- tsig_algorithm_t alg;
+ knot_tsig_algorithm_t alg;
} tok;
}
@@ -270,13 +400,15 @@ static int conf_mask(void* scanner, int nval, int prefixlen) {
%token <tok> SIZE
%token <tok> BOOL
-%token <tok> SYSTEM IDENTITY SVERSION NSID STORAGE KEY KEYS
+%token <tok> SYSTEM IDENTITY HOSTNAME SVERSION NSID STORAGE KEY KEYS
%token <tok> TSIG_ALGO_NAME
%token <tok> WORKERS
%token <tok> USER
+%token <tok> RUNDIR
%token <tok> PIDFILE
%token <tok> REMOTES
+%token <tok> GROUPS
%token <tok> ZONES FILENAME
%token <tok> DISABLE_ANY
@@ -297,6 +429,7 @@ static int conf_mask(void* scanner, int nval, int prefixlen) {
%token <tok> RATE_LIMIT
%token <tok> RATE_LIMIT_SIZE
%token <tok> RATE_LIMIT_SLIP
+%token <tok> TRANSFERS
%token <tok> INTERFACES ADDRESS PORT
%token <tok> IPA
@@ -384,9 +517,7 @@ interfaces:
INTERFACES '{'
| interfaces interface_start '{' interface '}' {
if (this_iface->address == 0) {
- char buf[512];
- snprintf(buf, sizeof(buf), "interface '%s' has no defined address", this_iface->name);
- cf_error(scanner, buf);
+ cf_error(scanner, "interface '%s' has no defined address", this_iface->name);
}
}
;
@@ -395,24 +526,29 @@ system:
SYSTEM '{'
| system SVERSION TEXT ';' { new_config->version = $3.t; }
| system IDENTITY TEXT ';' { new_config->identity = $3.t; }
+ | system HOSTNAME TEXT ';' { new_config->hostname = $3.t; }
| system NSID HEXSTR ';' { new_config->nsid = $3.t; new_config->nsid_len = $3.l; }
| system NSID TEXT ';' { new_config->nsid = $3.t; new_config->nsid_len = strlen(new_config->nsid); }
| system STORAGE TEXT ';' { new_config->storage = $3.t; }
- | system PIDFILE TEXT ';' { new_config->pidfile = $3.t; }
+ | system RUNDIR TEXT ';' { new_config->rundir = $3.t; }
+ | system PIDFILE TEXT ';' {
+ fprintf(stderr, "warning: Config option 'system.pidfile' is deprecated "
+ "and has no effect. Use 'rundir' instead.\n");
+ free($3.t);
+ }
| system KEY TSIG_ALGO_NAME TEXT ';' {
fprintf(stderr, "warning: Config option 'system.key' is deprecated "
"and has no effect.\n");
free($4.t);
}
- | system WORKERS NUM ';' {
- if ($3.i <= 0) {
+ | system WORKERS NUM ';' {
+ if ($3.i <= 0) {
cf_error(scanner, "worker count must be greater than 0\n");
} else {
new_config->workers = $3.i;
}
}
| system USER TEXT ';' {
- char buf[512];
new_config->uid = new_config->gid = -1; // Invalidate
char* dpos = strchr($3.t, '.'); // Find uid.gid format
if (dpos != NULL) {
@@ -420,8 +556,7 @@ system:
if (grp != NULL) {
new_config->gid = grp->gr_gid;
} else {
- snprintf(buf, sizeof(buf), "invalid group name '%s'", dpos + 1);
- cf_error(scanner, buf);
+ cf_error(scanner, "invalid group name '%s'", dpos + 1);
}
*dpos = '\0'; // Cut off
}
@@ -429,10 +564,9 @@ system:
if (pwd != NULL) {
new_config->uid = pwd->pw_uid;
} else {
- snprintf(buf, sizeof(buf), "invalid user name '%s'", $3.t);
- cf_error(scanner, buf);
+ cf_error(scanner, "invalid user name '%s'", $3.t);
}
-
+
free($3.t);
}
| system MAX_CONN_IDLE INTERVAL ';' { new_config->max_conn_idle = $3.i; }
@@ -442,22 +576,23 @@ system:
| system RATE_LIMIT_SIZE SIZE ';' { new_config->rrl_size = $3.l; }
| system RATE_LIMIT_SIZE NUM ';' { new_config->rrl_size = $3.i; }
| system RATE_LIMIT_SLIP NUM ';' { new_config->rrl_slip = $3.i; }
+ | system TRANSFERS NUM ';' { new_config->xfers = $3.i; }
;
keys:
KEYS '{'
| keys TEXT TSIG_ALGO_NAME TEXT ';' {
/* Check algorithm length. */
- if (tsig_alg_digest_length($3.alg) == 0) {
+ if (knot_tsig_digest_length($3.alg) == 0) {
cf_error(scanner, "unsupported digest algorithm");
}
-
+
/* Normalize to FQDN */
char *fqdn = $2.t;
size_t fqdnl = strlen(fqdn);
if (fqdn[fqdnl - 1] != '.') {
fqdnl = ((fqdnl + 2)/4+1)*4; /* '.', '\0' */
- char* tmpdn = malloc(fqdnl);
+ char* tmpdn = malloc(fqdnl);
if (!tmpdn) {
cf_error(scanner, "out of memory when allocating string");
free(fqdn);
@@ -475,24 +610,25 @@ keys:
if (fqdn != NULL && !conf_key_exists(scanner, fqdn)) {
knot_dname_t *dname = knot_dname_new_from_str(fqdn, fqdnl, 0);
if (!dname) {
- char buf[512];
- snprintf(buf, sizeof(buf), "key name '%s' not in valid domain "
- "name format", fqdn);
- cf_error(scanner, buf);
+ cf_error(scanner, "key name '%s' not in valid domain name format",
+ fqdn);
free($4.t);
} else {
+ knot_dname_to_lower(dname);
conf_key_t *k = malloc(sizeof(conf_key_t));
memset(k, 0, sizeof(conf_key_t));
+
k->k.name = dname;
k->k.algorithm = $3.alg;
- k->k.secret = $4.t;
+ knot_binary_from_base64($4.t, &(k->k.secret));
+ free($4.t);
add_tail(&new_config->keys, &k->n);
++new_config->key_count;
}
} else {
free($4.t);
}
-
+
free(fqdn);
}
@@ -602,13 +738,30 @@ remotes:
REMOTES '{'
| remotes remote_start '{' remote '}' {
if (this_remote->address == 0) {
- char buf[512];
- snprintf(buf, sizeof(buf), "remote '%s' has no defined address", this_remote->name);
- cf_error(scanner, buf);
+ cf_error(scanner, "remote '%s' has no defined address", this_remote->name);
}
}
;
+group_member:
+ TEXT { conf_add_member_into_group(scanner, $1.t); }
+ ;
+
+group:
+ /* empty */
+ | group_member
+ | group ',' group_member
+ ;
+
+group_start:
+ TEXT { conf_start_group(scanner, $1.t); }
+ ;
+
+groups:
+ GROUPS '{'
+ | groups group_start '{' group '}'
+ ;
+
zone_acl_start:
XFR_IN {
this_list = &this_zone->acl.xfr_in;
@@ -653,9 +806,7 @@ zone_acl:
/* Append to list if found. */
if (!found) {
- char buf[256];
- snprintf(buf, sizeof(buf), "remote '%s' is not defined", $2.t);
- cf_error(scanner, buf);
+ cf_error(scanner, "remote '%s' is not defined", $2.t);
} else {
conf_remote_t *remote = malloc(sizeof(conf_remote_t));
if (!remote) {
@@ -680,9 +831,7 @@ zone_start:
| CONTROL { conf_zone_start(scanner, strdup($1.t)); }
| NUM '/' TEXT {
if ($1.i < 0 || $1.i > 255) {
- char buf[256] = "";
- snprintf(buf, sizeof(buf), "rfc2317 origin prefix '%ld' out of bounds", $1.i);
- cf_error(scanner, buf);
+ cf_error(scanner, "rfc2317 origin prefix '%ld' out of bounds", $1.i);
}
size_t len = 3 + 1 + strlen($3.t) + 1; /* <0,255> '/' rest */
char *name = malloc(len * sizeof(char));
@@ -853,7 +1002,7 @@ ctl_allow_start:
;
control:
- CONTROL '{'
+ CONTROL '{' { new_config->ctl.have = true; }
| control ctl_listen_start '{' interface '}' {
if (this_iface->address == 0) {
cf_error(scanner, "control interface has no defined address");
@@ -861,11 +1010,16 @@ control:
new_config->ctl.iface = this_iface;
}
}
+ | control ctl_listen_start TEXT ';' {
+ this_iface->address = $3.t;
+ this_iface->family = AF_UNIX;
+ this_iface->port = 0;
+ new_config->ctl.iface = this_iface;
+ }
| control ctl_allow_start '{' zone_acl '}'
| control ctl_allow_start zone_acl_list
- ;
+ ;
-conf: ';' | system '}' | interfaces '}' | keys '}' | remotes '}' | zones '}' | log '}' | control '}';
+conf: ';' | system '}' | interfaces '}' | keys '}' | remotes '}' | groups '}' | zones '}' | log '}' | control '}';
%%
-
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index 562fb89..9ed354a 100644
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -12,8 +12,10 @@
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 <config.h>
+#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
@@ -25,7 +27,8 @@
#include <urcu.h>
#include "knot/conf/conf.h"
-#include "knot/common.h"
+#include "knot/conf/extra.h"
+#include "knot/knot.h"
#include "knot/ctl/remote.h"
/*
@@ -38,6 +41,8 @@ static const char *DEFAULT_CONFIG[] = {
};
#define DEFAULT_CONF_COUNT 1 /*!< \brief Number of default config paths. */
+#define ERROR_BUFFER_SIZE 512 /*!< \brief Error buffer size. */
+#define INCLUDES_MAX_DEPTH 8 /*!< \brief Max depth of config inclusion. */
/*
* Utilities.
@@ -46,54 +51,66 @@ static const char *DEFAULT_CONFIG[] = {
/* Prototypes for cf-parse.y */
extern int cf_parse(void *scanner);
extern int cf_get_lineno(void *scanner);
+extern void cf_set_error(void *scanner);
extern char *cf_get_text(void *scanner);
-extern int cf_lex_init(void *scanner);
+extern conf_extra_t *cf_get_extra(void *scanner);
+extern int cf_lex_init_extra(void *, void *scanner);
extern void cf_set_in(FILE *f, void *scanner);
extern void cf_lex_destroy(void *scanner);
extern void switch_input(const char *str, void *scanner);
+extern char *cf_current_filename(void *scanner);
conf_t *new_config = 0; /*!< \brief Currently parsed config. */
static volatile int _parser_res = 0; /*!< \brief Parser result. */
static pthread_mutex_t _parser_lock = PTHREAD_MUTEX_INITIALIZER;
-/*! \brief Config error report. */
-void cf_error(void *scanner, const char *msg)
+static void cf_print_error(void *scanner, const char *msg)
{
+ conf_extra_t *extra = NULL;
int lineno = -1;
- char *text = "???";
+ char *text = "?";
+ char *filename = NULL;
if (scanner) {
+ extra = cf_get_extra(scanner);
lineno = cf_get_lineno(scanner);
- text = (char *)cf_get_text(scanner);
+ text = cf_get_text(scanner);
+ filename = conf_includes_top(extra->includes);
+
+ extra->error = true;
}
- log_server_error("Config '%s' - %s on line %d (current token '%s').\n",
- new_config->filename, msg, lineno, text);
+ if (!filename)
+ filename = new_config->filename;
+ log_server_error("Config error in '%s' (line %d token '%s') - %s\n",
+ filename, lineno, text, msg);
_parser_res = KNOT_EPARSEFAIL;
}
-static int conf_ztree_compare(void *p1, void *p2)
+/*! \brief Config error report. */
+void cf_error(void *scanner, const char *format, ...)
{
- return knot_dname_compare((knot_dname_t*)p1, (knot_dname_t*)p2);
-}
+ char buffer[ERROR_BUFFER_SIZE];
+ va_list ap;
-static void conf_ztree_free(void *node, void *data)
-{
- UNUSED(data);
- knot_dname_t *zname = (knot_dname_t*)node;
- knot_dname_free(&zname);
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), format, ap);
+ va_end(ap);
+
+ cf_print_error(scanner, buffer);
}
static void conf_parse_begin(conf_t *conf)
{
- conf->zone_tree = gen_tree_new(conf_ztree_compare);
+ conf->names = hattrie_create();
}
-static void conf_parse_end(conf_t *conf)
+static void conf_parse_end(conf_t *conf)
{
- if (conf->zone_tree) {
- gen_tree_destroy(&conf->zone_tree, conf_ztree_free, NULL);
+ if (conf->names) {
+ hattrie_free(conf->names);
+ conf->names = NULL;
}
}
@@ -116,6 +133,25 @@ static void conf_update_hooks(conf_t *conf)
}
}
+/*! \brief Make relative path absolute to given directory.
+ * \param basedir Base directory.
+ * \param file Relative file name.
+ */
+static char* conf_abs_path(const char *basedir, char *file)
+{
+ /* Make path absolute to the directory. */
+ if (file[0] != '/') {
+ char *basepath = strcdup(basedir, "/");
+ char *path = strcdup(basepath, file);
+ free(basepath);
+ free(file);
+ file = path;
+ }
+
+ /* Normalize. */
+ return strcpath(file);
+}
+
/*!
* \brief Process parsed configuration.
*
@@ -129,12 +165,12 @@ static int conf_process(conf_t *conf)
{
// Check
if (conf->storage == NULL) {
- conf->storage = strdup("/var/lib/"PROJECT_EXEC);
+ conf->storage = strdup(STORAGE_DIR);
if (conf->storage == NULL) {
return KNOT_ENOMEM;
}
}
-
+
// Normalize paths
conf->storage = strcpath(conf->storage);
@@ -153,13 +189,13 @@ static int conf_process(conf_t *conf)
}
// Create PID file
- if (conf->pidfile == NULL) {
- conf->pidfile = strcdup(conf->storage, "/" PID_FILE);
- if (conf->pidfile == NULL) {
+ if (conf->rundir == NULL) {
+ conf->rundir = strdup(RUN_DIR);
+ if (conf->rundir == NULL) {
return KNOT_ENOMEM;
}
}
-
+
/* Default TCP/UDP limits. */
if (conf->max_conn_idle < 1) {
conf->max_conn_idle = CONFIG_IDLE_WD;
@@ -170,7 +206,7 @@ static int conf_process(conf_t *conf)
if (conf->max_conn_reply < 1) {
conf->max_conn_reply = CONFIG_REPLY_WD;
}
-
+
// Postprocess interfaces
conf_iface_t *cfg_if = NULL;
WALK_LIST(cfg_if, conf->ifaces) {
@@ -178,10 +214,32 @@ static int conf_process(conf_t *conf)
cfg_if->port = CONFIG_DEFAULT_PORT;
}
}
- if (conf->ctl.iface && conf->ctl.iface->port <= 0) {
- conf->ctl.iface->port = REMOTE_DPORT;
+
+ /* Default interface. */
+ conf_iface_t *ctl_if = conf->ctl.iface;
+ if (!conf->ctl.have && ctl_if == NULL) {
+ ctl_if = malloc(sizeof(conf_iface_t));
+ memset(ctl_if, 0, sizeof(conf_iface_t));
+ ctl_if->family = AF_UNIX;
+ ctl_if->address = strdup("knot.sock");
+ conf->ctl.iface = ctl_if;
+ }
+
+ /* Control interface. */
+ if (ctl_if) {
+ if (ctl_if->family == AF_UNIX) {
+ ctl_if->address = conf_abs_path(conf->rundir,
+ ctl_if->address);
+ /* Check for ACL existence. */
+ if (!EMPTY_LIST(conf->ctl.allow)) {
+ log_server_warning("Control 'allow' statement "
+ "does not affect UNIX sockets.\n");
+ }
+ } else if (ctl_if->port <= 0) {
+ ctl_if->port = REMOTE_DPORT;
+ }
}
-
+
/* Default RRL limits. */
if (conf->rrl_slip < 0) {
conf->rrl_slip = CONFIG_RRL_SLIP;
@@ -190,6 +248,9 @@ static int conf_process(conf_t *conf)
conf->rrl_size = CONFIG_RRL_SIZE;
}
+ /* Default parallel transfers. */
+ if (conf->xfers <= 0) conf->xfers = CONFIG_XFERS;
+
// Postprocess zones
int ret = KNOT_EOK;
node *n = 0;
@@ -200,7 +261,7 @@ static int conf_process(conf_t *conf)
if (zone->dbsync_timeout < 0) {
zone->dbsync_timeout = conf->dbsync_timeout;
}
-
+
// Default policy for ixfr-from-differences
if (zone->build_diffs < 0) {
zone->build_diffs = conf->build_diffs;
@@ -210,7 +271,7 @@ static int conf_process(conf_t *conf)
if (zone->enable_checks < 0) {
zone->enable_checks = conf->zone_checks;
}
-
+
// Default policy for disabling ANY type queries for AA
if (zone->disable_any < 0) {
zone->disable_any = conf->disable_any;
@@ -230,7 +291,7 @@ static int conf_process(conf_t *conf)
if (zone->ixfr_fslimit == 0) {
zone->ixfr_fslimit = conf->ixfr_fslimit;
}
-
+
// Default zone file
if (zone->file == NULL) {
zone->file = strcdup(zone->name, ".zone");
@@ -239,92 +300,45 @@ static int conf_process(conf_t *conf)
continue;
}
}
-
- // Relative zone filenames should be relative to storage
- if (zone->file[0] != '/') {
- size_t prefix_len = strlen(conf->storage) + 1; // + '\0'
- size_t zp_len = strlen(zone->file) + 1;
- char *ap = malloc(prefix_len + zp_len);
- if (ap != NULL) {
- memcpy(ap, conf->storage, prefix_len);
- ap[prefix_len - 1] = '/';
- memcpy(ap + prefix_len, zone->file, zp_len);
- free(zone->file);
- zone->file = ap;
- } else {
- ret = KNOT_ENOMEM;
- continue;
- }
- }
- // Normalize zone filename
- zone->file = strcpath(zone->file);
+ // Relative zone filenames should be relative to storage
+ zone->file = conf_abs_path(conf->storage, zone->file);
if (zone->file == NULL) {
- zone->db = NULL;
ret = KNOT_ENOMEM;
continue;
}
- // Create zone db filename
+ /* Create journal filename. */
size_t zname_len = strlen(zone->name);
size_t stor_len = strlen(conf->storage);
- size_t size = stor_len + zname_len + 4; // /db,\0
+ size_t size = stor_len + zname_len + 9; // /diff.db,\0
char *dest = malloc(size);
if (dest == NULL) {
- zone->db = NULL; /* Not enough memory. */
- ret = KNOT_ENOMEM; /* Error report. */
- continue;
- }
- char *dpos = dest;
-
- /* Since we have already allocd dest to accomodate
- * storage/zname length strcpy is safe. */
- memcpy(dpos, conf->storage, stor_len + 1);
- dpos += stor_len;
- if (*(dpos - 1) != '/') {
- *(dpos++) = '/';
- *dpos = '\0';
- }
-
- /* Copy origin and remove bad characters. */
- memcpy(dpos, zone->name, zname_len + 1);
- for (int i = 0; i < zname_len; ++i) {
- if (dpos[i] == '/') dpos[i] = '_';
- }
-
- memcpy(dpos + zname_len, "db", 3);
- zone->db = dest;
-
- // Create IXFR db filename
- stor_len = strlen(conf->storage);
- size = stor_len + zname_len + 9; // /diff.db,\0
- dest = malloc(size);
- if (dest == NULL) {
zone->ixfr_db = NULL; /* Not enough memory. */
ret = KNOT_ENOMEM; /* Error report. */
continue;
}
- dpos = dest;
+ char *dpos = dest;
memcpy(dpos, conf->storage, stor_len + 1);
dpos += stor_len;
if (conf->storage[stor_len - 1] != '/') {
- *(dpos++) = '/';
+ *(dpos++) = '/';
*dpos = '\0';
}
const char *dbext = "diff.db";
memcpy(dpos, zone->name, zname_len + 1);
- for (int i = 0; i < zname_len; ++i) {
+ for (size_t i = 0; i < zname_len; ++i) {
if (dpos[i] == '/') dpos[i] = '_';
}
memcpy(dpos + zname_len, dbext, strlen(dbext) + 1);
zone->ixfr_db = dest;
}
-
+
/* Update UID and GID. */
if (conf->uid < 0) conf->uid = getuid();
if (conf->gid < 0) conf->gid = getgid();
-
+
/* Build remote control ACL. */
sockaddr_t addr;
conf_remote_t *r = NULL;
@@ -364,7 +378,7 @@ void __attribute__ ((constructor)) conf_init()
++s_config->ifaces_count;
/* Create default storage. */
- s_config->storage = strdup("/var/lib/"PROJECT_EXEC);
+ s_config->storage = strdup(STORAGE_DIR);
/* Create default logs. */
@@ -419,7 +433,7 @@ static int conf_fparser(conf_t *conf)
int ret = KNOT_EOK;
pthread_mutex_lock(&_parser_lock);
-
+
// {
// Hook new configuration
new_config = conf;
@@ -433,15 +447,17 @@ static int conf_fparser(conf_t *conf)
_parser_res = KNOT_EOK;
new_config->filename = conf->filename;
void *sc = NULL;
- cf_lex_init(&sc);
+ conf_extra_t *extra = conf_extra_init(conf->filename, INCLUDES_MAX_DEPTH);
+ cf_lex_init_extra(extra, &sc);
cf_set_in(f, sc);
cf_parse(sc);
cf_lex_destroy(sc);
+ conf_extra_free(extra);
ret = _parser_res;
fclose(f);
// }
pthread_mutex_unlock(&_parser_lock);
-
+
return ret;
}
@@ -465,10 +481,12 @@ static int conf_strparser(conf_t *conf, const char *src)
char *oldfn = new_config->filename;
new_config->filename = "(stdin)";
void *sc = NULL;
- cf_lex_init(&sc);
+ conf_extra_t *extra = conf_extra_init("", INCLUDES_MAX_DEPTH);
+ cf_lex_init_extra(extra, &sc);
switch_input(src, sc);
cf_parse(sc);
cf_lex_destroy(sc);
+ conf_extra_free(extra);
new_config->filename = oldfn;
ret = _parser_res;
// }
@@ -496,6 +514,7 @@ conf_t *conf_new(const char* path)
init_list(&c->zones);
init_list(&c->hooks);
init_list(&c->remotes);
+ init_list(&c->groups);
init_list(&c->keys);
init_list(&c->ctl.allow);
@@ -507,9 +526,10 @@ conf_t *conf_new(const char* path)
c->ixfr_fslimit = -1;
c->uid = -1;
c->gid = -1;
+ c->xfers = -1;
c->rrl_slip = -1;
c->build_diffs = 0; /* Disable by default. */
-
+
/* ACLs. */
c->ctl.acl = acl_new(ACL_DENY, "remote_ctl");
if (!c->ctl.acl) {
@@ -544,7 +564,7 @@ int conf_parse(conf_t *conf)
conf_parse_begin(conf);
int ret = conf_fparser(conf);
conf_parse_end(conf);
-
+
/* Postprocess config. */
if (ret == 0) {
ret = conf_process(conf);
@@ -623,6 +643,12 @@ void conf_truncate(conf_t *conf, int unload_hooks)
conf->remotes_count = 0;
init_list(&conf->remotes);
+ // Free groups of remotes
+ WALK_LIST_DELSAFE(n, nxt, conf->groups) {
+ conf_free_group((conf_group_t *)n);
+ }
+ init_list(&conf->groups);
+
// Free zones
WALK_LIST_DELSAFE(n, nxt, conf->zones) {
conf_free_zone((conf_zone_t*)n);
@@ -638,6 +664,10 @@ void conf_truncate(conf_t *conf, int unload_hooks)
free(conf->identity);
conf->identity = 0;
}
+ if (conf->hostname) {
+ free(conf->hostname);
+ conf->hostname = 0;
+ }
if (conf->version) {
free(conf->version);
conf->version = 0;
@@ -646,25 +676,25 @@ void conf_truncate(conf_t *conf, int unload_hooks)
free(conf->storage);
conf->storage = 0;
}
- if (conf->pidfile) {
- free(conf->pidfile);
- conf->pidfile = 0;
+ if (conf->rundir) {
+ free(conf->rundir);
+ conf->rundir = 0;
}
if (conf->nsid) {
free(conf->nsid);
conf->nsid = 0;
}
-
+
/* Free remote control list. */
WALK_LIST_DELSAFE(n, nxt, conf->ctl.allow) {
conf_free_remote((conf_remote_t*)n);
}
conf->remotes_count = 0;
init_list(&conf->remotes);
-
+
/* Free remote control ACL. */
acl_truncate(conf->ctl.acl);
-
+
/* Free remote control iface. */
conf_free_iface(conf->ctl.iface);
}
@@ -677,7 +707,7 @@ void conf_free(conf_t *conf)
/* Truncate config. */
conf_truncate(conf, 1);
-
+
/* Free remote control ACL. */
acl_delete(&conf->ctl.acl);
@@ -740,7 +770,7 @@ int conf_open(const char* path)
/* Postprocess config. */
ret = conf_process(nconf);
}
-
+
if (ret != KNOT_EOK) {
conf_free(nconf);
return ret;
@@ -773,32 +803,13 @@ int conf_open(const char* path)
return KNOT_EOK;
}
-char* strcdup(const char *s1, const char *s2)
-{
- if (!s1 || !s2) {
- return NULL;
- }
-
- size_t slen = strlen(s1);
- size_t s2len = strlen(s2);
- size_t nlen = slen + s2len + 1;
- char* dst = malloc(nlen);
- if (dst == NULL) {
- return NULL;
- }
-
- memcpy(dst, s1, slen);
- strncpy(dst + slen, s2, s2len + 1); // With trailing '\0'
- return dst;
-}
-
char* strcpath(char *path)
{
// NULL path
if (!path) {
return NULL;
}
-
+
// Remote trailing slash
size_t plen = strlen(path);
if (path[plen - 1] == '/') {
@@ -838,7 +849,7 @@ char* strcpath(char *path)
npath[0] = '\0';
strncpy(npath, path, (size_t)(remainder - path));
strncat(npath, tild_exp, tild_len);
-
+
// Append remainder
++remainder;
strncat(npath, remainder, strlen(remainder));
@@ -866,19 +877,13 @@ void conf_free_zone(conf_zone_t *zone)
free(zone->name);
free(zone->file);
- free(zone->db);
free(zone->ixfr_db);
free(zone);
}
void conf_free_key(conf_key_t *k)
{
- /* Secure erase. */
- if (k->k.secret) {
- memset(k->k.secret, 0, strlen(k->k.secret));
- }
- free(k->k.secret);
- knot_dname_free(&k->k.name);
+ knot_tsig_key_free(&k->k);
free(k);
}
@@ -898,15 +903,24 @@ void conf_free_remote(conf_remote_t *r)
free(r);
}
+void conf_free_group(conf_group_t *group)
+{
+ conf_group_remote_t *remote, *next;
+ WALK_LIST_DELSAFE(remote, next, group->remotes) {
+ free(remote->name);
+ free(remote);
+ }
+
+ free(group);
+}
+
void conf_free_log(conf_log_t *log)
{
if (!log) {
return;
}
- if (log->file) {
- free(log->file);
- }
+ free(log->file);
/* Free loglevel mapping. */
node *n = 0, *nxt = 0;
@@ -916,4 +930,3 @@ void conf_free_log(conf_log_t *log)
free(log);
}
-
diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h
index 380d9df..57b250e 100644
--- a/src/knot/conf/conf.h
+++ b/src/knot/conf/conf.h
@@ -34,13 +34,13 @@
#include <urcu.h>
#include "libknot/dname.h"
-#include "libknot/util/descriptor.h"
#include "libknot/tsig.h"
+#include "libknot/sign/key.h"
#include "common/lists.h"
#include "common/log.h"
#include "common/acl.h"
#include "common/sockaddr.h"
-#include "common/general-tree.h"
+#include "common/hattrie/hat-trie.h"
/* Constants. */
#define CONFIG_DEFAULT_PORT 53
@@ -52,6 +52,7 @@
#define CONFIG_IDLE_WD 60 /*!< [secs] of allowed inactivity between requests */
#define CONFIG_RRL_SLIP 2 /*!< Default slip value. */
#define CONFIG_RRL_SIZE 393241 /*!< Htable default size. */
+#define CONFIG_XFERS 10
/*!
* \brief Configuration for the interface
@@ -62,13 +63,13 @@
*/
typedef struct conf_iface_t {
node n;
- char *name; /*!< Internal name for the interface. */
- char *address; /*!< IP (IPv4/v6) address for this interface */
- unsigned prefix; /*!< IP subnet prefix. */
- int port; /*!< Port number for this interface */
- int family; /*!< Address family. */
- knot_key_t *key; /*!< TSIG key (only valid for remotes). */
- sockaddr_t via; /*!< Used for remotes to specify qry endpoint.*/
+ char *name; /*!< Internal name for the interface. */
+ char *address; /*!< IP (IPv4/v6) address for this interface */
+ unsigned prefix; /*!< IP subnet prefix. */
+ int port; /*!< Port number for this interface */
+ int family; /*!< Address family. */
+ knot_tsig_key_t *key; /*!< TSIG key (only valid for remotes). */
+ sockaddr_t via; /*!< Used for remotes to specify qry endpoint.*/
} conf_iface_t;
/*!
@@ -82,6 +83,25 @@ typedef struct conf_remote_t {
} conf_remote_t;
/*!
+ * \brief Group of remotes list item.
+ *
+ * Holds the name of a remote in the list.
+ */
+typedef struct conf_group_remote_t {
+ node n;
+ char *name;
+} conf_group_remote_t;
+
+/*!
+ * \brief Group of remotes.
+ */
+typedef struct conf_group_t {
+ node n; /*!< List node. */
+ char *name; /*!< Unique name of the group. */
+ list remotes; /*!< List of remote names. */
+} conf_group_t;
+
+/*!
* \brief Zone configuration.
*
* This structure holds the configuration for the zone. In it's most
@@ -93,9 +113,8 @@ typedef struct conf_remote_t {
typedef struct conf_zone_t {
node n;
char *name; /*!< Zone name. */
- enum knot_rr_class cls; /*!< Zone class (IN or CH). */
+ uint16_t cls; /*!< Zone class (IN or CH). */
char *file; /*!< Path to a zone file. */
- char *db; /*!< Path to a database file. */
char *ixfr_db; /*!< Path to a IXFR database file. */
size_t ixfr_fslimit; /*!< File size limit for IXFR journal. */
int dbsync_timeout; /*!< Interval between syncing to zonefile.*/
@@ -109,7 +128,7 @@ typedef struct conf_zone_t {
list xfr_out; /*!< Remotes accepted for xfr-out.*/
list notify_in; /*!< Remotes accepted for notify-in.*/
list notify_out; /*!< Remotes accepted for notify-out.*/
- list update_in; /*!< Remotes accepted for DDNS.*/
+ list update_in; /*!< Remotes accepted for DDNS.*/
} acl;
} conf_zone_t;
@@ -148,7 +167,7 @@ typedef enum conf_section_t {
*/
typedef struct conf_key_t {
node n;
- knot_key_t k;
+ knot_tsig_key_t k;
} conf_key_t;
/*!
@@ -158,6 +177,7 @@ typedef struct conf_control_t {
conf_iface_t *iface; /*!< Remote control interface. */
list allow; /*!< List of allowed remotes. */
acl_t* acl; /*!< ACL. */
+ bool have; /*!< Set if configured. */
} conf_control_t;
/*!
@@ -171,9 +191,10 @@ typedef struct conf_t {
*/
char *filename; /*!< Name of the config file. */
char *identity; /*!< Identity to return on CH TXT id.server. */
+ char *hostname; /*!< Host name to return on CH TXT hostname.{bind,server} */
char *version; /*!< Version for CH TXT version.{bind|server} */
char *storage; /*!< Persistent storage path for databases and such. */
- char *pidfile; /*!< PID file path. */
+ char *rundir; /*!< Run-time directory path. */
char *nsid; /*!< Server's NSID. */
size_t nsid_len;/*!< Server's NSID length. */
int workers; /*!< Number of workers per interface. */
@@ -185,6 +206,7 @@ typedef struct conf_t {
int rrl; /*!< Rate limit (in responses per second). */
size_t rrl_size; /*!< Rate limit htable size. */
int rrl_slip; /*!< Rate limit SLIP. */
+ int xfers; /*!< Number of parallel transfers. */
/*
* Log
@@ -211,6 +233,11 @@ typedef struct conf_t {
int remotes_count;/*!< Count of remotes. */
/*
+ * Groups of remotes.
+ */
+ list groups; /*!< List of groups of remotes. */
+
+ /*
* Zones
*/
list zones; /*!< List of zones. */
@@ -222,8 +249,8 @@ typedef struct conf_t {
int dbsync_timeout; /*!< Default interval between syncing to zonefile.*/
size_t ixfr_fslimit; /*!< File size limit for IXFR journal. */
int build_diffs; /*!< Calculate differences from changes. */
- general_tree_t *zone_tree; /*!< Zone tree for duplicate checking. */
-
+ hattrie_t *names; /*!< Zone tree for duplicate checking. */
+
/*
* Remote control interface.
*/
@@ -359,17 +386,6 @@ static inline conf_t* conf() {
*/
/*!
- * \brief Create new string from a concatenation of s1 and s2.
- *
- * \param s1 First string.
- * \param s2 Second string.
- *
- * \retval Newly allocated string on success.
- * \retval NULL on error.
- */
-char* strcdup(const char *s1, const char *s2);
-
-/*!
* \brief Normalize file path and expand '~' placeholders.
*
* \note Old pointer may be freed.
@@ -390,6 +406,9 @@ void conf_free_iface(conf_iface_t *iface);
/*! \brief Free remotes config. */
void conf_free_remote(conf_remote_t *r);
+/*! \brief Free group config. */
+void conf_free_group(conf_group_t *group);
+
/*! \brief Free log config. */
void conf_free_log(conf_log_t *log);
diff --git a/src/knot/conf/extra.c b/src/knot/conf/extra.c
new file mode 100644
index 0000000..c172a15
--- /dev/null
+++ b/src/knot/conf/extra.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "knot/conf/includes.h"
+#include "knot/conf/extra.h"
+
+
+/*!
+ * \brief Init structure with custom data for config parser.
+ */
+conf_extra_t *conf_extra_init(const char *file, int includes_max_depth)
+{
+ conf_extra_t *extra = calloc(1, sizeof(conf_extra_t));
+ if (!extra)
+ return NULL;
+
+ conf_includes_t *includes = conf_includes_init(includes_max_depth);
+ if (!includes) {
+ free(extra);
+ return NULL;
+ }
+
+ if (!conf_includes_push(includes, file)) {
+ conf_includes_free(includes);
+ free(extra);
+ return NULL;
+ }
+
+ extra->error = false;
+ extra->includes = includes;
+
+ return extra;
+}
+
+/*!
+ * \brief Free structure with custom data for config parser.
+ */
+void conf_extra_free(conf_extra_t *extra)
+{
+ if (!extra)
+ return;
+
+ conf_includes_free(extra->includes);
+ free(extra);
+}
diff --git a/src/knot/conf/extra.h b/src/knot/conf/extra.h
new file mode 100644
index 0000000..bfd393c
--- /dev/null
+++ b/src/knot/conf/extra.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2011 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 extra.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief API for managing custom data in the configuration parser.
+ *
+ * \addtogroup config
+ * @{
+ */
+
+#ifndef _KNOT_CONF_EXTRA_H_
+#define _KNOT_CONF_EXTRA_H_
+
+#include <stdbool.h>
+
+#include "knot/conf/includes.h"
+
+/*!
+ * \brief Custom data held within the parser context.
+ */
+typedef struct {
+ bool error; //!< Indicates that error was set.
+ conf_includes_t *includes; //!< Used to handle filenames in includes.
+} conf_extra_t;
+
+/*!
+ * \brief Init structure with custom data for config parser.
+ *
+ * \param file Name of the main configuration file.
+ * \param includes_max_depth Max depth of file inclusions.
+ *
+ * \return Initialized stucture or NULL.
+ */
+conf_extra_t *conf_extra_init(const char *file, int includes_max_depth);
+
+/*!
+ * \brief Free structure with custom data for config parser.
+ *
+ * \param extra Structure to be freed.
+ */
+void conf_extra_free(conf_extra_t *extra);
+
+#endif /* _KNOT_CONF_EXTRA_H_ */
+
+/*! @} */
diff --git a/src/knot/conf/includes.c b/src/knot/conf/includes.c
new file mode 100644
index 0000000..8bd9c16
--- /dev/null
+++ b/src/knot/conf/includes.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "knot/conf/includes.h"
+
+/*!
+ * \brief Structure to store names of files included into the config.
+ */
+struct conf_includes {
+ int free_index; //!< First free index in 'names'.
+ int capacity; //!< Maximal capacity.
+ char *names[0]; //!< Pointers to store file names.
+};
+
+/*!
+ * \brief Initialize structure for storing names of included files.
+ */
+conf_includes_t *conf_includes_init(int capacity)
+{
+ if (capacity <= 0)
+ return NULL;
+
+ size_t size = sizeof(conf_includes_t) + (capacity * sizeof(char *));
+ conf_includes_t *result = calloc(1, size);
+ if (!result)
+ return NULL;
+
+ result->capacity = capacity;
+ return result;
+}
+
+/*!
+ * \brief Free structure for storing the names of included files.
+ */
+void conf_includes_free(conf_includes_t *includes)
+{
+ if (!includes)
+ return;
+
+ for (int i = 0; i < includes->free_index; i++)
+ free(includes->names[i]);
+
+ free(includes);
+}
+
+/**
+ * \brief Check if there is a capacity to insert new file..
+ */
+bool conf_includes_can_push(conf_includes_t *includes)
+{
+ if (!includes)
+ return false;
+
+ return includes->free_index < includes->capacity;
+}
+
+/**
+ * \brief Constructs a path relative to a reference file.
+ *
+ * e.g. path_relative_to("b.conf", "samples/a.conf") == "samples/b.conf"
+ *
+ * \param filename File name of the target file.
+ * \param reference Referece file name (just path is used).
+ *
+ * \return Relative path to a reference file.
+ */
+static char *path_relative_to(const char *filename, const char *reference)
+{
+ char *path_end = strrchr(reference, '/');
+ if (!path_end)
+ return strdup(filename);
+
+ int path_len = (int)(path_end - reference);
+ size_t result_len = path_len + 1 + strlen(filename) + 1;
+ char *result = malloc(result_len * sizeof(char));
+ if (!result)
+ return NULL;
+
+ int w;
+ w = snprintf(result, result_len, "%.*s/%s", path_len, reference, filename);
+ assert(w + 1 == (int)result_len);
+
+ return result;
+}
+
+/**
+ * \brief Pushes a file name onto the stack of files.
+ */
+bool conf_includes_push(conf_includes_t *includes, const char *filename)
+{
+ if (!includes || !filename)
+ return false;
+
+ if (!conf_includes_can_push(includes))
+ return false;
+
+ char *store = NULL;
+
+ if (includes->free_index == 0 || filename[0] == '/') {
+ store = strdup(filename);
+ } else {
+ char *previous = includes->names[includes->free_index - 1];
+ store = path_relative_to(filename, previous);
+ }
+
+ includes->names[includes->free_index++] = store;
+ return store != NULL;
+}
+
+/**
+ * \brief Returns a file name on the top of the stack.
+ */
+char *conf_includes_top(conf_includes_t *includes)
+{
+ if (!includes || includes->free_index == 0)
+ return NULL;
+
+ return includes->names[includes->free_index - 1];
+}
+
+/**
+ * \brief Returns a file name on the top of the stack and removes it.
+ */
+char *conf_includes_pop(conf_includes_t *includes)
+{
+ char *result = conf_includes_top(includes);
+ if (result)
+ includes->free_index -= 1;
+
+ return result;
+}
diff --git a/src/knot/conf/includes.h b/src/knot/conf/includes.h
new file mode 100644
index 0000000..64c26e5
--- /dev/null
+++ b/src/knot/conf/includes.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2011 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 includes.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief Handing of includes in configuration file.
+ *
+ * \addtogroup config
+ * @{
+ */
+
+#ifndef _KNOT_CONF_INCLUDES_H_
+#define _KNOT_CONF_INCLUDES_H_
+
+#include <stdbool.h>
+
+/*!
+ * \brief Structure to store names of files included into the config.
+ */
+struct conf_includes;
+typedef struct conf_includes conf_includes_t;
+
+/*!
+ * \brief Initialize structure for storing names of included files.
+ *
+ * \param capacity Max depth of the inclusion.
+ */
+conf_includes_t *conf_includes_init(int capacity);
+
+/*!
+ * \brief Free structure for storing the names of included files.
+ */
+void conf_includes_free(conf_includes_t *includes);
+
+/**
+ * \brief Check if there is a capacity to insert new file..
+ */
+bool conf_includes_can_push(conf_includes_t *includes);
+
+/**
+ * \brief Pushes a file name onto the stack of files.
+ *
+ * If the file name is not absolute (or first inserted), the name is changed
+ * to be relative to previously inserted file name.
+ *
+ * \param filename File name to be stored (and processed). It is copied.
+ *
+ * \return Success.
+ */
+bool conf_includes_push(conf_includes_t *includes, const char *filename);
+
+/**
+ * \brief Returns a file name on the top of the stack.
+ *
+ * \return File name on the top of the stack. Do not free it.
+ */
+char *conf_includes_top(conf_includes_t *includes);
+
+/**
+ * \brief Returns a file name on the top of the stack and removes it.
+ *
+ * \return File name on the top of the stack. Caller should free the result.
+ */
+char *conf_includes_pop(conf_includes_t *includes);
+
+#endif /* _KNOT_CONF_INCLUDES_H_ */
+
+/*! @} */
diff --git a/src/knot/conf/libknotd_la-cf-lex.c b/src/knot/conf/libknotd_la-cf-lex.c
new file mode 100644
index 0000000..d3683ec
--- /dev/null
+++ b/src/knot/conf/libknotd_la-cf-lex.c
@@ -0,0 +1,2889 @@
+#line 2 "knot/conf/libknotd_la-cf-lex.c"
+
+#line 4 "knot/conf/libknotd_la-cf-lex.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 35
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! C99 */
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE cf_restart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
+#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE cf_lex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-yylineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < yyleng; ++yyl )\
+ if ( yytext[yyl] == '\n' )\
+ --yylineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via cf_restart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void cf_restart (FILE *input_file ,yyscan_t yyscanner );
+void cf__switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE cf__create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void cf__delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void cf__flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void cf_push_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void cf_pop_buffer_state (yyscan_t yyscanner );
+
+static void cf_ensure_buffer_stack (yyscan_t yyscanner );
+static void cf__load_buffer_state (yyscan_t yyscanner );
+static void cf__init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER cf__flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE cf__scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE cf__scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE cf__scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *cf_alloc (yy_size_t ,yyscan_t yyscanner );
+void *cf_realloc (void *,yy_size_t ,yyscan_t yyscanner );
+void cf_free (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer cf__create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ cf_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cf__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ cf_ensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ cf__create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define cf_wrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 83
+#define YY_END_OF_BUFFER 84
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[446] =
+ { 0,
+ 0, 0, 0, 0, 84, 83, 2, 3, 83, 83,
+ 3, 78, 64, 64, 79, 78, 83, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 80,
+ 83, 2, 0, 77, 76, 0, 1, 78, 78, 64,
+ 0, 78, 63, 62, 62, 78, 0, 67, 0, 0,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 60, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+
+ 80, 0, 82, 81, 78, 68, 0, 67, 67, 67,
+ 0, 0, 78, 54, 78, 47, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 10, 78, 46, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 42, 78, 78, 78, 78, 78, 0, 0, 67, 67,
+ 67, 0, 0, 0, 0, 66, 78, 78, 78, 78,
+ 78, 78, 78, 15, 78, 78, 78, 78, 78, 78,
+ 56, 78, 78, 11, 78, 78, 78, 8, 78, 41,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+
+ 78, 78, 28, 78, 78, 78, 78, 50, 78, 0,
+ 0, 0, 0, 0, 0, 78, 44, 78, 78, 55,
+ 78, 59, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 14, 78, 0, 0, 78, 78, 78,
+ 78, 13, 78, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 57, 78, 78, 78, 78, 30, 78, 48,
+ 52, 51, 78, 53, 4, 78, 78, 78, 78, 78,
+ 22, 78, 78, 65, 0, 0, 40, 78, 43, 78,
+
+ 78, 78, 78, 78, 78, 61, 78, 78, 78, 78,
+ 78, 78, 29, 78, 12, 78, 9, 78, 78, 7,
+ 58, 27, 23, 78, 0, 0, 78, 78, 69, 70,
+ 78, 6, 5, 78, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 67, 0, 49,
+ 78, 71, 78, 78, 78, 78, 78, 78, 45, 78,
+ 25, 78, 78, 78, 78, 78, 38, 24, 78, 0,
+ 78, 78, 78, 78, 78, 39, 78, 78, 78, 78,
+ 78, 26, 78, 78, 35, 78, 78, 16, 72, 73,
+ 74, 75, 78, 78, 78, 78, 78, 78, 78, 78,
+
+ 78, 78, 78, 21, 78, 78, 78, 78, 78, 78,
+ 78, 78, 78, 78, 32, 78, 78, 78, 78, 78,
+ 78, 20, 78, 78, 34, 18, 19, 78, 78, 78,
+ 78, 78, 36, 37, 17, 78, 78, 78, 78, 78,
+ 33, 78, 78, 31, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 6, 4, 4, 4, 1, 4,
+ 4, 4, 4, 4, 7, 8, 4, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 16, 18, 4, 1,
+ 1, 1, 1, 4, 19, 19, 19, 19, 19, 19,
+ 20, 21, 21, 21, 21, 21, 20, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 22, 1, 23, 4, 21, 1, 24, 25, 26, 27,
+
+ 28, 29, 30, 31, 32, 21, 33, 34, 35, 36,
+ 37, 38, 21, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 4, 1, 4, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[48] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 4, 5, 2,
+ 2, 1, 1, 5, 5, 5, 5, 5, 5, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2
+ } ;
+
+static yyconst flex_int16_t yy_base[464] =
+ { 0,
+ 0, 0, 46, 50, 679, 680, 54, 680, 55, 675,
+ 0, 0, 54, 632, 658, 93, 657, 89, 637, 22,
+ 634, 640, 37, 78, 97, 643, 94, 646, 90, 99,
+ 97, 108, 110, 630, 99, 112, 117, 639, 630, 143,
+ 144, 150, 152, 680, 680, 663, 680, 0, 149, 620,
+ 646, 0, 0, 0, 0, 158, 645, 179, 644, 643,
+ 633, 625, 169, 622, 632, 616, 616, 620, 616, 612,
+ 627, 610, 621, 173, 619, 601, 606, 615, 599, 602,
+ 610, 612, 0, 613, 600, 597, 602, 600, 141, 173,
+ 595, 610, 606, 604, 592, 606, 590, 589, 588, 590,
+
+ 176, 208, 680, 680, 617, 0, 606, 615, 207, 604,
+ 603, 228, 581, 582, 574, 0, 576, 574, 591, 577,
+ 585, 570, 604, 584, 568, 572, 573, 569, 577, 565,
+ 563, 561, 0, 594, 568, 572, 569, 556, 568, 558,
+ 567, 569, 549, 221, 552, 225, 554, 565, 549, 547,
+ 0, 550, 552, 577, 555, 258, 564, 0, 573, 0,
+ 562, 561, 570, 267, 288, 680, 549, 532, 547, 535,
+ 543, 547, 532, 0, 532, 528, 561, 531, 525, 523,
+ 0, 525, 556, 0, 534, 535, 201, 0, 528, 0,
+ 552, 517, 525, 520, 527, 515, 511, 528, 514, 522,
+
+ 509, 507, 0, 515, 514, 517, 111, 172, 536, 535,
+ 524, 0, 533, 0, 297, 500, 0, 500, 501, 0,
+ 503, 0, 496, 495, 225, 510, 501, 505, 502, 501,
+ 493, 491, 499, 480, 491, 490, 495, 483, 480, 481,
+ 480, 477, 487, 486, 480, 485, 485, 475, 475, 471,
+ 473, 466, 475, 0, 306, 0, 498, 465, 472, 469,
+ 474, 0, 469, 473, 468, 463, 456, 468, 471, 189,
+ 487, 457, 0, 485, 463, 458, 449, 0, 456, 0,
+ 0, 0, 459, 0, 0, 458, 478, 448, 453, 442,
+ 0, 440, 446, 0, 471, 0, 0, 442, 0, 470,
+
+ 446, 461, 450, 445, 426, 0, 445, 433, 435, 431,
+ 431, 292, 0, 431, 0, 439, 0, 425, 431, 0,
+ 0, 0, 0, 434, 0, 453, 430, 435, 0, 0,
+ 316, 0, 0, 430, 422, 424, 419, 447, 417, 410,
+ 423, 418, 417, 441, 407, 410, 438, 0, 0, 0,
+ 408, 0, 250, 426, 432, 401, 433, 404, 0, 303,
+ 0, 397, 396, 401, 394, 408, 0, 0, 393, 409,
+ 385, 417, 414, 415, 416, 0, 399, 393, 400, 396,
+ 394, 0, 382, 392, 412, 387, 371, 0, 0, 0,
+ 0, 0, 384, 374, 378, 379, 374, 379, 373, 369,
+
+ 380, 371, 377, 0, 378, 376, 369, 374, 359, 216,
+ 374, 373, 369, 357, 0, 350, 355, 353, 346, 360,
+ 358, 0, 362, 358, 0, 0, 0, 360, 322, 301,
+ 301, 315, 0, 0, 0, 310, 304, 300, 304, 299,
+ 0, 261, 248, 0, 680, 342, 347, 352, 356, 359,
+ 362, 367, 370, 373, 376, 284, 379, 382, 260, 259,
+ 178, 111, 56
+ } ;
+
+static yyconst flex_int16_t yy_def[464] =
+ { 0,
+ 445, 1, 446, 446, 445, 445, 445, 445, 447, 448,
+ 449, 449, 445, 13, 450, 449, 451, 16, 16, 16,
+ 16, 16, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 445,
+ 452, 445, 447, 445, 445, 448, 445, 449, 449, 13,
+ 450, 16, 449, 16, 449, 449, 450, 445, 451, 453,
+ 16, 449, 449, 449, 16, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+
+ 445, 452, 445, 445, 49, 56, 454, 58, 445, 455,
+ 453, 445, 16, 449, 449, 449, 449, 16, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 454, 456, 109, 109,
+ 457, 458, 112, 445, 112, 445, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+
+ 449, 449, 449, 449, 449, 449, 449, 449, 156, 456,
+ 458, 459, 164, 164, 164, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 460, 459, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 255, 460, 461, 449, 449, 449, 449,
+
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 462, 461, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 462, 463, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 463,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
+ 449, 449, 449, 449, 0, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445
+ } ;
+
+static yyconst flex_int16_t yy_nxt[728] =
+ { 0,
+ 6, 7, 7, 8, 9, 10, 11, 12, 13, 14,
+ 14, 14, 14, 14, 14, 14, 14, 15, 16, 12,
+ 12, 17, 6, 18, 16, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 12, 39, 40, 40, 65,
+ 41, 40, 40, 66, 41, 42, 42, 44, 370, 45,
+ 48, 49, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 51, 52, 53, 48, 69, 70, 52, 52, 52,
+ 54, 52, 52, 48, 55, 48, 53, 48, 55, 48,
+ 48, 48, 48, 55, 48, 48, 48, 48, 56, 48,
+
+ 48, 52, 52, 52, 52, 52, 52, 52, 52, 52,
+ 51, 52, 71, 348, 72, 61, 52, 52, 52, 52,
+ 52, 52, 62, 73, 63, 77, 80, 82, 84, 81,
+ 78, 86, 74, 85, 83, 87, 93, 89, 94, 95,
+ 97, 75, 251, 96, 101, 101, 103, 252, 104, 88,
+ 90, 42, 42, 98, 44, 91, 45, 105, 105, 105,
+ 105, 105, 105, 105, 105, 105, 106, 106, 106, 106,
+ 106, 106, 106, 106, 106, 142, 106, 101, 101, 143,
+ 326, 106, 106, 106, 106, 106, 106, 108, 108, 108,
+ 108, 108, 108, 108, 108, 108, 109, 110, 127, 144,
+
+ 253, 128, 110, 110, 110, 110, 110, 110, 115, 145,
+ 103, 254, 104, 129, 116, 159, 159, 159, 159, 159,
+ 159, 159, 159, 159, 160, 161, 233, 308, 309, 234,
+ 161, 161, 161, 161, 161, 161, 163, 163, 163, 163,
+ 163, 163, 163, 163, 163, 164, 165, 419, 196, 420,
+ 166, 165, 165, 165, 165, 165, 165, 197, 199, 264,
+ 372, 295, 257, 373, 265, 200, 209, 209, 209, 209,
+ 209, 209, 209, 209, 209, 213, 213, 213, 213, 213,
+ 213, 213, 213, 213, 214, 215, 210, 444, 443, 166,
+ 215, 215, 215, 215, 215, 215, 165, 165, 165, 165,
+
+ 165, 165, 165, 165, 165, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 294, 294, 294, 294, 294, 294,
+ 294, 294, 294, 339, 442, 352, 353, 354, 340, 355,
+ 341, 441, 342, 379, 380, 440, 439, 438, 437, 436,
+ 435, 381, 6, 6, 6, 6, 6, 43, 43, 43,
+ 43, 43, 46, 46, 46, 46, 46, 48, 48, 434,
+ 48, 57, 57, 57, 59, 59, 59, 102, 102, 102,
+ 102, 102, 111, 111, 111, 157, 157, 157, 110, 110,
+ 110, 161, 161, 161, 211, 211, 211, 433, 432, 431,
+ 430, 429, 428, 427, 426, 425, 424, 423, 422, 421,
+
+ 418, 417, 416, 415, 414, 413, 412, 411, 410, 409,
+ 408, 407, 406, 405, 404, 403, 402, 401, 400, 399,
+ 398, 397, 396, 395, 394, 393, 392, 391, 390, 389,
+ 388, 166, 387, 386, 385, 384, 383, 382, 378, 377,
+ 376, 375, 374, 371, 369, 368, 367, 366, 365, 364,
+ 363, 362, 361, 360, 359, 358, 357, 356, 351, 350,
+ 349, 347, 346, 345, 344, 343, 338, 337, 336, 335,
+ 334, 333, 332, 331, 330, 329, 328, 327, 325, 324,
+ 323, 322, 321, 320, 319, 318, 317, 316, 315, 314,
+ 313, 312, 311, 310, 307, 306, 305, 304, 303, 302,
+
+ 301, 300, 299, 298, 297, 296, 293, 292, 291, 290,
+ 289, 288, 287, 286, 285, 284, 283, 282, 281, 280,
+ 279, 278, 277, 276, 275, 274, 273, 272, 271, 270,
+ 269, 268, 267, 266, 263, 262, 261, 260, 259, 258,
+ 212, 164, 256, 255, 250, 249, 248, 247, 246, 245,
+ 244, 243, 242, 241, 240, 239, 238, 237, 236, 235,
+ 232, 231, 230, 229, 228, 227, 226, 225, 224, 223,
+ 222, 221, 220, 219, 218, 217, 216, 212, 164, 160,
+ 158, 109, 208, 207, 206, 205, 204, 203, 202, 201,
+ 198, 195, 194, 193, 192, 191, 190, 189, 188, 187,
+
+ 186, 185, 184, 183, 182, 181, 180, 179, 178, 177,
+ 176, 175, 174, 173, 172, 171, 170, 169, 168, 167,
+ 162, 109, 158, 109, 156, 155, 154, 153, 152, 151,
+ 150, 149, 148, 147, 146, 141, 140, 139, 138, 137,
+ 83, 136, 135, 134, 133, 132, 131, 130, 126, 125,
+ 124, 123, 122, 121, 120, 119, 118, 117, 114, 113,
+ 112, 60, 107, 58, 48, 47, 100, 99, 92, 79,
+ 76, 68, 67, 64, 60, 58, 48, 47, 445, 5,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445
+ } ;
+
+static yyconst flex_int16_t yy_chk[728] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3, 3, 20,
+ 3, 4, 4, 20, 4, 7, 7, 9, 463, 9,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 23, 23, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+
+ 13, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 24, 462, 24, 18, 16, 16, 16, 16,
+ 16, 16, 18, 25, 18, 27, 29, 30, 31, 29,
+ 27, 32, 25, 31, 30, 32, 35, 33, 35, 36,
+ 37, 25, 207, 36, 40, 40, 41, 207, 41, 32,
+ 33, 42, 42, 37, 43, 33, 43, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 89, 56, 101, 101, 89,
+ 461, 56, 56, 56, 56, 56, 56, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 74, 90,
+
+ 208, 74, 58, 58, 58, 58, 58, 58, 63, 90,
+ 102, 208, 102, 74, 63, 109, 109, 109, 109, 109,
+ 109, 109, 109, 109, 109, 109, 187, 270, 270, 187,
+ 109, 109, 109, 109, 109, 109, 112, 112, 112, 112,
+ 112, 112, 112, 112, 112, 112, 112, 410, 144, 410,
+ 112, 112, 112, 112, 112, 112, 112, 144, 146, 225,
+ 353, 460, 459, 353, 225, 146, 156, 156, 156, 156,
+ 156, 156, 156, 156, 156, 164, 164, 164, 164, 164,
+ 164, 164, 164, 164, 164, 164, 456, 443, 442, 164,
+ 164, 164, 164, 164, 164, 164, 165, 165, 165, 165,
+
+ 165, 165, 165, 165, 165, 215, 215, 215, 215, 215,
+ 215, 215, 215, 215, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 312, 440, 331, 331, 331, 312, 331,
+ 312, 439, 312, 360, 360, 438, 437, 436, 432, 431,
+ 430, 360, 446, 446, 446, 446, 446, 447, 447, 447,
+ 447, 447, 448, 448, 448, 448, 448, 449, 449, 429,
+ 449, 450, 450, 450, 451, 451, 451, 452, 452, 452,
+ 452, 452, 453, 453, 453, 454, 454, 454, 455, 455,
+ 455, 457, 457, 457, 458, 458, 458, 428, 424, 423,
+ 421, 420, 419, 418, 417, 416, 414, 413, 412, 411,
+
+ 409, 408, 407, 406, 405, 403, 402, 401, 400, 399,
+ 398, 397, 396, 395, 394, 393, 387, 386, 385, 384,
+ 383, 381, 380, 379, 378, 377, 375, 374, 373, 372,
+ 371, 370, 369, 366, 365, 364, 363, 362, 358, 357,
+ 356, 355, 354, 351, 347, 346, 345, 344, 343, 342,
+ 341, 340, 339, 338, 337, 336, 335, 334, 328, 327,
+ 326, 324, 319, 318, 316, 314, 311, 310, 309, 308,
+ 307, 305, 304, 303, 302, 301, 300, 298, 295, 293,
+ 292, 290, 289, 288, 287, 286, 283, 279, 277, 276,
+ 275, 274, 272, 271, 269, 268, 267, 266, 265, 264,
+
+ 263, 261, 260, 259, 258, 257, 253, 252, 251, 250,
+ 249, 248, 247, 246, 245, 244, 243, 242, 241, 240,
+ 239, 238, 237, 236, 235, 234, 233, 232, 231, 230,
+ 229, 228, 227, 226, 224, 223, 221, 219, 218, 216,
+ 213, 211, 210, 209, 206, 205, 204, 202, 201, 200,
+ 199, 198, 197, 196, 195, 194, 193, 192, 191, 189,
+ 186, 185, 183, 182, 180, 179, 178, 177, 176, 175,
+ 173, 172, 171, 170, 169, 168, 167, 163, 162, 161,
+ 159, 157, 155, 154, 153, 152, 150, 149, 148, 147,
+ 145, 143, 142, 141, 140, 139, 138, 137, 136, 135,
+
+ 134, 132, 131, 130, 129, 128, 127, 126, 125, 124,
+ 123, 122, 121, 120, 119, 118, 117, 115, 114, 113,
+ 111, 110, 108, 107, 105, 100, 99, 98, 97, 96,
+ 95, 94, 93, 92, 91, 88, 87, 86, 85, 84,
+ 82, 81, 80, 79, 78, 77, 76, 75, 73, 72,
+ 71, 70, 69, 68, 67, 66, 65, 64, 62, 61,
+ 60, 59, 57, 51, 50, 46, 39, 38, 34, 28,
+ 26, 22, 21, 19, 17, 15, 14, 10, 5, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
+ 445, 445, 445, 445, 445, 445, 445
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[84] =
+ { 0,
+1, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 1, 0, 1, 0, };
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "cf-lex.l"
+/* Copyright (C) 2011 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 cf-lex.l
+ *
+ * \author Ondrej Sury <ondrej.sury@nic.cz>
+ *
+ * \brief Server configuration structures and API.
+ *
+ * IP address conversions from BIRD, (c) 1998--2000 Martin Mares <mj@ucw.cz>
+ */
+#line 26 "cf-lex.l"
+
+#include <config.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+
+#include "common/sockaddr.h"
+#include "knot/conf/conf.h"
+#include "knot/conf/includes.h"
+#include "knot/conf/extra.h"
+#include "common/log.h"
+#include "libknotd_la-cf-parse.h" /* Automake generated header. */
+
+/* Imported symbols. */
+#define lval (yylval->tok)
+extern void cf_error(void *scanner, const char *format, ...);
+extern int (*cf_read_hook)(char *buf, size_t nbytes);
+void switch_input(const char *str, void *scanner)
+{
+ cf__scan_string(str,scanner);
+}
+
+/* Convert hex to binary. */
+static inline char xd(char d) {
+ if (d >= '0' && d <= '9') return d - '0';
+ if (d >= 'a' && d <= 'f') return d - 'a' + 10;
+ if (d >= 'A' && d <= 'F') return d - 'A' + 10;
+ return 0;
+}
+int hex2bin(const char* src, char *dst, size_t len) {
+ for (unsigned i = 0; i < len; ++i) {
+ dst[i] = (xd(src[i<<1])<<4) + xd(src[(i<<1)+1]);
+ }
+ return 0;
+}
+
+//#define YY_INPUT(buf,result,max) result = cf_read_hook(buf, max);
+#define YY_NO_UNPUT
+
+#define YY_NO_INPUT 1
+
+#line 840 "knot/conf/libknotd_la-cf-lex.c"
+
+#define INITIAL 0
+#define include 1
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#define YY_EXTRA_TYPE conf_extra_t *
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+int cf_lex_init (yyscan_t* scanner);
+
+int cf_lex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner);
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int cf_lex_destroy (yyscan_t yyscanner );
+
+int cf_get_debug (yyscan_t yyscanner );
+
+void cf_set_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE cf_get_extra (yyscan_t yyscanner );
+
+void cf_set_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *cf_get_in (yyscan_t yyscanner );
+
+void cf_set_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *cf_get_out (yyscan_t yyscanner );
+
+void cf_set_out (FILE * out_str ,yyscan_t yyscanner );
+
+int cf_get_leng (yyscan_t yyscanner );
+
+char *cf_get_text (yyscan_t yyscanner );
+
+int cf_get_lineno (yyscan_t yyscanner );
+
+void cf_set_lineno (int line_number ,yyscan_t yyscanner );
+
+int cf_get_column (yyscan_t yyscanner );
+
+void cf_set_column (int column_no ,yyscan_t yyscanner );
+
+YYSTYPE * cf_get_lval (yyscan_t yyscanner );
+
+void cf_set_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int cf_wrap (yyscan_t yyscanner );
+#else
+extern int cf_wrap (yyscan_t yyscanner );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
+#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int cf_lex \
+ (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int cf_lex \
+ (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 87 "cf-lex.l"
+
+#line 1081 "knot/conf/libknotd_la-cf-lex.c"
+
+ yylval = yylval_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ cf_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cf__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cf__load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 446 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 680 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = yyg->yy_hold_char;
+ yy_cp = yyg->yy_last_accepting_cpos;
+ yy_current_state = yyg->yy_last_accepting_state;
+ goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 88 "cf-lex.l"
+/* Ignore comments */;
+ YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 89 "cf-lex.l"
+/* Ignore whitespace */;
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 90 "cf-lex.l"
+{ return yytext[0]; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 91 "cf-lex.l"
+{ lval.t = yytext; return SYSTEM; }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 92 "cf-lex.l"
+{ lval.t = yytext; return IDENTITY; }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 93 "cf-lex.l"
+{ lval.t = yytext; return HOSTNAME; }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 94 "cf-lex.l"
+{ lval.t = yytext; return SVERSION; }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 95 "cf-lex.l"
+{ lval.t = yytext; return NSID; }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 96 "cf-lex.l"
+{ lval.t = yytext; return STORAGE; }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 97 "cf-lex.l"
+{ lval.t = yytext; return KEY; }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 98 "cf-lex.l"
+{ lval.t = yytext; return KEYS; }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 99 "cf-lex.l"
+{ lval.t = yytext; return REMOTES; }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 100 "cf-lex.l"
+{ lval.t = yytext; return GROUPS; }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 102 "cf-lex.l"
+{ lval.t = yytext; return ZONES; }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 103 "cf-lex.l"
+{ lval.t = yytext; return FILENAME; }
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 104 "cf-lex.l"
+{ lval.t = yytext; return DISABLE_ANY; }
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 105 "cf-lex.l"
+{ lval.t = yytext; return SEMANTIC_CHECKS; }
+ YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 106 "cf-lex.l"
+{ lval.t = yytext; return NOTIFY_RETRIES; }
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 107 "cf-lex.l"
+{ lval.t = yytext; return NOTIFY_TIMEOUT; }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 108 "cf-lex.l"
+{ lval.t = yytext; return DBSYNC_TIMEOUT; }
+ YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 109 "cf-lex.l"
+{ lval.t = yytext; return IXFR_FSLIMIT; }
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 110 "cf-lex.l"
+{ lval.t = yytext; return XFR_IN; }
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 111 "cf-lex.l"
+{ lval.t = yytext; return XFR_OUT; }
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 112 "cf-lex.l"
+{ lval.t = yytext; return UPDATE_IN; }
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 113 "cf-lex.l"
+{ lval.t = yytext; return NOTIFY_IN; }
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 114 "cf-lex.l"
+{ lval.t = yytext; return NOTIFY_OUT; }
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 115 "cf-lex.l"
+{ lval.t = yytext; return WORKERS; }
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 116 "cf-lex.l"
+{ lval.t = yytext; return USER; }
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 117 "cf-lex.l"
+{ lval.t = yytext; return PIDFILE; }
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 118 "cf-lex.l"
+{ lval.t = yytext; return RUNDIR; }
+ YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 119 "cf-lex.l"
+{ lval.t = yytext; return BUILD_DIFFS; }
+ YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 120 "cf-lex.l"
+{ lval.t = yytext; return MAX_CONN_IDLE; }
+ YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 121 "cf-lex.l"
+{ lval.t = yytext; return MAX_CONN_HS; }
+ YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 122 "cf-lex.l"
+{ lval.t = yytext; return MAX_CONN_REPLY; }
+ YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 123 "cf-lex.l"
+{ lval.t = yytext; return RATE_LIMIT; }
+ YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 124 "cf-lex.l"
+{ lval.t = yytext; return RATE_LIMIT_SIZE; }
+ YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 125 "cf-lex.l"
+{ lval.t = yytext; return RATE_LIMIT_SLIP; }
+ YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 126 "cf-lex.l"
+{ lval.t = yytext; return TRANSFERS; }
+ YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 128 "cf-lex.l"
+{ lval.t = yytext; return INTERFACES; }
+ YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 129 "cf-lex.l"
+{ lval.t = yytext; return ADDRESS; }
+ YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 130 "cf-lex.l"
+{ lval.t = yytext; return PORT; }
+ YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 131 "cf-lex.l"
+{ lval.t = yytext; return VIA; }
+ YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 133 "cf-lex.l"
+{ lval.t = yytext; return CONTROL; }
+ YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 134 "cf-lex.l"
+{ lval.t = yytext; return ALLOW; }
+ YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 135 "cf-lex.l"
+{ lval.t = yytext; return LISTEN_ON; }
+ YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 137 "cf-lex.l"
+{ lval.t = yytext; return LOG; }
+ YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 139 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_ANY; return LOG_SRC; }
+ YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 140 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_SERVER; return LOG_SRC; }
+ YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 141 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_ANSWER; return LOG_SRC; }
+ YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 142 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_ZONE; return LOG_SRC; }
+ YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 143 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOGT_STDOUT; return LOG_DEST; }
+ YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 144 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOGT_STDERR; return LOG_DEST; }
+ YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 145 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOGT_SYSLOG; return LOG_DEST; }
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 146 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_UPTO(LOG_DEBUG); return LOG_LEVEL; }
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 147 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_MASK(LOG_DEBUG); return LOG_LEVEL; }
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 148 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_MASK(LOG_INFO); return LOG_LEVEL; }
+ YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 149 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_MASK(LOG_NOTICE); return LOG_LEVEL; }
+ YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 150 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_MASK(LOG_WARNING); return LOG_LEVEL; }
+ YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 151 "cf-lex.l"
+{ lval.t = yytext; lval.i = LOG_MASK(LOG_ERR); return LOG_LEVEL; }
+ YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 153 "cf-lex.l"
+{
+ lval.t = yytext;
+ lval.i = 0;
+ if (strcmp(yytext, "on") == 0) {
+ lval.i = 1;
+ }
+ return BOOL;
+}
+ YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 162 "cf-lex.l"
+BEGIN(include);
+ YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 164 "cf-lex.l"
+{
+ size_t mpos = strlen(yytext) - 1;
+ char multiplier = yytext[mpos];
+ yytext[mpos] = '\0';
+ lval.i = atoi(yytext);
+ if (lval.i < 1) {
+ cf_error(yyscanner, "interval must be a positive integer");
+ return END;
+ }
+
+ /* Handle multiplier. */
+ switch(multiplier) {
+ case 'm': lval.i *= 60; break; /* minutes */
+ case 'h': lval.i *= 60*60; break; /* hours */
+ case 'd': lval.i *= 24*60*60; break; /* days */
+ case 's': /* seconds */
+ default: break;
+ }
+
+ return INTERVAL;
+}
+ YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 186 "cf-lex.l"
+{
+ size_t mpos = strlen(yytext) - 1;
+ char multiplier = yytext[mpos];
+ yytext[mpos] = '\0';
+ lval.i = atol(yytext);
+ if (lval.i < 1) {
+ cf_error(yyscanner, "size must be a positive integer");
+ return END;
+ }
+
+ /* Handle multiplier. */
+ switch(multiplier) {
+ case 'k': lval.l = lval.i * 1024; break; /* kB */
+ case 'M': lval.l = lval.i * 1024*1024; break; /* MB */
+ case 'G': lval.l = lval.i * 1024*1024*1024; break; /* GB */
+ default: break;
+ }
+
+ return SIZE;
+}
+ YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 207 "cf-lex.l"
+{
+ lval.i = atol(yytext);
+ return NUM;
+}
+ YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 212 "cf-lex.l"
+{
+ unsigned char buf[sizeof(struct in_addr)];
+ if (inet_pton(AF_INET, yytext, buf)) {
+ lval.t = strdup(yytext);
+ return IPA;
+ }
+ cf_error(yyscanner, "Invalid IP address.");
+}
+ YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 221 "cf-lex.l"
+{
+#ifdef DISABLE_IPV6
+ lval.t = strdup(yytext);
+ cf_error(yyscanner, "IPv6 address support not compiled.");
+ return TEXT;
+#else
+ unsigned char buf[sizeof(struct in6_addr)];
+ yytext[strlen(yytext)-1] = '\0';
+ if (inet_pton(AF_INET6, yytext+1, buf)) {
+ lval.t = strdup(yytext+1);
+ return IPA6;
+ }
+ cf_error(yyscanner, "Invalid IPv6 address.");
+#endif
+ }
+ YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 237 "cf-lex.l"
+{
+#ifdef DISABLE_IPV6
+ lval.t = strdup(yytext);
+ cf_error(yyscanner, "IPv6 address support not compiled.");
+ return TEXT;
+#else
+ unsigned char buf[sizeof(struct in6_addr)];
+ if (inet_pton(AF_INET6, yytext, buf)) {
+ lval.t = strdup(yytext);
+ return IPA6;
+ }
+ cf_error(yyscanner, "Invalid IPv6 address.");
+#endif
+}
+ YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 252 "cf-lex.l"
+{
+ lval.t = NULL;
+ lval.l = 0;
+ yytext = yytext + 2; /* Cut off 0x */
+ size_t dlen = strlen(yytext);
+ if (dlen % 2 == 1) {
+ cf_error(yyscanner, "Invalid hex-string length.");
+ } else {
+ dlen = dlen / 2;
+ lval.t = malloc((dlen) * sizeof(char));
+ if (lval.t == NULL) {
+ cf_error(yyscanner, "Out of memory when allocating hex-string.\n");
+ } else {
+ memset(lval.t, 0, dlen);
+ if (hex2bin(yytext, lval.t, dlen) < 0) {
+ cf_error(yyscanner, "Failed to convert hex-string to binary.\n");
+ } else {
+ lval.l = dlen;
+ }
+ }
+ }
+
+ return HEXSTR;
+}
+ YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 277 "cf-lex.l"
+{ lval.alg = KNOT_TSIG_ALG_GSS_TSIG; return TSIG_ALGO_NAME; }
+ YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 278 "cf-lex.l"
+{ lval.alg = KNOT_TSIG_ALG_HMAC_MD5; return TSIG_ALGO_NAME; }
+ YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 279 "cf-lex.l"
+{ lval.alg = KNOT_TSIG_ALG_HMAC_SHA1; return TSIG_ALGO_NAME; }
+ YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 280 "cf-lex.l"
+{ lval.alg = KNOT_TSIG_ALG_HMAC_SHA224; return TSIG_ALGO_NAME; }
+ YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 281 "cf-lex.l"
+{ lval.alg = KNOT_TSIG_ALG_HMAC_SHA256; return TSIG_ALGO_NAME; }
+ YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 282 "cf-lex.l"
+{ lval.alg = KNOT_TSIG_ALG_HMAC_SHA384; return TSIG_ALGO_NAME; }
+ YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 283 "cf-lex.l"
+{ lval.alg = KNOT_TSIG_ALG_HMAC_SHA512; return TSIG_ALGO_NAME; }
+ YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 285 "cf-lex.l"
+{
+ yytext[yyleng-1] = 0;
+ lval.t = strdup(yytext + 1);
+ return TEXT;
+}
+ YY_BREAK
+case 77:
+/* rule 77 can match eol */
+YY_RULE_SETUP
+#line 291 "cf-lex.l"
+cf_error(yyscanner, "Unterminated string.");
+ YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 293 "cf-lex.l"
+{
+ lval.t = strdup(yytext);
+ return TEXT /* Last resort, alphanumeric word. */;
+}
+ YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 298 "cf-lex.l"
+/* Optional : in assignments. */;
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(include):
+#line 300 "cf-lex.l"
+{
+ char *name = conf_includes_pop(yyextra->includes);
+ free(name);
+ cf_pop_buffer_state(yyscanner);
+ if (!YY_CURRENT_BUFFER)
+ return END;
+}
+ YY_BREAK
+case 80:
+/* rule 80 can match eol */
+YY_RULE_SETUP
+#line 308 "cf-lex.l"
+
+ YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 309 "cf-lex.l"
+{
+ BEGIN(INITIAL);
+
+ // silently skip includes if there was a former error
+ if (yyextra->error) {
+ return END;
+ }
+
+ // remove quotes
+ yytext += 1;
+ yyleng -= 2;
+ yytext[yyleng] = '\0';
+
+ if (!conf_includes_push(yyextra->includes, yytext)) {
+ cf_error(yyscanner, "includes nested too deeply");
+ return END;
+ }
+
+ // retrieved relative to previous config
+ char *filename = conf_includes_top(yyextra->includes);
+
+ FILE *included = fopen(filename, "r");
+ if (!included) {
+ cf_error(yyscanner, "cannot open file '%s'", filename);
+ conf_includes_pop(yyextra->includes);
+ free(filename);
+ return END;
+ }
+
+ YY_BUFFER_STATE bs = cf__create_buffer(included,YY_BUF_SIZE,yyscanner);
+ cf_push_buffer_state(bs,yyscanner);
+}
+ YY_BREAK
+case 82:
+/* rule 82 can match eol */
+YY_RULE_SETUP
+#line 342 "cf-lex.l"
+cf_error(yyscanner, "Unterminated string.");
+ YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 344 "cf-lex.l"
+ECHO;
+ YY_BREAK
+#line 1753 "knot/conf/libknotd_la-cf-lex.c"
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * cf_lex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( cf_wrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of cf_lex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) (yyg->yy_c_buf_p - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ cf_realloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ cf_restart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) cf_realloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 446 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+ register char *yy_cp = yyg->yy_c_buf_p;
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ yyg->yy_last_accepting_state = yy_current_state;
+ yyg->yy_last_accepting_cpos = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 446 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 445);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ cf_restart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( cf_wrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ if ( c == '\n' )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void cf_restart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ cf_ensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ cf__create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ cf__init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ cf__load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void cf__switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * cf_pop_buffer_state();
+ * cf_push_buffer_state(new_buffer);
+ */
+ cf_ensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ cf__load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (cf_wrap()) processing, but the only time this flag
+ * is looked at is after cf_wrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void cf__load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE cf__create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) cf_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cf__create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) cf_alloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cf__create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ cf__init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with cf__create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void cf__delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ cf_free((void *) b->yy_ch_buf ,yyscanner );
+
+ cf_free((void *) b ,yyscanner );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a cf_restart() or at EOF.
+ */
+ static void cf__init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ cf__flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then cf__init_buffer was _probably_
+ * called from cf_restart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void cf__flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ cf__load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void cf_push_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ cf_ensure_buffer_stack(yyscanner);
+
+ /* This block is copied from cf__switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from cf__switch_to_buffer. */
+ cf__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void cf_pop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ cf__delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ cf__load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void cf_ensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)cf_alloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in cf_ensure_buffer_stack()" );
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)cf_realloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+ if ( ! yyg->yy_buffer_stack )
+ YY_FATAL_ERROR( "out of dynamic memory in cf_ensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE cf__scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) cf_alloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in cf__scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ cf__switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to cf_lex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * cf__scan_bytes() instead.
+ */
+YY_BUFFER_STATE cf__scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return cf__scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to cf_lex() will
+ * scan from a @e copy of @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE cf__scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) cf_alloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in cf__scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = cf__scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in cf__scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE cf_get_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int cf_get_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int cf_get_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *cf_get_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *cf_get_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int cf_get_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *cf_get_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void cf_set_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void cf_set_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "cf_set_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void cf_set_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "cf_set_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see cf__switch_to_buffer
+ */
+void cf_set_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void cf_set_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int cf_get_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void cf_set_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * cf_get_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void cf_set_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+/* User-visible API */
+
+/* cf_lex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int cf_lex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cf_alloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+/* cf_lex_init_extra has the same functionality as cf_lex_init, but follows the
+ * convention of taking the scanner as the last argument. Note however, that
+ * this is a *pointer* to a scanner, as it will be allocated by this call (and
+ * is the reason, too, why this function also must handle its own declaration).
+ * The user defined value in the first argument will be available to cf_alloc in
+ * the yyextra field.
+ */
+
+int cf_lex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals )
+
+{
+ struct yyguts_t dummy_yyguts;
+
+ cf_set_extra (yy_user_defined, &dummy_yyguts);
+
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) cf_alloc ( sizeof( struct yyguts_t ), &dummy_yyguts );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in
+ yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ cf_set_extra (yy_user_defined, *ptr_yy_globals);
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from cf_lex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * cf_lex_init()
+ */
+ return 0;
+}
+
+/* cf_lex_destroy is for both reentrant and non-reentrant scanners. */
+int cf_lex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ cf__delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ cf_pop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ cf_free(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ cf_free(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * cf_lex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ cf_free ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *cf_alloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *cf_realloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void cf_free (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see cf_realloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 344 "cf-lex.l"
+
+
+
diff --git a/src/knot/conf/libknotd_la-cf-parse.c b/src/knot/conf/libknotd_la-cf-parse.c
new file mode 100644
index 0000000..52280ca
--- /dev/null
+++ b/src/knot/conf/libknotd_la-cf-parse.c
@@ -0,0 +1,3420 @@
+/* A Bison parser, made by GNU Bison 2.5. */
+
+/* Bison implementation for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.5"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Push parsers. */
+#define YYPUSH 0
+
+/* Pull parsers. */
+#define YYPULL 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names. */
+#define yyparse cf_parse
+#define yylex cf_lex
+#define yyerror cf_error
+#define yylval cf_lval
+#define yychar cf_char
+#define yydebug cf_debug
+#define yynerrs cf_nerrs
+
+
+/* Copy the first part of user declarations. */
+
+/* Line 268 of yacc.c */
+#line 23 "cf-parse.y"
+
+/* Headers */
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
+#include "common/sockaddr.h"
+#include "libknot/dname.h"
+#include "libknot/binary.h"
+#include "knot/conf/conf.h"
+#include "libknotd_la-cf-parse.h" /* Automake generated header. */
+
+extern int cf_lex (YYSTYPE *lvalp, void *scanner);
+extern void cf_error(void *scanner, const char *format, ...);
+extern conf_t *new_config;
+static conf_iface_t *this_iface = 0;
+static conf_iface_t *this_remote = 0;
+static conf_zone_t *this_zone = 0;
+static conf_group_t *this_group = 0;
+static list *this_list = 0;
+static conf_log_t *this_log = 0;
+static conf_log_map_t *this_logmap = 0;
+//#define YYERROR_VERBOSE 1
+
+static void conf_init_iface(void *scanner, char* ifname, int port)
+{
+ this_iface = malloc(sizeof(conf_iface_t));
+ if (this_iface == NULL) {
+ cf_error(scanner, "not enough memory when allocating interface");
+ return;
+ }
+ memset(this_iface, 0, sizeof(conf_iface_t));
+ this_iface->name = ifname;
+ this_iface->port = port;
+}
+
+static void conf_start_iface(void *scanner, char* ifname)
+{
+ conf_init_iface(scanner, ifname, -1);
+ add_tail(&new_config->ifaces, &this_iface->n);
+ ++new_config->ifaces_count;
+}
+
+static conf_iface_t *conf_get_remote(const char *name)
+{
+ conf_iface_t *remote;
+ WALK_LIST (remote, new_config->remotes) {
+ if (strcmp(remote->name, name) == 0) {
+ return remote;
+ }
+ }
+
+ return NULL;
+}
+
+static void conf_start_remote(void *scanner, char *remote)
+{
+ if (conf_get_remote(remote) != NULL) {
+ cf_error(scanner, "remote '%s' already defined", remote);
+ return;
+ }
+
+ this_remote = malloc(sizeof(conf_iface_t));
+ if (this_remote == NULL) {
+ cf_error(scanner, "not enough memory when allocating remote");
+ return;
+ }
+
+ memset(this_remote, 0, sizeof(conf_iface_t));
+ this_remote->name = remote;
+ add_tail(&new_config->remotes, &this_remote->n);
+ sockaddr_init(&this_remote->via, -1);
+ ++new_config->remotes_count;
+}
+
+static void conf_remote_set_via(void *scanner, char *item) {
+ /* Find existing node in interfaces. */
+ node* r = 0; conf_iface_t* found = 0;
+ WALK_LIST (r, new_config->ifaces) {
+ if (strcmp(((conf_iface_t*)r)->name, item) == 0) {
+ found = (conf_iface_t*)r;
+ break;
+ }
+ }
+
+ /* Check */
+ if (!found) {
+ cf_error(scanner, "interface '%s' is not defined", item);
+ } else {
+ sockaddr_set(&this_remote->via, found->family, found->address, 0);
+ }
+}
+
+static conf_group_t *conf_get_group(const char *name)
+{
+ conf_group_t *group;
+ WALK_LIST (group, new_config->groups) {
+ if (strcmp(group->name, name) == 0) {
+ return group;
+ }
+ }
+
+ return NULL;
+}
+
+static void conf_start_group(void *scanner, char *name)
+{
+ conf_group_t *group = conf_get_group(name);
+ if (group) {
+ cf_error(scanner, "group '%s' already defined", name);
+ return;
+ }
+
+ if (conf_get_remote(name) != NULL) {
+ cf_error(scanner, "group name '%s' conflicts with remote name",
+ name);
+ free(name);
+ return;
+ }
+
+ /* Add new group. */
+
+ group = calloc(1, sizeof(conf_group_t));
+ if (!group) {
+ cf_error(scanner, "out of memory");
+ free(name);
+ return;
+ }
+
+ group->name = name;
+ init_list(&group->remotes);
+
+ add_tail(&new_config->groups, &group->n);
+ this_group = group;
+}
+
+static void conf_add_member_into_group(void *scanner, char *name)
+{
+ if (!this_group) {
+ cf_error(scanner, "parser error, variable 'this_group' null");
+ free(name);
+ return;
+ }
+
+ if (conf_get_remote(name) == NULL) {
+ cf_error(scanner, "remote '%s' is not defined", name);
+ free(name);
+ return;
+ }
+
+ // add the remote into the group while silently ignoring duplicates
+
+ conf_group_remote_t *remote;
+ node *n;
+ WALK_LIST (n, this_group->remotes) {
+ remote = (conf_group_remote_t *)n;
+ if (strcmp(remote->name, name) == 0) {
+ free(name);
+ return;
+ }
+ }
+
+ remote = calloc(1, sizeof(conf_group_remote_t));
+ remote->name = name;
+ add_tail(&this_group->remotes, &remote->n);
+}
+
+static bool set_remote_or_group(void *scanner, char *name,
+ void (*install)(void *, conf_iface_t *))
+{
+ // search remotes
+
+ conf_iface_t *remote = conf_get_remote(name);
+ if (remote) {
+ install(scanner, remote);
+ return true;
+ }
+
+ // search groups
+
+ conf_group_t *group = conf_get_group(name);
+ if (group) {
+ conf_group_remote_t *group_remote;
+ WALK_LIST (group_remote, group->remotes) {
+ remote = conf_get_remote(group_remote->name);
+ if (!remote)
+ continue;
+ install(scanner, remote);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+static void conf_acl_item_install(void *scanner, conf_iface_t *found)
+{
+ // silently skip duplicates
+
+ conf_remote_t *remote;
+ WALK_LIST (remote, *this_list) {
+ if (remote->remote == found) {
+ return;
+ }
+ }
+
+ // additional check for transfers
+
+ if ((this_list == &this_zone->acl.xfr_in ||
+ this_list == &this_zone->acl.notify_out) && found->port == 0)
+ {
+ cf_error(scanner, "remote specified for XFR/IN or "
+ "NOTIFY/OUT needs to have valid port!");
+ return;
+ }
+
+ // add into the list
+
+ remote = malloc(sizeof(conf_remote_t));
+ if (!remote) {
+ cf_error(scanner, "out of memory");
+ return;
+ }
+
+ remote->remote = found;
+ add_tail(this_list, &remote->n);
+}
+
+static void conf_acl_item(void *scanner, char *item)
+{
+ if (!set_remote_or_group(scanner, item, conf_acl_item_install)) {
+ cf_error(scanner, "remote or group '%s' not defined", item);
+ }
+
+ free(item);
+}
+
+static int conf_key_exists(void *scanner, char *item)
+{
+ /* Find existing node in keys. */
+ knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item), 0);
+ conf_key_t* r = 0;
+ WALK_LIST (r, new_config->keys) {
+ if (knot_dname_compare(r->k.name, sample) == 0) {
+ cf_error(scanner, "key '%s' is already defined", item);
+ knot_dname_free(&sample);
+ return 1;
+ }
+ }
+
+ knot_dname_free(&sample);
+ return 0;
+}
+
+static int conf_key_add(void *scanner, knot_tsig_key_t **key, char *item)
+{
+ /* Reset */
+ *key = 0;
+
+ /* Find in keys */
+ knot_dname_t *sample = knot_dname_new_from_str(item, strlen(item), 0);
+
+ conf_key_t* r = 0;
+ WALK_LIST (r, new_config->keys) {
+ if (knot_dname_compare(r->k.name, sample) == 0) {
+ *key = &r->k;
+ knot_dname_free(&sample);
+ return 0;
+ }
+ }
+
+ cf_error(scanner, "key '%s' is not defined", item);
+ knot_dname_free(&sample);
+ return 1;
+}
+
+static void conf_zone_start(void *scanner, char *name) {
+ this_zone = malloc(sizeof(conf_zone_t));
+ if (this_zone == NULL || name == NULL) {
+ cf_error(scanner, "out of memory while allocating zone config");
+ return;
+ }
+ memset(this_zone, 0, sizeof(conf_zone_t));
+ this_zone->enable_checks = -1; // Default policy applies
+ this_zone->notify_timeout = -1; // Default policy applies
+ this_zone->notify_retries = 0; // Default policy applies
+ this_zone->ixfr_fslimit = -1; // Default policy applies
+ this_zone->dbsync_timeout = -1; // Default policy applies
+ this_zone->disable_any = -1; // Default policy applies
+ this_zone->build_diffs = -1; // Default policy applies
+
+ // Append mising dot to ensure FQDN
+ size_t nlen = strlen(name);
+ if (name[nlen - 1] != '.') {
+ this_zone->name = malloc(nlen + 2);
+ if (this_zone->name != NULL) {
+ memcpy(this_zone->name, name, nlen);
+ this_zone->name[nlen] = '.';
+ this_zone->name[++nlen] = '\0';
+ }
+ free(name);
+ } else {
+ this_zone->name = name; /* Already FQDN */
+ }
+
+ /* Initialize ACL lists. */
+ init_list(&this_zone->acl.xfr_in);
+ init_list(&this_zone->acl.xfr_out);
+ init_list(&this_zone->acl.notify_in);
+ init_list(&this_zone->acl.notify_out);
+ init_list(&this_zone->acl.update_in);
+
+ /* Check domain name. */
+ knot_dname_t *dn = NULL;
+ if (this_zone->name != NULL) {
+ dn = knot_dname_new_from_str(this_zone->name, nlen, 0);
+ }
+ if (dn == NULL) {
+ free(this_zone->name);
+ free(this_zone);
+ this_zone = NULL;
+ cf_error(scanner, "invalid zone origin");
+ } else {
+ /* Check for duplicates. */
+ if (hattrie_tryget(new_config->names, (const char*)dn->name, dn->size) != NULL) {
+ cf_error(scanner, "zone '%s' is already present, refusing to "
+ "duplicate", this_zone->name);
+ knot_dname_free(&dn);
+ free(this_zone->name);
+ this_zone->name = NULL;
+ /* Must not free, some versions of flex might continue after error and segfault.
+ * free(this_zone); this_zone = NULL;
+ */
+ return;
+ }
+
+ /* Directly discard dname, won't be needed. */
+ add_tail(&new_config->zones, &this_zone->n);
+ *hattrie_get(new_config->names, (const char*)dn->name, dn->size) = (void *)1;
+ ++new_config->zones_count;
+ knot_dname_free(&dn);
+ }
+}
+
+static int conf_mask(void* scanner, int nval, int prefixlen) {
+ if (nval < 0 || nval > prefixlen) {
+ cf_error(scanner, "IPv%c subnet prefix '%d' is out of range <0,%d>",
+ prefixlen == IPV4_PREFIXLEN ? '4' : '6', nval, prefixlen);
+ return prefixlen; /* single host */
+ }
+ return nval;
+}
+
+
+
+/* Line 268 of yacc.c */
+#line 438 "knot/conf/libknotd_la-cf-parse.c"
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ END = 258,
+ INVALID_TOKEN = 259,
+ TEXT = 260,
+ HEXSTR = 261,
+ NUM = 262,
+ INTERVAL = 263,
+ SIZE = 264,
+ BOOL = 265,
+ SYSTEM = 266,
+ IDENTITY = 267,
+ HOSTNAME = 268,
+ SVERSION = 269,
+ NSID = 270,
+ STORAGE = 271,
+ KEY = 272,
+ KEYS = 273,
+ TSIG_ALGO_NAME = 274,
+ WORKERS = 275,
+ USER = 276,
+ RUNDIR = 277,
+ PIDFILE = 278,
+ REMOTES = 279,
+ GROUPS = 280,
+ ZONES = 281,
+ FILENAME = 282,
+ DISABLE_ANY = 283,
+ SEMANTIC_CHECKS = 284,
+ NOTIFY_RETRIES = 285,
+ NOTIFY_TIMEOUT = 286,
+ DBSYNC_TIMEOUT = 287,
+ IXFR_FSLIMIT = 288,
+ XFR_IN = 289,
+ XFR_OUT = 290,
+ UPDATE_IN = 291,
+ NOTIFY_IN = 292,
+ NOTIFY_OUT = 293,
+ BUILD_DIFFS = 294,
+ MAX_CONN_IDLE = 295,
+ MAX_CONN_HS = 296,
+ MAX_CONN_REPLY = 297,
+ RATE_LIMIT = 298,
+ RATE_LIMIT_SIZE = 299,
+ RATE_LIMIT_SLIP = 300,
+ TRANSFERS = 301,
+ INTERFACES = 302,
+ ADDRESS = 303,
+ PORT = 304,
+ IPA = 305,
+ IPA6 = 306,
+ VIA = 307,
+ CONTROL = 308,
+ ALLOW = 309,
+ LISTEN_ON = 310,
+ LOG = 311,
+ LOG_DEST = 312,
+ LOG_SRC = 313,
+ LOG_LEVEL = 314
+ };
+#endif
+/* Tokens. */
+#define END 258
+#define INVALID_TOKEN 259
+#define TEXT 260
+#define HEXSTR 261
+#define NUM 262
+#define INTERVAL 263
+#define SIZE 264
+#define BOOL 265
+#define SYSTEM 266
+#define IDENTITY 267
+#define HOSTNAME 268
+#define SVERSION 269
+#define NSID 270
+#define STORAGE 271
+#define KEY 272
+#define KEYS 273
+#define TSIG_ALGO_NAME 274
+#define WORKERS 275
+#define USER 276
+#define RUNDIR 277
+#define PIDFILE 278
+#define REMOTES 279
+#define GROUPS 280
+#define ZONES 281
+#define FILENAME 282
+#define DISABLE_ANY 283
+#define SEMANTIC_CHECKS 284
+#define NOTIFY_RETRIES 285
+#define NOTIFY_TIMEOUT 286
+#define DBSYNC_TIMEOUT 287
+#define IXFR_FSLIMIT 288
+#define XFR_IN 289
+#define XFR_OUT 290
+#define UPDATE_IN 291
+#define NOTIFY_IN 292
+#define NOTIFY_OUT 293
+#define BUILD_DIFFS 294
+#define MAX_CONN_IDLE 295
+#define MAX_CONN_HS 296
+#define MAX_CONN_REPLY 297
+#define RATE_LIMIT 298
+#define RATE_LIMIT_SIZE 299
+#define RATE_LIMIT_SLIP 300
+#define TRANSFERS 301
+#define INTERFACES 302
+#define ADDRESS 303
+#define PORT 304
+#define IPA 305
+#define IPA6 306
+#define VIA 307
+#define CONTROL 308
+#define ALLOW 309
+#define LISTEN_ON 310
+#define LOG 311
+#define LOG_DEST 312
+#define LOG_SRC 313
+#define LOG_LEVEL 314
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 293 of yacc.c */
+#line 386 "cf-parse.y"
+
+ struct {
+ char *t;
+ long i;
+ size_t l;
+ knot_tsig_algorithm_t alg;
+ } tok;
+
+
+
+/* Line 293 of yacc.c */
+#line 603 "knot/conf/libknotd_la-cf-parse.c"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 343 of yacc.c */
+#line 615 "knot/conf/libknotd_la-cf-parse.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if defined YYENABLE_NLS && YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined EXIT_SUCCESS \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss_alloc;
+ YYSTYPE yyvs_alloc;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+# define YYCOPY_NEEDED 1
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+#if defined YYCOPY_NEEDED && YYCOPY_NEEDED
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+#endif /* !YYCOPY_NEEDED */
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 3
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 280
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 66
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 34
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 146
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 290
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 314
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 65, 2, 2, 64, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 60,
+ 2, 2, 2, 2, 61, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 62, 2, 63, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+ 55, 56, 57, 58, 59
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint16 yyprhs[] =
+{
+ 0, 0, 3, 6, 7, 10, 11, 13, 15, 17,
+ 19, 21, 23, 24, 29, 34, 41, 46, 53, 56,
+ 62, 65, 70, 75, 80, 85, 90, 95, 100, 105,
+ 111, 116, 121, 126, 131, 136, 141, 146, 151, 156,
+ 161, 164, 170, 171, 173, 175, 177, 179, 181, 182,
+ 187, 192, 199, 206, 211, 218, 225, 230, 235, 240,
+ 245, 248, 254, 256, 257, 259, 263, 265, 268, 274,
+ 276, 278, 280, 282, 284, 285, 287, 289, 291, 293,
+ 295, 296, 300, 304, 305, 309, 310, 312, 314, 316,
+ 318, 320, 322, 326, 328, 331, 337, 341, 346, 351,
+ 356, 361, 366, 371, 376, 381, 386, 391, 394, 398,
+ 403, 408, 413, 418, 423, 428, 433, 438, 443, 444,
+ 446, 450, 454, 455, 459, 461, 464, 465, 466, 472,
+ 478, 483, 485, 487, 490, 496, 501, 507, 511, 513,
+ 516, 519, 522, 525, 528, 531, 534
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 67, 0, -1, 68, 3, -1, -1, 68, 99, -1,
+ -1, 5, -1, 24, -1, 58, -1, 56, -1, 59,
+ -1, 53, -1, -1, 70, 49, 7, 60, -1, 70,
+ 48, 50, 60, -1, 70, 48, 50, 61, 7, 60,
+ -1, 70, 48, 51, 60, -1, 70, 48, 51, 61,
+ 7, 60, -1, 47, 62, -1, 71, 69, 62, 70,
+ 63, -1, 11, 62, -1, 72, 14, 5, 60, -1,
+ 72, 12, 5, 60, -1, 72, 13, 5, 60, -1,
+ 72, 15, 6, 60, -1, 72, 15, 5, 60, -1,
+ 72, 16, 5, 60, -1, 72, 22, 5, 60, -1,
+ 72, 23, 5, 60, -1, 72, 17, 19, 5, 60,
+ -1, 72, 20, 7, 60, -1, 72, 21, 5, 60,
+ -1, 72, 40, 8, 60, -1, 72, 41, 8, 60,
+ -1, 72, 42, 8, 60, -1, 72, 43, 7, 60,
+ -1, 72, 44, 9, 60, -1, 72, 44, 7, 60,
+ -1, 72, 45, 7, 60, -1, 72, 46, 7, 60,
+ -1, 18, 62, -1, 73, 5, 19, 5, 60, -1,
+ -1, 5, -1, 58, -1, 56, -1, 59, -1, 53,
+ -1, -1, 75, 49, 7, 60, -1, 75, 48, 50,
+ 60, -1, 75, 48, 50, 64, 7, 60, -1, 75,
+ 48, 50, 61, 7, 60, -1, 75, 48, 51, 60,
+ -1, 75, 48, 51, 64, 7, 60, -1, 75, 48,
+ 51, 61, 7, 60, -1, 75, 17, 5, 60, -1,
+ 75, 52, 50, 60, -1, 75, 52, 51, 60, -1,
+ 75, 52, 5, 60, -1, 24, 62, -1, 76, 74,
+ 62, 75, 63, -1, 5, -1, -1, 77, -1, 78,
+ 65, 77, -1, 5, -1, 25, 62, -1, 80, 79,
+ 62, 78, 63, -1, 34, -1, 35, -1, 37, -1,
+ 38, -1, 36, -1, -1, 5, -1, 58, -1, 56,
+ -1, 59, -1, 53, -1, -1, 83, 82, 65, -1,
+ 83, 82, 60, -1, -1, 84, 5, 60, -1, -1,
+ 21, -1, 24, -1, 58, -1, 56, -1, 59, -1,
+ 53, -1, 7, 64, 5, -1, 5, -1, 85, 62,
+ -1, 86, 81, 62, 84, 63, -1, 86, 81, 83,
+ -1, 86, 27, 5, 60, -1, 86, 39, 10, 60,
+ -1, 86, 29, 10, 60, -1, 86, 28, 10, 60,
+ -1, 86, 32, 7, 60, -1, 86, 32, 8, 60,
+ -1, 86, 33, 9, 60, -1, 86, 33, 7, 60,
+ -1, 86, 30, 7, 60, -1, 86, 31, 7, 60,
+ -1, 26, 62, -1, 87, 86, 63, -1, 87, 28,
+ 10, 60, -1, 87, 39, 10, 60, -1, 87, 29,
+ 10, 60, -1, 87, 33, 9, 60, -1, 87, 33,
+ 7, 60, -1, 87, 30, 7, 60, -1, 87, 31,
+ 7, 60, -1, 87, 32, 7, 60, -1, 87, 32,
+ 8, 60, -1, -1, 88, -1, 89, 59, 65, -1,
+ 89, 59, 60, -1, -1, 90, 58, 89, -1, 57,
+ -1, 27, 5, -1, -1, -1, 94, 91, 62, 90,
+ 63, -1, 94, 92, 62, 90, 63, -1, 56, 62,
+ 94, 93, -1, 55, -1, 54, -1, 53, 62, -1,
+ 98, 96, 62, 70, 63, -1, 98, 96, 5, 60,
+ -1, 98, 97, 62, 84, 63, -1, 98, 97, 83,
+ -1, 60, -1, 72, 63, -1, 71, 63, -1, 73,
+ 63, -1, 76, 63, -1, 80, 63, -1, 87, 63,
+ -1, 95, 63, -1, 98, 63, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 448, 448, 450, 452, 455, 456, 457, 458, 459,
+ 460, 461, 464, 465, 472, 480, 493, 501, 517, 518,
+ 526, 527, 528, 529, 530, 531, 532, 533, 534, 539,
+ 544, 551, 572, 573, 574, 575, 576, 577, 578, 579,
+ 583, 584, 635, 636, 637, 638, 639, 640, 643, 644,
+ 651, 660, 669, 683, 692, 701, 715, 723, 727, 731,
+ 738, 739, 747, 750, 752, 753, 757, 761, 762, 766,
+ 769, 772, 775, 778, 783, 784, 785, 786, 787, 788,
+ 791, 792, 793, 796, 797, 825, 826, 827, 828, 829,
+ 830, 831, 832, 849, 853, 854, 855, 856, 857, 858,
+ 859, 860, 861, 862, 863, 864, 871, 881, 882, 883,
+ 884, 885, 886, 887, 888, 895, 902, 909, 912, 921,
+ 922, 923, 926, 927, 933, 956, 983, 987, 988, 989,
+ 992, 995, 999, 1005, 1006, 1013, 1019, 1020, 1023, 1023,
+ 1023, 1023, 1023, 1023, 1023, 1023, 1023
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "END", "INVALID_TOKEN", "TEXT", "HEXSTR",
+ "NUM", "INTERVAL", "SIZE", "BOOL", "SYSTEM", "IDENTITY", "HOSTNAME",
+ "SVERSION", "NSID", "STORAGE", "KEY", "KEYS", "TSIG_ALGO_NAME",
+ "WORKERS", "USER", "RUNDIR", "PIDFILE", "REMOTES", "GROUPS", "ZONES",
+ "FILENAME", "DISABLE_ANY", "SEMANTIC_CHECKS", "NOTIFY_RETRIES",
+ "NOTIFY_TIMEOUT", "DBSYNC_TIMEOUT", "IXFR_FSLIMIT", "XFR_IN", "XFR_OUT",
+ "UPDATE_IN", "NOTIFY_IN", "NOTIFY_OUT", "BUILD_DIFFS", "MAX_CONN_IDLE",
+ "MAX_CONN_HS", "MAX_CONN_REPLY", "RATE_LIMIT", "RATE_LIMIT_SIZE",
+ "RATE_LIMIT_SLIP", "TRANSFERS", "INTERFACES", "ADDRESS", "PORT", "IPA",
+ "IPA6", "VIA", "CONTROL", "ALLOW", "LISTEN_ON", "LOG", "LOG_DEST",
+ "LOG_SRC", "LOG_LEVEL", "';'", "'@'", "'{'", "'}'", "'/'", "','",
+ "$accept", "config", "conf_entries", "interface_start", "interface",
+ "interfaces", "system", "keys", "remote_start", "remote", "remotes",
+ "group_member", "group", "group_start", "groups", "zone_acl_start",
+ "zone_acl_item", "zone_acl_list", "zone_acl", "zone_start", "zone",
+ "zones", "log_prios_start", "log_prios", "log_src", "log_dest",
+ "log_file", "log_end", "log_start", "log", "ctl_listen_start",
+ "ctl_allow_start", "control", "conf", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 314,
+ 59, 64, 123, 125, 47, 44
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 66, 67, 68, 68, 69, 69, 69, 69, 69,
+ 69, 69, 70, 70, 70, 70, 70, 70, 71, 71,
+ 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+ 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+ 73, 73, 74, 74, 74, 74, 74, 74, 75, 75,
+ 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 76, 76, 77, 78, 78, 78, 79, 80, 80, 81,
+ 81, 81, 81, 81, 82, 82, 82, 82, 82, 82,
+ 83, 83, 83, 84, 84, 85, 85, 85, 85, 85,
+ 85, 85, 85, 85, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 87, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 88, 89,
+ 89, 89, 90, 90, 91, 92, 93, 94, 94, 94,
+ 95, 96, 97, 98, 98, 98, 98, 98, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 2, 0, 2, 0, 1, 1, 1, 1,
+ 1, 1, 0, 4, 4, 6, 4, 6, 2, 5,
+ 2, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 2, 5, 0, 1, 1, 1, 1, 1, 0, 4,
+ 4, 6, 6, 4, 6, 6, 4, 4, 4, 4,
+ 2, 5, 1, 0, 1, 3, 1, 2, 5, 1,
+ 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 3, 3, 0, 3, 0, 1, 1, 1, 1,
+ 1, 1, 3, 1, 2, 5, 3, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 2, 3, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 0, 1,
+ 3, 3, 0, 3, 1, 2, 0, 0, 5, 5,
+ 4, 1, 1, 2, 5, 4, 5, 3, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2
+};
+
+/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 3, 0, 0, 1, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 138, 5, 0, 0, 42, 0, 85,
+ 0, 0, 4, 20, 40, 60, 67, 107, 18, 133,
+ 127, 6, 7, 11, 9, 8, 10, 140, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 139, 0, 141, 43,
+ 47, 45, 44, 46, 142, 0, 66, 143, 0, 93,
+ 0, 86, 87, 0, 0, 0, 0, 0, 0, 0,
+ 91, 89, 88, 90, 144, 0, 0, 145, 132, 131,
+ 146, 0, 80, 126, 12, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 48, 63, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 94, 0, 0,
+ 0, 0, 0, 0, 0, 69, 70, 73, 71, 72,
+ 0, 108, 80, 0, 12, 83, 137, 0, 124, 0,
+ 0, 130, 0, 22, 23, 21, 25, 24, 26, 0,
+ 30, 31, 27, 28, 32, 33, 34, 35, 37, 36,
+ 38, 39, 0, 0, 62, 64, 0, 92, 109, 111,
+ 114, 115, 116, 117, 113, 112, 110, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 83, 96, 135,
+ 0, 0, 75, 79, 77, 76, 78, 0, 125, 122,
+ 122, 0, 0, 19, 29, 41, 0, 0, 0, 0,
+ 61, 68, 0, 97, 100, 99, 105, 106, 101, 102,
+ 104, 103, 98, 0, 134, 0, 136, 82, 81, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 65, 95, 84, 118, 128, 129, 14, 0, 16,
+ 0, 13, 56, 50, 0, 0, 53, 0, 0, 49,
+ 59, 57, 58, 119, 123, 0, 0, 0, 0, 0,
+ 0, 0, 15, 17, 52, 51, 55, 54, 121, 120
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int16 yydefgoto[] =
+{
+ -1, 1, 2, 38, 152, 14, 15, 16, 65, 173,
+ 17, 175, 176, 68, 18, 142, 207, 146, 201, 85,
+ 86, 19, 273, 274, 239, 149, 150, 151, 93, 20,
+ 91, 92, 21, 22
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -47
+static const yytype_int16 yypact[] =
+{
+ -47, 30, 72, -47, -47, -25, 12, 22, 42, 58,
+ 67, 68, 69, -47, 14, 93, 0, 23, 1, 3,
+ 5, -42, -47, -47, -47, -47, -47, -47, -47, -47,
+ -47, -47, -47, -47, -47, -47, -47, -47, 91, 119,
+ 149, 150, 38, 152, 52, 151, 154, 155, 156, 157,
+ 158, 159, 161, 9, 162, 163, -47, 143, -47, -47,
+ -47, -47, -47, -47, -47, 101, -47, -47, 102, -47,
+ 107, -47, -47, 164, 165, 166, 170, 87, 71, 168,
+ -47, -47, -47, -47, -47, 110, 113, -47, -47, -47,
+ -47, -4, 117, -18, -47, 120, 121, 122, 123, 124,
+ 125, 181, 127, 128, 129, 130, 131, 132, 133, 134,
+ 135, 136, 137, 138, 194, -47, 195, 196, 142, 144,
+ 145, 146, 147, 148, 153, 160, 167, -47, 198, 199,
+ 200, 204, 205, 92, 78, -47, -47, -47, -47, -47,
+ 206, -47, 169, 172, -47, -47, -5, 209, -47, 171,
+ 173, -47, -46, -47, -47, -47, -47, -47, -47, 174,
+ -47, -47, -47, -47, -47, -47, -47, -47, -47, -47,
+ -47, -47, 176, 40, -47, -47, 28, -47, -47, -47,
+ -47, -47, -47, -47, -47, -47, -47, 177, 178, 179,
+ 180, 182, 183, 184, 185, 186, 187, -47, -5, -47,
+ -34, 2, -47, -47, -47, -47, -47, -40, -47, -47,
+ -47, 51, 208, -47, -47, -47, 212, 61, 211, -1,
+ -47, -47, 195, -47, -47, -47, -47, -47, -47, -47,
+ -47, -47, -47, 6, -47, 188, -47, -47, -47, -17,
+ -11, 62, 66, 189, 190, -38, 57, 191, 192, 193,
+ 197, -47, -47, -47, -47, -47, -47, -47, 214, -47,
+ 215, -47, -47, -47, 216, 217, -47, 218, 219, -47,
+ -47, -47, -47, -47, 201, 202, 203, 207, 210, 213,
+ 220, -20, -47, -47, -47, -47, -47, -47, -47, -47
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -47, -47, -47, -47, 75, -47, -47, -47, -47, -47,
+ -47, 7, -47, -47, -47, -47, -47, 86, 33, -47,
+ -47, -47, -47, -47, 31, -47, -47, -47, -47, -47,
+ -47, -47, -47, -47
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -75
+static const yytype_int16 yytable[] =
+{
+ 202, 143, 211, 212, 248, 57, 66, 235, 69, 147,
+ 70, 235, 88, 89, 211, 212, 110, 213, 111, 31,
+ 237, 90, 263, 264, 71, 238, 265, 72, 59, 234,
+ 3, 73, 74, 75, 76, 77, 78, 23, 32, 148,
+ 288, 254, 79, 98, 99, 289, 255, 254, 203, 249,
+ 250, 204, 256, 205, 206, -74, 80, 216, 144, 81,
+ -74, 82, 83, 58, 67, 236, 84, 33, 87, 252,
+ 34, 101, 35, 36, 24, 4, 60, 37, 124, 61,
+ 125, 62, 63, 5, 25, 194, 64, 195, 217, 218,
+ 6, 221, 219, 222, 122, 123, 7, 8, 9, 192,
+ 193, 241, 242, 220, 26, 39, 40, 41, 42, 43,
+ 44, 245, 246, 45, 46, 47, 48, 266, 267, 10,
+ 27, 268, 257, 258, 95, 11, 259, 260, 12, 28,
+ 29, 30, 13, 49, 50, 51, 52, 53, 54, 55,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
+ 138, 139, 140, 94, 96, 97, 56, 100, 102, 103,
+ 104, 105, 114, 115, 116, 106, 107, 108, 109, 112,
+ 113, 117, 127, 120, 118, 119, 141, 121, 126, 145,
+ 153, 154, 155, 156, 157, 158, 159, 160, 161, 162,
+ 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
+ 174, 177, 178, 187, 179, 180, 181, 182, 183, 188,
+ 189, 190, 191, 184, 208, 243, 196, 244, 247, 200,
+ 185, 275, 276, 277, 278, 279, 280, 186, 198, 251,
+ 233, 197, 199, 209, 214, 210, 215, 223, 224, 225,
+ 226, 240, 227, 228, 229, 230, 231, 232, 253, 261,
+ 262, 269, 270, 271, 0, 0, 0, 272, 0, 0,
+ 281, 0, 282, 283, 0, 0, 0, 284, 0, 0,
+ 285, 0, 0, 286, 0, 0, 0, 0, 0, 0,
+ 287
+};
+
+#define yypact_value_is_default(yystate) \
+ ((yystate) == (-47))
+
+#define yytable_value_is_error(yytable_value) \
+ YYID (0)
+
+static const yytype_int16 yycheck[] =
+{
+ 5, 5, 48, 49, 5, 5, 5, 5, 5, 27,
+ 7, 5, 54, 55, 48, 49, 7, 63, 9, 5,
+ 60, 63, 60, 61, 21, 65, 64, 24, 5, 63,
+ 0, 28, 29, 30, 31, 32, 33, 62, 24, 57,
+ 60, 58, 39, 5, 6, 65, 63, 58, 53, 50,
+ 51, 56, 63, 58, 59, 60, 53, 17, 62, 56,
+ 65, 58, 59, 63, 63, 63, 63, 53, 63, 63,
+ 56, 19, 58, 59, 62, 3, 53, 63, 7, 56,
+ 9, 58, 59, 11, 62, 7, 63, 9, 48, 49,
+ 18, 63, 52, 65, 7, 8, 24, 25, 26, 7,
+ 8, 50, 51, 63, 62, 12, 13, 14, 15, 16,
+ 17, 50, 51, 20, 21, 22, 23, 60, 61, 47,
+ 62, 64, 60, 61, 5, 53, 60, 61, 56, 62,
+ 62, 62, 60, 40, 41, 42, 43, 44, 45, 46,
+ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 62, 5, 5, 63, 5, 7, 5,
+ 5, 5, 19, 62, 62, 8, 8, 8, 7, 7,
+ 7, 64, 62, 7, 10, 10, 63, 7, 10, 62,
+ 60, 60, 60, 60, 60, 60, 5, 60, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 5,
+ 5, 5, 60, 5, 60, 60, 60, 60, 60, 10,
+ 10, 7, 7, 60, 5, 7, 10, 5, 7, 144,
+ 60, 7, 7, 7, 7, 7, 7, 60, 142, 222,
+ 197, 62, 60, 62, 60, 62, 60, 60, 60, 60,
+ 60, 210, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 60, -1, -1, -1, 60, -1, -1,
+ 59, -1, 60, 60, -1, -1, -1, 60, -1, -1,
+ 60, -1, -1, 60, -1, -1, -1, -1, -1, -1,
+ 60
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 67, 68, 0, 3, 11, 18, 24, 25, 26,
+ 47, 53, 56, 60, 71, 72, 73, 76, 80, 87,
+ 95, 98, 99, 62, 62, 62, 62, 62, 62, 62,
+ 62, 5, 24, 53, 56, 58, 59, 63, 69, 12,
+ 13, 14, 15, 16, 17, 20, 21, 22, 23, 40,
+ 41, 42, 43, 44, 45, 46, 63, 5, 63, 5,
+ 53, 56, 58, 59, 63, 74, 5, 63, 79, 5,
+ 7, 21, 24, 28, 29, 30, 31, 32, 33, 39,
+ 53, 56, 58, 59, 63, 85, 86, 63, 54, 55,
+ 63, 96, 97, 94, 62, 5, 5, 5, 5, 6,
+ 5, 19, 7, 5, 5, 5, 8, 8, 8, 7,
+ 7, 9, 7, 7, 19, 62, 62, 64, 10, 10,
+ 7, 7, 7, 8, 7, 9, 10, 62, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 63, 81, 5, 62, 62, 83, 27, 57, 91,
+ 92, 93, 70, 60, 60, 60, 60, 60, 60, 5,
+ 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 5, 75, 5, 77, 78, 5, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 5, 10, 10,
+ 7, 7, 7, 8, 7, 9, 10, 62, 83, 60,
+ 70, 84, 5, 53, 56, 58, 59, 82, 5, 62,
+ 62, 48, 49, 63, 60, 60, 17, 48, 49, 52,
+ 63, 63, 65, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 84, 63, 5, 63, 60, 65, 90,
+ 90, 50, 51, 7, 5, 50, 51, 7, 5, 50,
+ 51, 77, 63, 60, 58, 63, 63, 60, 61, 60,
+ 61, 60, 60, 60, 61, 64, 60, 61, 64, 60,
+ 60, 60, 60, 88, 89, 7, 7, 7, 7, 7,
+ 7, 59, 60, 60, 60, 60, 60, 60, 60, 65
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. However,
+ YYFAIL appears to be in use. Nevertheless, it is formally deprecated
+ in Bison 2.4.2's NEWS entry, where a plan to phase it out is
+ discussed. */
+
+#define YYFAIL goto yyerrlab
+#if defined YYFAIL
+ /* This is here to suppress warnings from the GCC cpp's
+ -Wunused-macros. Normally we don't worry about that warning, but
+ some users do, and we want to make it easy for users to remove
+ YYFAIL uses, which will produce warnings from Bison 2.5. */
+#endif
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (scanner, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* This macro is provided for backward compatibility. */
+
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, scanner)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, scanner); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ void *scanner;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (scanner);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, scanner)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ void *scanner;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, void *scanner)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, scanner)
+ YYSTYPE *yyvsp;
+ int yyrule;
+ void *scanner;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ YYFPRINTF (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , scanner);
+ YYFPRINTF (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule, scanner); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message
+ about the unexpected token YYTOKEN for the state stack whose top is
+ YYSSP.
+
+ Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is
+ not large enough to hold the message. In that case, also set
+ *YYMSG_ALLOC to the required number of bytes. Return 2 if the
+ required number of bytes is too large to store. */
+static int
+yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
+ yytype_int16 *yyssp, int yytoken)
+{
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ /* Internationalized format string. */
+ const char *yyformat = 0;
+ /* Arguments of yyformat. */
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ /* Number of reported tokens (one for the "unexpected", one per
+ "expected"). */
+ int yycount = 0;
+
+ /* There are many possibilities here to consider:
+ - Assume YYFAIL is not used. It's too flawed to consider. See
+ <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
+ for details. YYERROR is fine as it does not invoke this
+ function.
+ - If this state is a consistent state with a default action, then
+ the only way this function was invoked is if the default action
+ is an error action. In that case, don't check for expected
+ tokens because there are none.
+ - The only way there can be no lookahead present (in yychar) is if
+ this state is a consistent state with a default action. Thus,
+ detecting the absence of a lookahead is sufficient to determine
+ that there is no unexpected or expected token to report. In that
+ case, just report a simple "syntax error".
+ - Don't assume there isn't a lookahead just because this state is a
+ consistent state with a default action. There might have been a
+ previous inconsistent state, consistent state with a non-default
+ action, or user semantic action that manipulated yychar.
+ - Of course, the expected token list depends on states to have
+ correct lookahead information, and it depends on the parser not
+ to perform extra reductions after fetching a lookahead from the
+ scanner and before detecting a syntax error. Thus, state merging
+ (from LALR or IELR) and default reductions corrupt the expected
+ token list. However, the list is correct for canonical LR with
+ one exception: it will still contain any token that will not be
+ accepted due to an error action in a later state.
+ */
+ if (yytoken != YYEMPTY)
+ {
+ int yyn = yypact[*yyssp];
+ yyarg[yycount++] = yytname[yytoken];
+ if (!yypact_value_is_default (yyn))
+ {
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. In other words, skip the first -YYN actions for
+ this state because they are default actions. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yyx;
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
+ && !yytable_value_is_error (yytable[yyx + yyn]))
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
+ }
+ }
+
+ switch (yycount)
+ {
+# define YYCASE_(N, S) \
+ case N: \
+ yyformat = S; \
+ break
+ YYCASE_(0, YY_("syntax error"));
+ YYCASE_(1, YY_("syntax error, unexpected %s"));
+ YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
+ YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
+ YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
+ YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
+# undef YYCASE_
+ }
+
+ yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+
+ if (*yymsg_alloc < yysize)
+ {
+ *yymsg_alloc = 2 * yysize;
+ if (! (yysize <= *yymsg_alloc
+ && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM))
+ *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM;
+ return 1;
+ }
+
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ {
+ char *yyp = *yymsg;
+ int yyi = 0;
+ while ((*yyp = *yyformat) != '\0')
+ if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyformat += 2;
+ }
+ else
+ {
+ yyp++;
+ yyformat++;
+ }
+ }
+ return 0;
+}
+#endif /* YYERROR_VERBOSE */
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *scanner)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, scanner)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ void *scanner;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (scanner);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *scanner);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *scanner)
+#else
+int
+yyparse (scanner)
+ void *scanner;
+#endif
+#endif
+{
+/* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+ /* Number of syntax errors so far. */
+ int yynerrs;
+
+ int yystate;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+
+ /* The stacks and their tools:
+ `yyss': related to states.
+ `yyvs': related to semantic values.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs;
+ YYSTYPE *yyvsp;
+
+ YYSIZE_T yystacksize;
+
+ int yyn;
+ int yyresult;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken;
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ yytoken = 0;
+ yyss = yyssa;
+ yyvs = yyvsa;
+ yystacksize = YYINITDEPTH;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yypact_value_is_default (yyn))
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yytable_value_is_error (yyn))
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+
+/* Line 1806 of yacc.c */
+#line 448 "cf-parse.y"
+ { return 0; }
+ break;
+
+ case 6:
+
+/* Line 1806 of yacc.c */
+#line 456 "cf-parse.y"
+ { conf_start_iface(scanner, (yyvsp[(1) - (1)].tok).t); }
+ break;
+
+ case 7:
+
+/* Line 1806 of yacc.c */
+#line 457 "cf-parse.y"
+ { conf_start_iface(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 8:
+
+/* Line 1806 of yacc.c */
+#line 458 "cf-parse.y"
+ { conf_start_iface(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 9:
+
+/* Line 1806 of yacc.c */
+#line 459 "cf-parse.y"
+ { conf_start_iface(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 10:
+
+/* Line 1806 of yacc.c */
+#line 460 "cf-parse.y"
+ { conf_start_iface(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 11:
+
+/* Line 1806 of yacc.c */
+#line 461 "cf-parse.y"
+ { conf_start_iface(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 13:
+
+/* Line 1806 of yacc.c */
+#line 465 "cf-parse.y"
+ {
+ if (this_iface->port > 0) {
+ cf_error(scanner, "only one port definition is allowed in interface section\n");
+ } else {
+ this_iface->port = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 14:
+
+/* Line 1806 of yacc.c */
+#line 472 "cf-parse.y"
+ {
+ if (this_iface->address != 0) {
+ cf_error(scanner, "only one address is allowed in interface section\n");
+ } else {
+ this_iface->address = (yyvsp[(3) - (4)].tok).t;
+ this_iface->family = AF_INET;
+ }
+ }
+ break;
+
+ case 15:
+
+/* Line 1806 of yacc.c */
+#line 480 "cf-parse.y"
+ {
+ if (this_iface->address != 0) {
+ cf_error(scanner, "only one address is allowed in interface section\n");
+ } else {
+ this_iface->address = (yyvsp[(3) - (6)].tok).t;
+ this_iface->family = AF_INET;
+ if (this_iface->port > 0) {
+ cf_error(scanner, "only one port definition is allowed in interface section\n");
+ } else {
+ this_iface->port = (yyvsp[(5) - (6)].tok).i;
+ }
+ }
+ }
+ break;
+
+ case 16:
+
+/* Line 1806 of yacc.c */
+#line 493 "cf-parse.y"
+ {
+ if (this_iface->address != 0) {
+ cf_error(scanner, "only one address is allowed in interface section\n");
+ } else {
+ this_iface->address = (yyvsp[(3) - (4)].tok).t;
+ this_iface->family = AF_INET6;
+ }
+ }
+ break;
+
+ case 17:
+
+/* Line 1806 of yacc.c */
+#line 501 "cf-parse.y"
+ {
+ if (this_iface->address != 0) {
+ cf_error(scanner, "only one address is allowed in interface section\n");
+ } else {
+ this_iface->address = (yyvsp[(3) - (6)].tok).t;
+ this_iface->family = AF_INET6;
+ if (this_iface->port > 0) {
+ cf_error(scanner, "only one port definition is allowed in interface section\n");
+ } else {
+ this_iface->port = (yyvsp[(5) - (6)].tok).i;
+ }
+ }
+ }
+ break;
+
+ case 19:
+
+/* Line 1806 of yacc.c */
+#line 518 "cf-parse.y"
+ {
+ if (this_iface->address == 0) {
+ cf_error(scanner, "interface '%s' has no defined address", this_iface->name);
+ }
+ }
+ break;
+
+ case 21:
+
+/* Line 1806 of yacc.c */
+#line 527 "cf-parse.y"
+ { new_config->version = (yyvsp[(3) - (4)].tok).t; }
+ break;
+
+ case 22:
+
+/* Line 1806 of yacc.c */
+#line 528 "cf-parse.y"
+ { new_config->identity = (yyvsp[(3) - (4)].tok).t; }
+ break;
+
+ case 23:
+
+/* Line 1806 of yacc.c */
+#line 529 "cf-parse.y"
+ { new_config->hostname = (yyvsp[(3) - (4)].tok).t; }
+ break;
+
+ case 24:
+
+/* Line 1806 of yacc.c */
+#line 530 "cf-parse.y"
+ { new_config->nsid = (yyvsp[(3) - (4)].tok).t; new_config->nsid_len = (yyvsp[(3) - (4)].tok).l; }
+ break;
+
+ case 25:
+
+/* Line 1806 of yacc.c */
+#line 531 "cf-parse.y"
+ { new_config->nsid = (yyvsp[(3) - (4)].tok).t; new_config->nsid_len = strlen(new_config->nsid); }
+ break;
+
+ case 26:
+
+/* Line 1806 of yacc.c */
+#line 532 "cf-parse.y"
+ { new_config->storage = (yyvsp[(3) - (4)].tok).t; }
+ break;
+
+ case 27:
+
+/* Line 1806 of yacc.c */
+#line 533 "cf-parse.y"
+ { new_config->rundir = (yyvsp[(3) - (4)].tok).t; }
+ break;
+
+ case 28:
+
+/* Line 1806 of yacc.c */
+#line 534 "cf-parse.y"
+ {
+ fprintf(stderr, "warning: Config option 'system.pidfile' is deprecated "
+ "and has no effect. Use 'rundir' instead.\n");
+ free((yyvsp[(3) - (4)].tok).t);
+ }
+ break;
+
+ case 29:
+
+/* Line 1806 of yacc.c */
+#line 539 "cf-parse.y"
+ {
+ fprintf(stderr, "warning: Config option 'system.key' is deprecated "
+ "and has no effect.\n");
+ free((yyvsp[(4) - (5)].tok).t);
+ }
+ break;
+
+ case 30:
+
+/* Line 1806 of yacc.c */
+#line 544 "cf-parse.y"
+ {
+ if ((yyvsp[(3) - (4)].tok).i <= 0) {
+ cf_error(scanner, "worker count must be greater than 0\n");
+ } else {
+ new_config->workers = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 31:
+
+/* Line 1806 of yacc.c */
+#line 551 "cf-parse.y"
+ {
+ new_config->uid = new_config->gid = -1; // Invalidate
+ char* dpos = strchr((yyvsp[(3) - (4)].tok).t, '.'); // Find uid.gid format
+ if (dpos != NULL) {
+ struct group *grp = getgrnam(dpos + 1); // Skip dot
+ if (grp != NULL) {
+ new_config->gid = grp->gr_gid;
+ } else {
+ cf_error(scanner, "invalid group name '%s'", dpos + 1);
+ }
+ *dpos = '\0'; // Cut off
+ }
+ struct passwd* pwd = getpwnam((yyvsp[(3) - (4)].tok).t);
+ if (pwd != NULL) {
+ new_config->uid = pwd->pw_uid;
+ } else {
+ cf_error(scanner, "invalid user name '%s'", (yyvsp[(3) - (4)].tok).t);
+ }
+
+ free((yyvsp[(3) - (4)].tok).t);
+ }
+ break;
+
+ case 32:
+
+/* Line 1806 of yacc.c */
+#line 572 "cf-parse.y"
+ { new_config->max_conn_idle = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 33:
+
+/* Line 1806 of yacc.c */
+#line 573 "cf-parse.y"
+ { new_config->max_conn_hs = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 34:
+
+/* Line 1806 of yacc.c */
+#line 574 "cf-parse.y"
+ { new_config->max_conn_reply = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 35:
+
+/* Line 1806 of yacc.c */
+#line 575 "cf-parse.y"
+ { new_config->rrl = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 36:
+
+/* Line 1806 of yacc.c */
+#line 576 "cf-parse.y"
+ { new_config->rrl_size = (yyvsp[(3) - (4)].tok).l; }
+ break;
+
+ case 37:
+
+/* Line 1806 of yacc.c */
+#line 577 "cf-parse.y"
+ { new_config->rrl_size = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 38:
+
+/* Line 1806 of yacc.c */
+#line 578 "cf-parse.y"
+ { new_config->rrl_slip = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 39:
+
+/* Line 1806 of yacc.c */
+#line 579 "cf-parse.y"
+ { new_config->xfers = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 41:
+
+/* Line 1806 of yacc.c */
+#line 584 "cf-parse.y"
+ {
+ /* Check algorithm length. */
+ if (knot_tsig_digest_length((yyvsp[(3) - (5)].tok).alg) == 0) {
+ cf_error(scanner, "unsupported digest algorithm");
+ }
+
+ /* Normalize to FQDN */
+ char *fqdn = (yyvsp[(2) - (5)].tok).t;
+ size_t fqdnl = strlen(fqdn);
+ if (fqdn[fqdnl - 1] != '.') {
+ fqdnl = ((fqdnl + 2)/4+1)*4; /* '.', '\0' */
+ char* tmpdn = malloc(fqdnl);
+ if (!tmpdn) {
+ cf_error(scanner, "out of memory when allocating string");
+ free(fqdn);
+ fqdn = NULL;
+ fqdnl = 0;
+ } else {
+ strncpy(tmpdn, fqdn, fqdnl);
+ strncat(tmpdn, ".", 1);
+ free(fqdn);
+ fqdn = tmpdn;
+ fqdnl = strlen(fqdn);
+ }
+ }
+
+ if (fqdn != NULL && !conf_key_exists(scanner, fqdn)) {
+ knot_dname_t *dname = knot_dname_new_from_str(fqdn, fqdnl, 0);
+ if (!dname) {
+ cf_error(scanner, "key name '%s' not in valid domain name format",
+ fqdn);
+ free((yyvsp[(4) - (5)].tok).t);
+ } else {
+ knot_dname_to_lower(dname);
+ conf_key_t *k = malloc(sizeof(conf_key_t));
+ memset(k, 0, sizeof(conf_key_t));
+
+ k->k.name = dname;
+ k->k.algorithm = (yyvsp[(3) - (5)].tok).alg;
+ knot_binary_from_base64((yyvsp[(4) - (5)].tok).t, &(k->k.secret));
+ free((yyvsp[(4) - (5)].tok).t);
+ add_tail(&new_config->keys, &k->n);
+ ++new_config->key_count;
+ }
+ } else {
+ free((yyvsp[(4) - (5)].tok).t);
+ }
+
+ free(fqdn);
+}
+ break;
+
+ case 43:
+
+/* Line 1806 of yacc.c */
+#line 636 "cf-parse.y"
+ { conf_start_remote(scanner, (yyvsp[(1) - (1)].tok).t); }
+ break;
+
+ case 44:
+
+/* Line 1806 of yacc.c */
+#line 637 "cf-parse.y"
+ { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 45:
+
+/* Line 1806 of yacc.c */
+#line 638 "cf-parse.y"
+ { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 46:
+
+/* Line 1806 of yacc.c */
+#line 639 "cf-parse.y"
+ { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 47:
+
+/* Line 1806 of yacc.c */
+#line 640 "cf-parse.y"
+ { conf_start_remote(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 49:
+
+/* Line 1806 of yacc.c */
+#line 644 "cf-parse.y"
+ {
+ if (this_remote->port != 0) {
+ cf_error(scanner, "only one port definition is allowed in remote section\n");
+ } else {
+ this_remote->port = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 50:
+
+/* Line 1806 of yacc.c */
+#line 651 "cf-parse.y"
+ {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = (yyvsp[(3) - (4)].tok).t;
+ this_remote->prefix = IPV4_PREFIXLEN;
+ this_remote->family = AF_INET;
+ }
+ }
+ break;
+
+ case 51:
+
+/* Line 1806 of yacc.c */
+#line 660 "cf-parse.y"
+ {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = (yyvsp[(3) - (6)].tok).t;
+ this_remote->family = AF_INET;
+ this_remote->prefix = conf_mask(scanner, (yyvsp[(5) - (6)].tok).i, IPV4_PREFIXLEN);
+ }
+ }
+ break;
+
+ case 52:
+
+/* Line 1806 of yacc.c */
+#line 669 "cf-parse.y"
+ {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = (yyvsp[(3) - (6)].tok).t;
+ this_remote->family = AF_INET;
+ this_remote->prefix = IPV4_PREFIXLEN;
+ if (this_remote->port != 0) {
+ cf_error(scanner, "only one port definition is allowed in remote section\n");
+ } else {
+ this_remote->port = (yyvsp[(5) - (6)].tok).i;
+ }
+ }
+ }
+ break;
+
+ case 53:
+
+/* Line 1806 of yacc.c */
+#line 683 "cf-parse.y"
+ {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = (yyvsp[(3) - (4)].tok).t;
+ this_remote->family = AF_INET6;
+ this_remote->prefix = IPV6_PREFIXLEN;
+ }
+ }
+ break;
+
+ case 54:
+
+/* Line 1806 of yacc.c */
+#line 692 "cf-parse.y"
+ {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = (yyvsp[(3) - (6)].tok).t;
+ this_remote->family = AF_INET6;
+ this_remote->prefix = conf_mask(scanner, (yyvsp[(5) - (6)].tok).i, IPV6_PREFIXLEN);
+ }
+ }
+ break;
+
+ case 55:
+
+/* Line 1806 of yacc.c */
+#line 701 "cf-parse.y"
+ {
+ if (this_remote->address != 0) {
+ cf_error(scanner, "only one address is allowed in remote section\n");
+ } else {
+ this_remote->address = (yyvsp[(3) - (6)].tok).t;
+ this_remote->family = AF_INET6;
+ this_remote->prefix = IPV6_PREFIXLEN;
+ if (this_remote->port != 0) {
+ cf_error(scanner, "only one port definition is allowed in remote section\n");
+ } else {
+ this_remote->port = (yyvsp[(5) - (6)].tok).i;
+ }
+ }
+ }
+ break;
+
+ case 56:
+
+/* Line 1806 of yacc.c */
+#line 715 "cf-parse.y"
+ {
+ if (this_remote->key != 0) {
+ cf_error(scanner, "only one TSIG key definition is allowed in remote section\n");
+ } else {
+ conf_key_add(scanner, &this_remote->key, (yyvsp[(3) - (4)].tok).t);
+ }
+ free((yyvsp[(3) - (4)].tok).t);
+ }
+ break;
+
+ case 57:
+
+/* Line 1806 of yacc.c */
+#line 723 "cf-parse.y"
+ {
+ sockaddr_set(&this_remote->via, AF_INET, (yyvsp[(3) - (4)].tok).t, 0);
+ free((yyvsp[(3) - (4)].tok).t);
+ }
+ break;
+
+ case 58:
+
+/* Line 1806 of yacc.c */
+#line 727 "cf-parse.y"
+ {
+ sockaddr_set(&this_remote->via, AF_INET6, (yyvsp[(3) - (4)].tok).t, 0);
+ free((yyvsp[(3) - (4)].tok).t);
+ }
+ break;
+
+ case 59:
+
+/* Line 1806 of yacc.c */
+#line 731 "cf-parse.y"
+ {
+ conf_remote_set_via(scanner, (yyvsp[(3) - (4)].tok).t);
+ free((yyvsp[(3) - (4)].tok).t);
+ }
+ break;
+
+ case 61:
+
+/* Line 1806 of yacc.c */
+#line 739 "cf-parse.y"
+ {
+ if (this_remote->address == 0) {
+ cf_error(scanner, "remote '%s' has no defined address", this_remote->name);
+ }
+ }
+ break;
+
+ case 62:
+
+/* Line 1806 of yacc.c */
+#line 747 "cf-parse.y"
+ { conf_add_member_into_group(scanner, (yyvsp[(1) - (1)].tok).t); }
+ break;
+
+ case 66:
+
+/* Line 1806 of yacc.c */
+#line 757 "cf-parse.y"
+ { conf_start_group(scanner, (yyvsp[(1) - (1)].tok).t); }
+ break;
+
+ case 69:
+
+/* Line 1806 of yacc.c */
+#line 766 "cf-parse.y"
+ {
+ this_list = &this_zone->acl.xfr_in;
+ }
+ break;
+
+ case 70:
+
+/* Line 1806 of yacc.c */
+#line 769 "cf-parse.y"
+ {
+ this_list = &this_zone->acl.xfr_out;
+ }
+ break;
+
+ case 71:
+
+/* Line 1806 of yacc.c */
+#line 772 "cf-parse.y"
+ {
+ this_list = &this_zone->acl.notify_in;
+ }
+ break;
+
+ case 72:
+
+/* Line 1806 of yacc.c */
+#line 775 "cf-parse.y"
+ {
+ this_list = &this_zone->acl.notify_out;
+ }
+ break;
+
+ case 73:
+
+/* Line 1806 of yacc.c */
+#line 778 "cf-parse.y"
+ {
+ this_list = &this_zone->acl.update_in;
+ }
+ break;
+
+ case 75:
+
+/* Line 1806 of yacc.c */
+#line 784 "cf-parse.y"
+ { conf_acl_item(scanner, (yyvsp[(1) - (1)].tok).t); }
+ break;
+
+ case 76:
+
+/* Line 1806 of yacc.c */
+#line 785 "cf-parse.y"
+ { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 77:
+
+/* Line 1806 of yacc.c */
+#line 786 "cf-parse.y"
+ { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 78:
+
+/* Line 1806 of yacc.c */
+#line 787 "cf-parse.y"
+ { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 79:
+
+/* Line 1806 of yacc.c */
+#line 788 "cf-parse.y"
+ { conf_acl_item(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 84:
+
+/* Line 1806 of yacc.c */
+#line 797 "cf-parse.y"
+ {
+ /* Find existing node in remotes. */
+ node* r = 0; conf_iface_t* found = 0;
+ WALK_LIST (r, new_config->remotes) {
+ if (strcmp(((conf_iface_t*)r)->name, (yyvsp[(2) - (3)].tok).t) == 0) {
+ found = (conf_iface_t*)r;
+ break;
+ }
+ }
+
+ /* Append to list if found. */
+ if (!found) {
+ cf_error(scanner, "remote '%s' is not defined", (yyvsp[(2) - (3)].tok).t);
+ } else {
+ conf_remote_t *remote = malloc(sizeof(conf_remote_t));
+ if (!remote) {
+ cf_error(scanner, "out of memory");
+ } else {
+ remote->remote = found;
+ add_tail(this_list, &remote->n);
+ }
+ }
+
+ /* Free text token. */
+ free((yyvsp[(2) - (3)].tok).t);
+ }
+ break;
+
+ case 86:
+
+/* Line 1806 of yacc.c */
+#line 826 "cf-parse.y"
+ { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 87:
+
+/* Line 1806 of yacc.c */
+#line 827 "cf-parse.y"
+ { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 88:
+
+/* Line 1806 of yacc.c */
+#line 828 "cf-parse.y"
+ { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 89:
+
+/* Line 1806 of yacc.c */
+#line 829 "cf-parse.y"
+ { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 90:
+
+/* Line 1806 of yacc.c */
+#line 830 "cf-parse.y"
+ { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 91:
+
+/* Line 1806 of yacc.c */
+#line 831 "cf-parse.y"
+ { conf_zone_start(scanner, strdup((yyvsp[(1) - (1)].tok).t)); }
+ break;
+
+ case 92:
+
+/* Line 1806 of yacc.c */
+#line 832 "cf-parse.y"
+ {
+ if ((yyvsp[(1) - (3)].tok).i < 0 || (yyvsp[(1) - (3)].tok).i > 255) {
+ cf_error(scanner, "rfc2317 origin prefix '%ld' out of bounds", (yyvsp[(1) - (3)].tok).i);
+ }
+ size_t len = 3 + 1 + strlen((yyvsp[(3) - (3)].tok).t) + 1; /* <0,255> '/' rest */
+ char *name = malloc(len * sizeof(char));
+ if (name == NULL) {
+ cf_error(scanner, "out of memory");
+ } else {
+ name[0] = '\0';
+ if (snprintf(name, len, "%ld/%s", (yyvsp[(1) - (3)].tok).i, (yyvsp[(3) - (3)].tok).t) < 0) {
+ cf_error(scanner,"failed to convert rfc2317 origin to string");
+ }
+ }
+ free((yyvsp[(3) - (3)].tok).t);
+ conf_zone_start(scanner, name);
+ }
+ break;
+
+ case 93:
+
+/* Line 1806 of yacc.c */
+#line 849 "cf-parse.y"
+ { conf_zone_start(scanner, (yyvsp[(1) - (1)].tok).t); }
+ break;
+
+ case 97:
+
+/* Line 1806 of yacc.c */
+#line 856 "cf-parse.y"
+ { this_zone->file = (yyvsp[(3) - (4)].tok).t; }
+ break;
+
+ case 98:
+
+/* Line 1806 of yacc.c */
+#line 857 "cf-parse.y"
+ { this_zone->build_diffs = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 99:
+
+/* Line 1806 of yacc.c */
+#line 858 "cf-parse.y"
+ { this_zone->enable_checks = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 100:
+
+/* Line 1806 of yacc.c */
+#line 859 "cf-parse.y"
+ { this_zone->disable_any = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 101:
+
+/* Line 1806 of yacc.c */
+#line 860 "cf-parse.y"
+ { this_zone->dbsync_timeout = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 102:
+
+/* Line 1806 of yacc.c */
+#line 861 "cf-parse.y"
+ { this_zone->dbsync_timeout = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 103:
+
+/* Line 1806 of yacc.c */
+#line 862 "cf-parse.y"
+ { new_config->ixfr_fslimit = (yyvsp[(3) - (4)].tok).l; }
+ break;
+
+ case 104:
+
+/* Line 1806 of yacc.c */
+#line 863 "cf-parse.y"
+ { this_zone->ixfr_fslimit = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 105:
+
+/* Line 1806 of yacc.c */
+#line 864 "cf-parse.y"
+ {
+ if ((yyvsp[(3) - (4)].tok).i < 1) {
+ cf_error(scanner, "notify retries must be positive integer");
+ } else {
+ this_zone->notify_retries = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 106:
+
+/* Line 1806 of yacc.c */
+#line 871 "cf-parse.y"
+ {
+ if ((yyvsp[(3) - (4)].tok).i < 1) {
+ cf_error(scanner, "notify timeout must be positive integer");
+ } else {
+ this_zone->notify_timeout = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 109:
+
+/* Line 1806 of yacc.c */
+#line 883 "cf-parse.y"
+ { new_config->disable_any = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 110:
+
+/* Line 1806 of yacc.c */
+#line 884 "cf-parse.y"
+ { new_config->build_diffs = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 111:
+
+/* Line 1806 of yacc.c */
+#line 885 "cf-parse.y"
+ { new_config->zone_checks = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 112:
+
+/* Line 1806 of yacc.c */
+#line 886 "cf-parse.y"
+ { new_config->ixfr_fslimit = (yyvsp[(3) - (4)].tok).l; }
+ break;
+
+ case 113:
+
+/* Line 1806 of yacc.c */
+#line 887 "cf-parse.y"
+ { new_config->ixfr_fslimit = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 114:
+
+/* Line 1806 of yacc.c */
+#line 888 "cf-parse.y"
+ {
+ if ((yyvsp[(3) - (4)].tok).i < 1) {
+ cf_error(scanner, "notify retries must be positive integer");
+ } else {
+ new_config->notify_retries = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 115:
+
+/* Line 1806 of yacc.c */
+#line 895 "cf-parse.y"
+ {
+ if ((yyvsp[(3) - (4)].tok).i < 1) {
+ cf_error(scanner, "notify timeout must be positive integer");
+ } else {
+ new_config->notify_timeout = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 116:
+
+/* Line 1806 of yacc.c */
+#line 902 "cf-parse.y"
+ {
+ if ((yyvsp[(3) - (4)].tok).i < 1) {
+ cf_error(scanner, "zonefile sync timeout must be positive integer");
+ } else {
+ new_config->dbsync_timeout = (yyvsp[(3) - (4)].tok).i;
+ }
+ }
+ break;
+
+ case 117:
+
+/* Line 1806 of yacc.c */
+#line 909 "cf-parse.y"
+ { new_config->dbsync_timeout = (yyvsp[(3) - (4)].tok).i; }
+ break;
+
+ case 118:
+
+/* Line 1806 of yacc.c */
+#line 912 "cf-parse.y"
+ {
+ this_logmap = malloc(sizeof(conf_log_map_t));
+ this_logmap->source = 0;
+ this_logmap->prios = 0;
+ add_tail(&this_log->map, &this_logmap->n);
+}
+ break;
+
+ case 120:
+
+/* Line 1806 of yacc.c */
+#line 922 "cf-parse.y"
+ { this_logmap->prios |= (yyvsp[(2) - (3)].tok).i; }
+ break;
+
+ case 121:
+
+/* Line 1806 of yacc.c */
+#line 923 "cf-parse.y"
+ { this_logmap->prios |= (yyvsp[(2) - (3)].tok).i; }
+ break;
+
+ case 123:
+
+/* Line 1806 of yacc.c */
+#line 927 "cf-parse.y"
+ {
+ this_logmap->source = (yyvsp[(2) - (3)].tok).i;
+ this_logmap = 0;
+ }
+ break;
+
+ case 124:
+
+/* Line 1806 of yacc.c */
+#line 933 "cf-parse.y"
+ {
+ /* Find already existing rule. */
+ this_log = 0;
+ node *n = 0;
+ WALK_LIST(n, new_config->logs) {
+ conf_log_t* log = (conf_log_t*)n;
+ if (log->type == (yyvsp[(1) - (1)].tok).i) {
+ this_log = log;
+ break;
+ }
+ }
+
+ if (!this_log) {
+ this_log = malloc(sizeof(conf_log_t));
+ this_log->type = (yyvsp[(1) - (1)].tok).i;
+ this_log->file = 0;
+ init_list(&this_log->map);
+ add_tail(&new_config->logs, &this_log->n);
+ ++new_config->logs_count;
+ }
+}
+ break;
+
+ case 125:
+
+/* Line 1806 of yacc.c */
+#line 956 "cf-parse.y"
+ {
+ /* Find already existing rule. */
+ this_log = 0;
+ node *n = 0;
+ WALK_LIST(n, new_config->logs) {
+ conf_log_t* log = (conf_log_t*)n;
+ if (log->type == LOGT_FILE) {
+ if (strcmp((yyvsp[(2) - (2)].tok).t, log->file) == 0) {
+ this_log = log;
+ free((yyvsp[(2) - (2)].tok).t);
+ break;
+ }
+ }
+ }
+
+ /* Create new rule. */
+ if (!this_log) {
+ this_log = malloc(sizeof(conf_log_t));
+ this_log->type = LOGT_FILE;
+ this_log->file = strcpath((yyvsp[(2) - (2)].tok).t);
+ init_list(&this_log->map);
+ add_tail(&new_config->logs, &this_log->n);
+ ++new_config->logs_count;
+ }
+}
+ break;
+
+ case 126:
+
+/* Line 1806 of yacc.c */
+#line 983 "cf-parse.y"
+ {
+}
+ break;
+
+ case 131:
+
+/* Line 1806 of yacc.c */
+#line 995 "cf-parse.y"
+ { conf_init_iface(scanner, NULL, -1); }
+ break;
+
+ case 132:
+
+/* Line 1806 of yacc.c */
+#line 999 "cf-parse.y"
+ {
+ this_list = &new_config->ctl.allow;
+ }
+ break;
+
+ case 133:
+
+/* Line 1806 of yacc.c */
+#line 1005 "cf-parse.y"
+ { new_config->ctl.have = true; }
+ break;
+
+ case 134:
+
+/* Line 1806 of yacc.c */
+#line 1006 "cf-parse.y"
+ {
+ if (this_iface->address == 0) {
+ cf_error(scanner, "control interface has no defined address");
+ } else {
+ new_config->ctl.iface = this_iface;
+ }
+ }
+ break;
+
+ case 135:
+
+/* Line 1806 of yacc.c */
+#line 1013 "cf-parse.y"
+ {
+ this_iface->address = (yyvsp[(3) - (4)].tok).t;
+ this_iface->family = AF_UNIX;
+ this_iface->port = 0;
+ new_config->ctl.iface = this_iface;
+ }
+ break;
+
+
+
+/* Line 1806 of yacc.c */
+#line 3188 "knot/conf/libknotd_la-cf-parse.c"
+ default: break;
+ }
+ /* User semantic actions sometimes alter yychar, and that requires
+ that yytoken be updated with the new translation. We take the
+ approach of translating immediately before every use of yytoken.
+ One alternative is translating here after every semantic action,
+ but that translation would be missed if the semantic action invokes
+ YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or
+ if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an
+ incorrect destructor might then be invoked immediately. In the
+ case of YYERROR or YYBACKUP, subsequent parser actions might lead
+ to an incorrect destructor call or verbose syntax error message
+ before the lookahead is translated. */
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar);
+
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (scanner, YY_("syntax error"));
+#else
+# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \
+ yyssp, yytoken)
+ {
+ char const *yymsgp = YY_("syntax error");
+ int yysyntax_error_status;
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ if (yysyntax_error_status == 0)
+ yymsgp = yymsg;
+ else if (yysyntax_error_status == 1)
+ {
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc);
+ if (!yymsg)
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ yysyntax_error_status = 2;
+ }
+ else
+ {
+ yysyntax_error_status = YYSYNTAX_ERROR;
+ yymsgp = yymsg;
+ }
+ }
+ yyerror (scanner, yymsgp);
+ if (yysyntax_error_status == 2)
+ goto yyexhaustedlab;
+ }
+# undef YYSYNTAX_ERROR
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, scanner);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (!yypact_value_is_default (yyn))
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, scanner);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#if !defined(yyoverflow) || YYERROR_VERBOSE
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (scanner, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ {
+ /* Make sure we have latest lookahead translation. See comments at
+ user semantic actions for why this is necessary. */
+ yytoken = YYTRANSLATE (yychar);
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, scanner);
+ }
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, scanner);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+
+/* Line 2067 of yacc.c */
+#line 1025 "cf-parse.y"
+
+
diff --git a/src/knot/conf/libknotd_la-cf-parse.h b/src/knot/conf/libknotd_la-cf-parse.h
new file mode 100644
index 0000000..d95ad8c
--- /dev/null
+++ b/src/knot/conf/libknotd_la-cf-parse.h
@@ -0,0 +1,187 @@
+/* A Bison parser, made by GNU Bison 2.5. */
+
+/* Bison interface for Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc.
+
+ 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/>. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ END = 258,
+ INVALID_TOKEN = 259,
+ TEXT = 260,
+ HEXSTR = 261,
+ NUM = 262,
+ INTERVAL = 263,
+ SIZE = 264,
+ BOOL = 265,
+ SYSTEM = 266,
+ IDENTITY = 267,
+ HOSTNAME = 268,
+ SVERSION = 269,
+ NSID = 270,
+ STORAGE = 271,
+ KEY = 272,
+ KEYS = 273,
+ TSIG_ALGO_NAME = 274,
+ WORKERS = 275,
+ USER = 276,
+ RUNDIR = 277,
+ PIDFILE = 278,
+ REMOTES = 279,
+ GROUPS = 280,
+ ZONES = 281,
+ FILENAME = 282,
+ DISABLE_ANY = 283,
+ SEMANTIC_CHECKS = 284,
+ NOTIFY_RETRIES = 285,
+ NOTIFY_TIMEOUT = 286,
+ DBSYNC_TIMEOUT = 287,
+ IXFR_FSLIMIT = 288,
+ XFR_IN = 289,
+ XFR_OUT = 290,
+ UPDATE_IN = 291,
+ NOTIFY_IN = 292,
+ NOTIFY_OUT = 293,
+ BUILD_DIFFS = 294,
+ MAX_CONN_IDLE = 295,
+ MAX_CONN_HS = 296,
+ MAX_CONN_REPLY = 297,
+ RATE_LIMIT = 298,
+ RATE_LIMIT_SIZE = 299,
+ RATE_LIMIT_SLIP = 300,
+ TRANSFERS = 301,
+ INTERFACES = 302,
+ ADDRESS = 303,
+ PORT = 304,
+ IPA = 305,
+ IPA6 = 306,
+ VIA = 307,
+ CONTROL = 308,
+ ALLOW = 309,
+ LISTEN_ON = 310,
+ LOG = 311,
+ LOG_DEST = 312,
+ LOG_SRC = 313,
+ LOG_LEVEL = 314
+ };
+#endif
+/* Tokens. */
+#define END 258
+#define INVALID_TOKEN 259
+#define TEXT 260
+#define HEXSTR 261
+#define NUM 262
+#define INTERVAL 263
+#define SIZE 264
+#define BOOL 265
+#define SYSTEM 266
+#define IDENTITY 267
+#define HOSTNAME 268
+#define SVERSION 269
+#define NSID 270
+#define STORAGE 271
+#define KEY 272
+#define KEYS 273
+#define TSIG_ALGO_NAME 274
+#define WORKERS 275
+#define USER 276
+#define RUNDIR 277
+#define PIDFILE 278
+#define REMOTES 279
+#define GROUPS 280
+#define ZONES 281
+#define FILENAME 282
+#define DISABLE_ANY 283
+#define SEMANTIC_CHECKS 284
+#define NOTIFY_RETRIES 285
+#define NOTIFY_TIMEOUT 286
+#define DBSYNC_TIMEOUT 287
+#define IXFR_FSLIMIT 288
+#define XFR_IN 289
+#define XFR_OUT 290
+#define UPDATE_IN 291
+#define NOTIFY_IN 292
+#define NOTIFY_OUT 293
+#define BUILD_DIFFS 294
+#define MAX_CONN_IDLE 295
+#define MAX_CONN_HS 296
+#define MAX_CONN_REPLY 297
+#define RATE_LIMIT 298
+#define RATE_LIMIT_SIZE 299
+#define RATE_LIMIT_SLIP 300
+#define TRANSFERS 301
+#define INTERFACES 302
+#define ADDRESS 303
+#define PORT 304
+#define IPA 305
+#define IPA6 306
+#define VIA 307
+#define CONTROL 308
+#define ALLOW 309
+#define LISTEN_ON 310
+#define LOG 311
+#define LOG_DEST 312
+#define LOG_SRC 313
+#define LOG_LEVEL 314
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{
+
+/* Line 2068 of yacc.c */
+#line 386 "cf-parse.y"
+
+ struct {
+ char *t;
+ long i;
+ size_t l;
+ knot_tsig_algorithm_t alg;
+ } tok;
+
+
+
+/* Line 2068 of yacc.c */
+#line 179 "knot/conf/libknotd_la-cf-parse.h"
+} YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+
diff --git a/src/knot/conf/logconf.c b/src/knot/conf/logconf.c
index 0d2b7da..427e762 100644
--- a/src/knot/conf/logconf.c
+++ b/src/knot/conf/logconf.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
@@ -25,7 +26,7 @@
#include "knot/conf/conf.h"
#include "common/log.h"
#include "common/lists.h"
-#include "knot/common.h"
+#include "knot/knot.h"
int log_conf_hook(const struct conf_t *conf, void *data)
{
@@ -98,4 +99,3 @@ int log_conf_hook(const struct conf_t *conf, void *data)
return KNOT_EOK;
}
-
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index dd37ddf..73c6058 100644
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -32,7 +32,8 @@
#include <sys/wait.h>
#endif
-#include "knot/common.h"
+#include "knot/knot.h"
+#include "common/descriptor.h"
#include "knot/ctl/process.h"
#include "knot/ctl/remote.h"
#include "knot/conf/conf.h"
@@ -42,11 +43,8 @@
#include "libknot/util/wire.h"
#include "libknot/packet/query.h"
#include "libknot/packet/response.h"
-
-/*! \brief Controller constants. */
-enum knotc_constants_t {
- WAITPID_TIMEOUT = 120 /*!< \brief Timeout for waiting for process. */
-};
+#include "knot/zone/zone-load.h"
+#include "knot/zone/estimator.h"
/*! \brief Controller flags. */
enum knotc_flag_t {
@@ -68,225 +66,81 @@ static inline unsigned has_flag(unsigned flags, enum knotc_flag_t f)
}
/*! \brief Callback prototype for command. */
-typedef int (*knot_cmdf_t)(int argc, char *argv[], unsigned flags, int jobs);
+typedef int (*knot_cmdf_t)(int argc, char *argv[], unsigned flags);
/*! \brief Command table item. */
-typedef struct knot_cmd_t {
- const char *name;
+typedef struct knot_cmd {
knot_cmdf_t cb;
- const char *desc;
int need_conf;
+ const char *name;
+ const char *params;
+ const char *desc;
} knot_cmd_t;
/* Forward decls. */
-static int cmd_start(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_stop(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_restart(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_reload(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_refresh(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_flush(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_status(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_zonestatus(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_checkconf(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_checkzone(int argc, char *argv[], unsigned flags, int jobs);
-static int cmd_compile(int argc, char *argv[], unsigned flags, int jobs);
+static int cmd_stop(int argc, char *argv[], unsigned flags);
+static int cmd_restart(int argc, char *argv[], unsigned flags);
+static int cmd_reload(int argc, char *argv[], unsigned flags);
+static int cmd_refresh(int argc, char *argv[], unsigned flags);
+static int cmd_flush(int argc, char *argv[], unsigned flags);
+static int cmd_status(int argc, char *argv[], unsigned flags);
+static int cmd_zonestatus(int argc, char *argv[], unsigned flags);
+static int cmd_checkconf(int argc, char *argv[], unsigned flags);
+static int cmd_checkzone(int argc, char *argv[], unsigned flags);
+static int cmd_memstats(int argc, char *argv[], unsigned flags);
/*! \brief Table of remote commands. */
knot_cmd_t knot_cmd_tbl[] = {
- {"start", &cmd_start, "\tStart server (no-op if running).", 1},
- {"stop", &cmd_stop, "\tStop server (no-op if running).", 1},
- {"restart", &cmd_restart, "Restarts server (no-op if running).", 1},
- {"reload", &cmd_reload, "\tReloads configuration and changed zones.",0},
- {"refresh", &cmd_refresh,"Refresh slave zones (all if not specified).",0},
- {"flush", &cmd_flush, "\tFlush journal and update zone files.",0},
- {"status", &cmd_status, "\tCheck if server is running.",0},
- {"zonestatus",&cmd_zonestatus, "Show status of configured zones.",0},
- {"checkconf", &cmd_checkconf, "Check server configuration.",1},
- {"checkzone", &cmd_checkzone, "Check specified zone files.",1},
- {"compile", &cmd_compile, "Compile zone files (all if not specified).",1},
- {NULL, NULL, NULL,0}
+ {&cmd_stop, 0, "stop", "", "\t\tStop server."},
+ {&cmd_restart, 0, "restart", "", "\tRestart server."},
+ {&cmd_reload, 0, "reload", "", "\tReload configuration and changed zones."},
+ {&cmd_refresh, 0, "refresh", "[zone]", "\tRefresh slave zone (all if not specified)."},
+ {&cmd_flush, 0, "flush", "", "\t\tFlush journal and update zone files."},
+ {&cmd_status, 0, "status", "", "\tCheck if server is running."},
+ {&cmd_zonestatus, 0, "zonestatus", "", "\tShow status of configured zones."},
+ {&cmd_checkconf, 1, "checkconf", "", "\tCheck current server configuration."},
+ {&cmd_checkzone, 1, "checkzone", "[zone]", "Check zone (all if not specified)."},
+ {&cmd_memstats, 1, "memstats", "[zone]", "Estimate memory use for zone (all if not specified)."},
+ {NULL, 0, NULL, NULL, NULL}
};
/*! \brief Print help. */
-void help(int argc, char **argv)
+void help(void)
{
- printf("Usage: %sc [parameters] <action> [action_args]\n", PACKAGE_NAME);
+ printf("Usage: %sc [parameters] <action>\n", PACKAGE_NAME);
printf("\nParameters:\n"
" -c [file], --config=[file]\tSelect configuration file.\n"
- " -j [num], --jobs=[num] \tNumber of parallel tasks to run when compiling.\n"
- " -s [server] \tRemote server address (default %s)\n"
- " -p [port] \tRemote server port (default %d)\n"
- " -y [hmac:]name:key] \tUse key_id specified on the command line.\n"
+ " -s [server] \tRemote UNIX socket/IP address (default %s).\n"
+ " -p [port] \tRemote server port (only for IP).\n"
+ " -y [[hmac:]name:key] \tUse key_id specified on the command line.\n"
" -k [file] \tUse key file (as in config section 'keys').\n"
- " \t f.e. echo \"knotc-key hmac-md5 Wg==\" > knotc.key\n"
+ " \t Example: echo \"knotc-key hmac-md5 Wg==\" > knotc.key\n"
" -f, --force \tForce operation - override some checks.\n"
" -v, --verbose \tVerbose mode - additional runtime information.\n"
" -V, --version \tPrint %s server version.\n"
- " -w, --wait \tWait for the server to finish start/stop operations.\n"
" -i, --interactive \tInteractive mode (do not daemonize).\n"
" -h, --help \tPrint help and usage.\n",
- "127.0.0.1", REMOTE_DPORT, PACKAGE_NAME);
+ RUN_DIR "/knot.sock", PACKAGE_NAME);
printf("\nActions:\n");
knot_cmd_t *c = knot_cmd_tbl;
while (c->name != NULL) {
- printf(" %s\t\t\t%s\n", c->name, c->desc);
+ printf(" %s %s\t\t%s\n", c->name, c->params, c->desc);
++c;
}
}
-/*!
- * \brief Check if the zone needs recompilation.
- *
- * \param db Path to zone db file.
- * \param source Path to zone source file.
- *
- * \retval KNOT_EOK if up to date.
- * \retval KNOT_ERROR if needs recompilation.
- */
-static int check_zone(const char *db, const char *source)
-{
- /* Check zonefile. */
- struct stat st;
- if (stat(source, &st) != 0) {
- int reason = errno;
- const char *emsg = "";
- switch (reason) {
- case EACCES:
- emsg = "Not enough permissions to access zone file '%s'.\n";
- break;
- case ENOENT:
- emsg = "Zone file '%s' doesn't exist.\n";
- break;
- default:
- emsg = "Unable to stat zone file '%s'.\n";
- break;
- }
- log_zone_error(emsg, source);
- return KNOT_ENOENT;
- }
-
- /* Read zonedb header. */
- zloader_t *zl = 0;
- knot_zload_open(&zl, db);
- if (!zl) {
- return KNOT_ERROR;
- }
-
- /* Check source files and mtime. */
- int ret = KNOT_ERROR;
- int src_changed = strcmp(source, zl->source) != 0;
- if (!src_changed && !knot_zload_needs_update(zl)) {
- ret = KNOT_EOK;
- }
-
- knot_zload_close(zl);
- return ret;
-}
-
-/*! \brief Zone compiler task. */
-typedef struct {
- conf_zone_t *zone;
- pid_t proc;
-} knotc_zctask_t;
-
-/*! \brief Create set of watched tasks. */
-static knotc_zctask_t *zctask_create(int count)
-{
- if (count <= 0) {
- return 0;
- }
-
- knotc_zctask_t *t = malloc(count * sizeof(knotc_zctask_t));
- for (unsigned i = 0; i < count; ++i) {
- t[i].proc = -1;
- t[i].zone = 0;
- }
-
- return t;
-}
-
-/*! \brief Wait for single task to finish. */
-static int zctask_wait(knotc_zctask_t *tasks, int count, int is_checkzone)
-{
- /* Wait for children to finish. */
- int rc = 0;
- pid_t pid = pid_wait(-1, &rc);
-
- /* Find task. */
- conf_zone_t *z = 0;
- for (unsigned i = 0; i < count; ++i) {
- if (tasks[i].proc == pid) {
- tasks[i].proc = -1; /* Invalidate. */
- z = tasks[i].zone;
- break;
- }
- }
-
- if (z == 0) {
- log_server_error("Failed to find zone for finished "
- "zone compilation process.\n");
- return 1;
- }
-
- /* Evaluate. */
- if (!WIFEXITED(rc)) {
- log_server_error("%s of '%s' failed, process was killed.\n",
- is_checkzone ? "Checking" : "Compilation",
- z->name);
- return 1;
- } else {
- if (rc < 0 || WEXITSTATUS(rc) != 0) {
- if (!is_checkzone) {
- log_zone_error("Compilation of "
- "'%s' failed, knot-zcompile "
- "return code was '%d'\n",
- z->name, WEXITSTATUS(rc));
- }
-
- return 1;
- }
- }
-
- return 0;
-}
-
-/*! \brief Register running zone compilation process. */
-static int zctask_add(knotc_zctask_t *tasks, int count, pid_t pid,
- conf_zone_t *zone)
-{
- /* Find free space. */
- for (unsigned i = 0; i < count; ++i) {
- if (tasks[i].proc == -1) {
- tasks[i].proc = pid;
- tasks[i].zone = zone;
- return 0;
- }
- }
-
- /* Free space not found. */
- return -1;
-}
-
static int cmd_remote_print_reply(const knot_rrset_t *rr)
{
/* Process first RRSet in data section. */
if (knot_rrset_type(rr) != KNOT_RRTYPE_TXT) {
return KNOT_EMALF;
}
-
- const knot_rdata_t *rd = knot_rrset_rdata(rr);
- while (rd != NULL) {
- /* Skip empty nodes. */
- if (knot_rdata_item_count(rd) < 1) {
- rd = knot_rrset_rdata_next(rr, rd);
- continue;
- }
+ for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rr); i++) {
/* Parse TXT. */
- remote_print_txt(rd);
- rd = knot_rrset_rdata_next(rr, rd);
+ remote_print_txt(rr, i);
}
-
+
return KNOT_EOK;
}
@@ -299,28 +153,36 @@ static int cmd_remote_reply(int c)
knot_packet_free(&reply);
return KNOT_ENOMEM;
}
-
+
/* Read response packet. */
int n = tcp_recv(c, rwire, SOCKET_MTU_SZ, NULL);
- if (n < 0) {
+ if (n <= 0) {
dbg_server("remote: couldn't receive response = %d\n", n);
knot_packet_free(&reply);
free(rwire);
return KNOT_ECONN;
}
-
+
/* Parse packet and check response. */
int ret = remote_parse(reply, rwire, n);
if (ret == KNOT_EOK) {
/* Check RCODE */
ret = knot_packet_rcode(reply);
-
- /* Check extra data. */
- if (knot_packet_authority_rrset_count(reply) > 0) {
- ret = cmd_remote_print_reply(reply->authority[0]);
+ switch(ret) {
+ case KNOT_RCODE_NOERROR:
+ if (knot_packet_authority_rrset_count(reply) > 0) {
+ ret = cmd_remote_print_reply(reply->authority[0]);
+ }
+ break;
+ case KNOT_RCODE_REFUSED:
+ ret = KNOT_EDENIED;
+ break;
+ default:
+ ret = KNOT_ERROR;
+ break;
}
}
-
+
/* Response cleanup. */
knot_packet_free(&reply);
free(rwire);
@@ -338,7 +200,7 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
cmd);
return 1;
}
-
+
/* Make query. */
uint8_t *buf = NULL;
size_t buflen = 0;
@@ -348,26 +210,27 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
cmd);
return 1;
}
-
+
/* Build query data. */
- knot_rdata_t *rd = NULL;
- knot_rrset_t *rr = remote_build_rr("data.", rrt);
- for (int i = 0; i < argc; ++i) {
- switch(rrt) {
- case KNOT_RRTYPE_CNAME:
- rd = remote_create_cname(argv[i]);
- break;
- case KNOT_RRTYPE_TXT:
- default:
- rd = remote_create_txt(argv[i], strlen(argv[i]));
- break;
+ knot_rrset_t *rr = NULL;
+ if (argc > 0) {
+ rr = remote_build_rr("data.", rrt);
+ for (int i = 0; i < argc; ++i) {
+ switch(rrt) {
+ case KNOT_RRTYPE_NS:
+ remote_create_ns(rr, argv[i]);
+ break;
+ case KNOT_RRTYPE_TXT:
+ default:
+ remote_create_txt(rr, argv[i], strlen(argv[i]));
+ break;
+ }
}
- knot_rrset_add_rdata(rr, rd);
- rd = NULL;
+ remote_query_append(qr, rr);
}
- remote_query_append(qr, rr);
+
if (knot_packet_to_wire(qr, &buf, &buflen) != KNOT_EOK) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
knot_packet_free(&qr);
return 1;
}
@@ -375,71 +238,64 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
if (r->key) {
remote_query_sign(buf, &buflen, qr->max_size, r->key);
}
-
+
/* Send query. */
- int s = socket_create(r->family, SOCK_STREAM);
- int conn_state = socket_connect(s, r->address, r->port);
+ int s = socket_create(r->family, SOCK_STREAM, 0);
+ int conn_state = socket_connect(s, r->family, r->address, r->port);
if (conn_state != KNOT_EOK || tcp_send(s, buf, buflen) <= 0) {
+ char portstr[32] = { '\0' };
+ if (r->family != AF_UNIX)
+ snprintf(portstr, sizeof(portstr), "@%d", r->port);
log_server_error("Couldn't connect to remote host "
- " %s@%d.\n", r->address, r->port);
+ "%s%s\n", r->address, portstr);
rc = 1;
}
-
+
/* Wait for reply. */
if (rc == 0) {
int ret = KNOT_EOK;
- while (ret != KNOT_ECONN) {
+ while (ret == KNOT_EOK) {
ret = cmd_remote_reply(s);
- }
- if (ret != KNOT_EOK && ret != KNOT_ECONN) {
- log_server_warning("Remote command reply: %s\n",
- knot_strerror(ret));
- rc = 1;
+ if (ret != KNOT_EOK && ret != KNOT_ECONN) {
+ log_server_warning("Remote command reply: %s\n",
+ knot_strerror(ret));
+ rc = 1;
+ }
}
}
-
+
/* Cleanup. */
- printf("\n");
- knot_rrset_deep_free(&rr, 1, 1, 1);
-
+ if (rc == 0) printf("\n");
+ knot_rrset_deep_free(&rr, 1, 1);
+
/* Close connection. */
socket_close(s);
knot_packet_free(&qr);
return rc;
}
-static knot_lookup_table_t tsig_algn_tbl[] = {
- { KNOT_TSIG_ALG_NULL, "gss-tsig" },
- { KNOT_TSIG_ALG_HMAC_MD5, "hmac-md5" },
- { KNOT_TSIG_ALG_HMAC_SHA1, "hmac-sha1" },
- { KNOT_TSIG_ALG_HMAC_SHA224, "hmac-sha224" },
- { KNOT_TSIG_ALG_HMAC_SHA256, "hmac-sha256" },
- { KNOT_TSIG_ALG_HMAC_SHA384, "hmac-sha384" },
- { KNOT_TSIG_ALG_HMAC_SHA512, "hmac-sha512" },
- { KNOT_TSIG_ALG_NULL, NULL }
-};
-
-static int tsig_parse_str(knot_key_t *key, const char *str)
+static int tsig_parse_str(knot_tsig_key_t *key, const char *str)
{
char *h = strdup(str);
if (!h) {
return KNOT_ENOMEM;
}
-
+
char *k = NULL, *s = NULL;
if ((k = (char*)strchr(h, ':'))) { /* Second part - NAME|SECRET */
*k++ = '\0'; /* String separator */
s = (char*)strchr(k, ':'); /* Thirt part - |SECRET */
}
-
+
/* Determine algorithm. */
- key->algorithm = KNOT_TSIG_ALG_HMAC_MD5;
+
+ int algorithm = KNOT_TSIG_ALG_HMAC_MD5;
if (s) {
*s++ = '\0'; /* Last part separator */
knot_lookup_table_t *alg = NULL;
- alg = knot_lookup_by_name(tsig_algn_tbl, h);
+ alg = knot_lookup_by_name(knot_tsig_alg_domain_names, h);
if (alg) {
- key->algorithm = alg->id;
+ algorithm = alg->id;
} else {
free(h);
return KNOT_EINVAL;
@@ -448,27 +304,21 @@ static int tsig_parse_str(knot_key_t *key, const char *str)
s = k; /* Ignore first part, push down. */
k = h;
}
-
+
/* Parse key name. */
- key->name = remote_dname_fqdn(k);
- key->secret = strdup(s);
+
+ int result = knot_tsig_create_key(k, algorithm, s, key);
free(h);
-
- /* Check name and secret. */
- if (!key->name || !key->secret) {
- return KNOT_EINVAL;
- }
-
- return KNOT_EOK;
+ return result;
}
-static int tsig_parse_line(knot_key_t *k, char *l)
+static int tsig_parse_line(knot_tsig_key_t *k, char *l)
{
const char *n, *a, *s;
n = a = s = NULL;
int fw = 1; /* 0 = reading word, 1 = between words */
while (*l != '\0') {
- if (isspace(*l) || *l == '"') {
+ if (isspace((unsigned char)(*l)) || *l == '"') {
*l = '\0';
fw = 1; /* End word. */
} else if (fw) {
@@ -484,41 +334,33 @@ static int tsig_parse_line(knot_key_t *k, char *l)
if (!n) {
return KNOT_EMALF;
}
-
+
/* Assume hmac-md5 if no algo specified. */
if (!s) {
s = a;
a = "hmac-md5";
}
-
- /* Set algorithm. */
- knot_lookup_table_t *alg = knot_lookup_by_name(tsig_algn_tbl, a);
- if (alg) {
- k->algorithm = alg->id;
- } else {
+
+ /* Lookup algorithm. */
+ knot_lookup_table_t *alg;
+ alg = knot_lookup_by_name(knot_tsig_alg_names, a);
+
+ if (!alg) {
return KNOT_EMALF;
}
-
- /* Set name. */
- k->name = remote_dname_fqdn(n);
- k->secret = strdup(s);
-
- /* Check name and secret. */
- if (!k->name || !k->secret) {
- return KNOT_EINVAL;
- }
- return KNOT_EOK;
+ /* Create the key data. */
+ return knot_tsig_create_key(n, alg->id, s, k);
}
-static int tsig_parse_file(knot_key_t *k, const char *f)
+static int tsig_parse_file(knot_tsig_key_t *k, const char *f)
{
FILE* fp = fopen(f, "r");
if (!fp) {
log_server_error("Couldn't open key-file '%s'.\n", f);
return KNOT_EINVAL;
}
-
+
int c = 0;
int ret = KNOT_EOK;
char *line = malloc(64);
@@ -527,7 +369,7 @@ static int tsig_parse_file(knot_key_t *k, const char *f)
if (line) {
lres = 64;
}
-
+
while ((c = fgetc(fp)) != EOF) {
if (mreserve(&line, sizeof(char), llen + 1, 512, &lres) != 0) {
ret = KNOT_ENOMEM;
@@ -547,42 +389,33 @@ static int tsig_parse_file(knot_key_t *k, const char *f)
} else {
line[llen++] = (char)c;
}
-
+
}
-
+
free(line);
fclose(fp);
return ret;
}
-static void tsig_key_cleanup(knot_key_t *k)
-{
- if (k) {
- knot_dname_free(&k->name);
- free(k->secret);
- }
-}
-
int main(int argc, char **argv)
{
/* Parse command line arguments */
- int c = 0, li = 0;
- unsigned jobs = 1;
+ int c = 0, li = 0, rc = 0;
unsigned flags = F_NULL;
char *config_fn = NULL;
char *default_config = conf_find_default();
-
+
/* Remote server descriptor. */
int ret = KNOT_EOK;
const char *r_addr = NULL;
int r_port = -1;
- knot_key_t r_key;
- memset(&r_key, 0, sizeof(knot_key_t));
-
+ knot_tsig_key_t r_key;
+ memset(&r_key, 0, sizeof(knot_tsig_key_t));
+
/* Initialize. */
log_init();
log_levels_set(LOG_SYSLOG, LOG_ANY, 0);
-
+
/* Long options. */
struct option opts[] = {
{"wait", no_argument, 0, 'w'},
@@ -590,7 +423,6 @@ int main(int argc, char **argv)
{"config", required_argument, 0, 'c'},
{"verbose", no_argument, 0, 'v'},
{"interactive", no_argument, 0, 'i'},
- {"jobs", required_argument, 0, 'j'},
{"version", no_argument, 0, 'V'},
{"help", no_argument, 0, 'h'},
{"server", required_argument, 0, 's' },
@@ -600,7 +432,7 @@ int main(int argc, char **argv)
{0, 0, 0, 0}
};
- while ((c = getopt_long(argc, argv, "s:p:y:k:wfc:vij:Vh", opts, &li)) != -1) {
+ while ((c = getopt_long(argc, argv, "s:p:y:k:wfc:viVh", opts, &li)) != -1) {
switch (c) {
case 's':
r_addr = optarg;
@@ -613,7 +445,7 @@ int main(int argc, char **argv)
if (ret != KNOT_EOK) {
log_server_error("Couldn't parse TSIG key '%s' "
"\n", optarg);
- tsig_key_cleanup(&r_key);
+ knot_tsig_key_free(&r_key);
log_close();
return 1;
}
@@ -623,7 +455,7 @@ int main(int argc, char **argv)
if (ret != KNOT_EOK) {
log_server_error("Couldn't parse TSIG key file "
"'%s'\n", optarg);
- tsig_key_cleanup(&r_key);
+ knot_tsig_key_free(&r_key);
log_close();
return 1;
}
@@ -643,48 +475,29 @@ int main(int argc, char **argv)
case 'c':
config_fn = strdup(optarg);
break;
- case 'j':
- jobs = atoi(optarg);
-
- if (jobs < 1) {
- log_server_error("Invalid parameter '%s' to '-j'"
- ", expects number <1..n>\n",
- optarg);
- help(argc, argv);
- log_close();
- free(config_fn);
- free(default_config);
- return 1;
- }
-
- break;
case 'V':
+ rc = 0;
printf("%s, version %s\n", "Knot DNS", PACKAGE_VERSION);
- log_close();
- free(config_fn);
- free(default_config);
- return 0;
+ goto exit;
case 'h':
case '?':
+ rc = 0;
+ help();
+ goto exit;
default:
- help(argc, argv);
- log_close();
- free(config_fn);
- free(default_config);
- return 1;
+ rc = 1;
+ help();
+ goto exit;
}
}
/* Check if there's at least one remaining non-option. */
if (argc - optind < 1) {
- help(argc, argv);
- tsig_key_cleanup(&r_key);
- log_close();
- free(config_fn);
- free(default_config);
- return 1;
+ rc = 1;
+ help();
+ goto exit;
}
-
+
/* Find requested command. */
knot_cmd_t *cmd = knot_cmd_tbl;
while (cmd->name) {
@@ -693,15 +506,12 @@ int main(int argc, char **argv)
}
++cmd;
}
-
+
/* Command not found. */
if (!cmd->name) {
log_server_error("Invalid command: '%s'\n", argv[optind]);
- tsig_key_cleanup(&r_key);
- log_close();
- free(config_fn);
- free(default_config);
- return 1;
+ rc = 1;
+ goto exit;
}
/* Open config, allow if not exists. */
@@ -710,7 +520,7 @@ int main(int argc, char **argv)
flags |= F_NOCONF;
}
}
-
+
/* Create remote iface if not present in config. */
conf_iface_t *ctl_if = conf()->ctl.iface;
if (!ctl_if) {
@@ -718,32 +528,40 @@ int main(int argc, char **argv)
assert(ctl_if);
conf()->ctl.iface = ctl_if;
memset(ctl_if, 0, sizeof(conf_iface_t));
-
+
/* Fill defaults. */
- if (!r_addr) r_addr = "127.0.0.1";
- if (r_port < 0) r_port = REMOTE_DPORT;
-
- /* Create empty key. */
- if (r_key.name) {
- ctl_if->key = malloc(sizeof(knot_key_t));
- if (ctl_if->key) {
- memcpy(ctl_if->key, &r_key, sizeof(knot_key_t));
- }
- }
- } else {
- if (r_key.name) {
- tsig_key_cleanup(ctl_if->key);
- ctl_if->key = &r_key;
- }
+ if (!r_addr)
+ r_addr = RUN_DIR "/knot.sock";
+ else if (r_port < 0)
+ r_port = REMOTE_DPORT;
+ }
+
+ /* Install the key. */
+ if (r_key.name) {
+ ctl_if->key = &r_key;
}
-
+
/* Override from command line. */
if (r_addr) {
free(ctl_if->address);
ctl_if->address = strdup(r_addr);
ctl_if->family = AF_INET;
- if (strchr(r_addr, ':')) { /* Dumb way to check for v6 addr. */
+
+ /* Check for v6 address. */
+ if (strchr(r_addr, ':'))
ctl_if->family = AF_INET6;
+
+ /* Check if address could be a UNIX socket. */
+ if (strchr(r_addr, '/')) {
+ /* Check if file is really a socket. */
+ struct stat st;
+ if (stat(r_addr, &st) == 0 && !S_ISSOCK(st.st_mode)) {
+ log_server_warning("Address '%s' is not a "
+ "UNIX socket.\n", r_addr);
+ }
+
+ ctl_if->family = AF_UNIX;
+ r_port = 0; /* Override. */
}
}
if (r_port > -1) ctl_if->port = r_port;
@@ -755,221 +573,82 @@ int main(int argc, char **argv)
}
/* Execute command. */
- int rc = cmd->cb(argc - optind - 1, argv + optind + 1, flags, jobs);
+ rc = cmd->cb(argc - optind - 1, argv + optind + 1, flags);
+exit:
/* Finish */
- tsig_key_cleanup(&r_key); /* Not cleaned by config deinit. */
+ knot_tsig_key_free(&r_key);
log_close();
free(config_fn);
free(default_config);
return rc;
}
-static int cmd_start(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_stop(int argc, char *argv[], unsigned flags)
{
- /* Check config. */
- if (has_flag(flags, F_NOCONF)) {
- log_server_error("Couldn't parse config file, refusing to "
- "continue.\n");
- return 1;
- }
-
- /* Alter privileges. */
- log_update_privileges(conf()->uid, conf()->gid);
- proc_update_privileges(conf()->uid, conf()->gid);
-
- /* Fetch PID. */
- char *pidfile = pid_filename();
- pid_t pid = pid_read(pidfile);
- log_server_info("Starting server...\n");
-
- /* Prevent concurrent daemon launch. */
- int rc = 0;
- struct stat st;
- int is_pidf = 0;
-
- /* Check PID. */
- if (pid > 0 && pid_running(pid)) {
- log_server_error("Server PID found, already running.\n");
- is_pidf = 1;
- } else if (stat(pidfile, &st) == 0) {
- log_server_warning("PID file '%s' exists, another process "
- "is starting or PID file is stale.\n",
- pidfile);
- is_pidf = 1;
- }
- if (is_pidf) {
- if (!has_flag(flags, F_FORCE)) {
- free(pidfile);
- return 1;
- } else {
- log_server_info("Forcing server start.\n");
- pid_remove(pidfile);
- }
- } else {
- /* Create empty PID file. */
- FILE *f = fopen(pidfile, "w");
- if (f == NULL) {
- log_server_warning("PID file '%s' is not writeable.\n",
- pidfile);
- free(pidfile);
- return 1;
- }
- fclose(f);
- }
-
- /* Recompile zones if needed. */
- cmd_compile(argc, argv, flags, jobs);
-
- /* Prepare command */
- const char *cfg = conf()->filename;
- size_t args_c = 6;
- const char *args[] = {
- PROJECT_EXEC,
- has_flag(flags, F_INTERACTIVE) ? "" : "-d",
- cfg ? "-c" : "",
- cfg ? cfg : "",
- has_flag(flags, F_VERBOSE) ? "-v" : "",
- argc > 0 ? argv[0] : ""
- };
-
- /* Execute command */
- if (has_flag(flags, F_INTERACTIVE)) {
- log_server_info("Running in interactive mode.\n");
- fflush(stderr);
- fflush(stdout);
- }
- if ((rc = cmd_exec(args, args_c)) < 0) {
- pid_remove(pidfile);
- rc = 1;
- }
- fflush(stderr);
- fflush(stdout);
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(flags);
- /* Wait for finish */
- if (has_flag(flags, F_WAIT) && !has_flag(flags, F_INTERACTIVE)) {
- if (has_flag(flags, F_VERBOSE)) {
- log_server_info("Waiting for server to load.\n");
- }
-
- /* Periodically read pidfile and wait for valid result. */
- pid = 0;
- while (pid == 0 || !pid_running(pid)) {
- pid = pid_read(pidfile);
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 500 * 1000;
- select(0, 0, 0, 0, &tv);
- }
- }
-
- free(pidfile);
- return rc;
+ return cmd_remote("stop", KNOT_RRTYPE_TXT, 0, NULL);
}
-static int cmd_stop(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_restart(int argc, char *argv[], unsigned flags)
{
- /* Check config. */
- if (has_flag(flags, F_NOCONF)) {
- log_server_error("Couldn't parse config file, refusing to "
- "continue.\n");
- return 1;
- }
-
- /* Alter privileges. */
- log_update_privileges(conf()->uid, conf()->gid);
- proc_update_privileges(conf()->uid, conf()->gid);
-
- /* Fetch PID. */
- char *pidfile = pid_filename();
- pid_t pid = pid_read(pidfile);
- int rc = 0;
- struct stat st;
-
- /* Check for non-existent PID file. */
- int has_pidf = (stat(pidfile, &st) == 0);
- if(has_pidf && pid <= 0) {
- log_server_warning("Empty PID file '%s' exists, daemon process "
- "is starting or PID file is stale.\n",
- pidfile);
- free(pidfile);
- return 1;
- } else if (pid <= 0 || !pid_running(pid)) {
- log_server_warning("Server PID not found, "
- "probably not running.\n");
- if (!has_flag(flags, F_FORCE)) {
- free(pidfile);
- return 1;
- } else {
- log_server_info("Forcing server stop.\n");
- }
- }
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(flags);
- /* Stop */
- log_server_info("Stopping server...\n");
- if (kill(pid, SIGTERM) < 0) {
- pid_remove(pidfile);
- rc = 1;
- }
-
-
- /* Wait for finish */
- if (rc == 0 && has_flag(flags, F_WAIT)) {
- log_server_info("Waiting for server to finish.\n");
- while (pid_running(pid)) {
- struct timeval tv;
- tv.tv_sec = 0;
- tv.tv_usec = 500 * 1000;
- select(0, 0, 0, 0, &tv);
- pid = pid_read(pidfile); /* Update */
- }
- }
-
- return rc;
+ return cmd_remote("restart", KNOT_RRTYPE_TXT, 0, NULL);
}
-static int cmd_restart(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_reload(int argc, char *argv[], unsigned flags)
{
- /* Check config. */
- if (has_flag(flags, F_NOCONF)) {
- log_server_error("Couldn't parse config file, refusing to "
- "continue.\n");
- return 1;
- }
-
- int rc = 0;
- rc |= cmd_stop(argc, argv, flags | F_WAIT, jobs);
- rc |= cmd_start(argc, argv, flags, jobs);
- return rc;
-}
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(flags);
-static int cmd_reload(int argc, char *argv[], unsigned flags, int jobs)
-{
return cmd_remote("reload", KNOT_RRTYPE_TXT, 0, NULL);
}
-static int cmd_refresh(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_refresh(int argc, char *argv[], unsigned flags)
{
- return cmd_remote("refresh", KNOT_RRTYPE_CNAME, argc, argv);
+ UNUSED(flags);
+
+ return cmd_remote("refresh", KNOT_RRTYPE_NS, argc, argv);
}
-static int cmd_flush(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_flush(int argc, char *argv[], unsigned flags)
{
- return cmd_remote("flush", KNOT_RRTYPE_CNAME, argc, argv);
+ UNUSED(flags);
+
+ return cmd_remote("flush", KNOT_RRTYPE_NS, argc, argv);
}
-static int cmd_status(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_status(int argc, char *argv[], unsigned flags)
{
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(flags);
+
return cmd_remote("status", KNOT_RRTYPE_TXT, 0, NULL);
}
-static int cmd_zonestatus(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_zonestatus(int argc, char *argv[], unsigned flags)
{
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(flags);
+
return cmd_remote("zonestatus", KNOT_RRTYPE_TXT, 0, NULL);
}
-static int cmd_checkconf(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_checkconf(int argc, char *argv[], unsigned flags)
{
+ UNUSED(argc);
+ UNUSED(argv);
+ UNUSED(flags);
+
/* Check config. */
if (has_flag(flags, F_NOCONF)) {
log_server_error("Couldn't parse config file, refusing to "
@@ -978,39 +657,26 @@ static int cmd_checkconf(int argc, char *argv[], unsigned flags, int jobs)
} else {
log_server_info("OK, configuration is valid.\n");
}
-
+
return 0;
}
-static int cmd_checkzone(int argc, char *argv[], unsigned flags, int jobs)
+static int cmd_checkzone(int argc, char *argv[], unsigned flags)
{
- return cmd_compile(argc, argv, flags | F_DRYRUN, jobs);
-}
-
-static int cmd_compile(int argc, char *argv[], unsigned flags, int jobs)
-{
- /* Print job count */
- if (jobs > 1 && argc == 0) {
- log_server_warning("Will attempt to compile %d zones "
- "in parallel, this increases memory "
- "consumption for large zones.\n", jobs);
- }
+ UNUSED(flags);
/* Zone checking */
int rc = 0;
node *n = 0;
- int running = 0;
- int is_checkzone = has_flag(flags, F_DRYRUN);
- knotc_zctask_t *tasks = zctask_create(jobs);
-
+
/* Generate databases for all zones */
WALK_LIST(n, conf()->zones) {
/* Fetch zone */
conf_zone_t *zone = (conf_zone_t *) n;
int zone_match = 0;
- for (unsigned i = 0; i < argc; ++i) {
+ for (unsigned i = 0; i < (unsigned)argc; ++i) {
size_t len = strlen(zone->name);
-
+
/* All (except root) without final dot */
if (len > 1) {
len -= 1;
@@ -1022,68 +688,151 @@ static int cmd_compile(int argc, char *argv[], unsigned flags, int jobs)
}
if (!zone_match && argc > 0) {
+ /* WALK_LIST is a for-cycle. */
continue;
}
- /* Check source files and mtime */
- int zone_status = check_zone(zone->db, zone->file);
- if (zone_status == KNOT_EOK && !is_checkzone) {
- log_zone_info("Zone '%s' is up-to-date.\n", zone->name);
- if (has_flag(flags, F_FORCE)) {
- log_zone_info("Forcing zone "
- "recompilation.\n");
- } else {
- continue;
- }
+ /* Create zone loader context. */
+ zloader_t *l = NULL;
+ int ret = knot_zload_open(&l, zone->file, zone->name,
+ zone->enable_checks);
+ if (ret != KNOT_EOK) {
+ log_zone_error("Could not open zone %s (%s).\n",
+ zone->name, knot_strerror(ret));
+ knot_zload_close(l);
+ rc = 1;
+ continue;
}
- /* Check for not existing source */
- if (zone_status == KNOT_ENOENT) {
+ knot_zone_t *z = knot_zload_load(l);
+ if (z == NULL) {
+ log_zone_error("Loading of zone %s failed.\n",
+ zone->name);
+ knot_zload_close(l);
+ rc = 1;
continue;
}
- /* Evaluate space for new task. */
- if (running == jobs) {
- rc |= zctask_wait(tasks, jobs, is_checkzone);
- --running;
- }
+ knot_zone_deep_free(&z);
+ knot_zload_close(l);
+ log_zone_info("Zone %s OK.\n", zone->name);
+ }
- /* Build executable command. */
- int ac = 0;
- const char *args[7] = { NULL };
- args[ac++] = ZONEPARSER_EXEC;
- if (zone->enable_checks) {
- args[ac++] = "-s";
- }
- if (has_flag(flags, F_VERBOSE)) {
- args[ac++] = "-v";
+ return rc;
+}
+
+static int cmd_memstats(int argc, char *argv[], unsigned flags)
+{
+ UNUSED(flags);
+
+ /* Zone checking */
+ int rc = 0;
+ node *n = 0;
+ size_t total_size = 0;
+
+ /* Generate databases for all zones */
+ WALK_LIST(n, conf()->zones) {
+ /* Fetch zone */
+ conf_zone_t *zone = (conf_zone_t *) n;
+ int zone_match = 0;
+ for (unsigned i = 0; i < (unsigned)argc; ++i) {
+ size_t len = strlen(zone->name);
+
+ /* All (except root) without final dot */
+ if (len > 1) {
+ len -= 1;
+ }
+ if (strncmp(zone->name, argv[i], len) == 0) {
+ zone_match = 1;
+ break;
+ }
}
- if (!is_checkzone) {
- args[ac++] = "-o";
- args[ac++] = zone->db;
+
+ if (!zone_match && argc > 0) {
+ /* WALK_LIST is a for-cycle. */
+ continue;
}
- args[ac++] = zone->name;
- args[ac++] = zone->file;
- /* Execute command */
- if (has_flag(flags, F_VERBOSE) && !is_checkzone) {
- log_zone_info("Compiling '%s' as '%s'...\n",
- zone->name, zone->db);
+ /* Init malloc wrapper for trie size estimation. */
+ size_t malloc_size = 0;
+ mm_ctx_t mem_ctx = { .ctx = &malloc_size,
+ .alloc = estimator_malloc,
+ .free = estimator_free };
+
+ /* Init memory estimation context. */
+ zone_estim_t est = {.node_table = hattrie_create_n(TRIE_BUCKET_SIZE, &mem_ctx),
+ .dname_table = hattrie_create_n(TRIE_BUCKET_SIZE, &mem_ctx),
+ .dname_size = 0, .rrset_size = 0,
+ .node_size = 0, .ahtable_size = 0,
+ .rdata_size = 0, .record_count = 0 };
+ if (est.node_table == NULL) {
+ if (est.dname_table) {
+ hattrie_free(est.dname_table);
+ }
+ log_server_error("Not enough memory.\n");
+ continue;
+ }
+ if (est.dname_table == NULL) {
+ if (est.node_table) {
+ hattrie_free(est.node_table);
+ }
+ log_server_error("Not enough memory.\n");
+ continue;
}
- fflush(stdout);
- fflush(stderr);
- pid_t zcpid = pid_start(args, ac,
- has_flag(flags, F_UNPRIVILEGED));
- zctask_add(tasks, jobs, zcpid, zone);
- ++running;
- }
- /* Wait for all running tasks. */
- while (running > 0) {
- rc |= zctask_wait(tasks, jobs, is_checkzone);
- --running;
+ /* Create file loader. */
+ file_loader_t *loader = file_loader_create(zone->file, zone->name,
+ KNOT_CLASS_IN, 3600,
+ estimator_rrset_memsize_wrap,
+ process_error,
+ &est);
+ if (loader == NULL) {
+ log_zone_error("Could not load zone.\n");
+ hattrie_apply_rev(est.node_table, estimator_free_trie_node, NULL);
+ hattrie_apply_rev(est.dname_table, estimator_free_trie_node, NULL);
+ hattrie_free(est.node_table);
+ hattrie_free(est.dname_table);
+ return KNOT_ERROR;
+ }
+
+ /* Do a parser run, but do not actually create the zone. */
+ int ret = file_loader_process(loader);
+ if (ret != KNOT_EOK) {
+ log_zone_error("Failed to parse zone.\n");
+ hattrie_apply_rev(est.node_table, estimator_free_trie_node, NULL);
+ hattrie_apply_rev(est.dname_table, estimator_free_trie_node, NULL);
+ hattrie_free(est.node_table);
+ hattrie_free(est.dname_table);
+ file_loader_free(loader);
+ return KNOT_ERROR;
+ }
+
+ /* Only size of ahtables inside trie's nodes is missing. */
+ assert(est.ahtable_size == 0);
+ est.ahtable_size = estimator_trie_ahtable_memsize(est.node_table);
+
+ /* Cleanup */
+ hattrie_apply_rev(est.node_table, estimator_free_trie_node, NULL);
+ hattrie_apply_rev(est.dname_table, estimator_free_trie_node, NULL);
+ hattrie_free(est.node_table);
+ hattrie_free(est.dname_table);
+
+ size_t zone_size = (size_t)(((double)(est.rdata_size +
+ est.node_size +
+ est.rrset_size +
+ est.dname_size +
+ est.ahtable_size +
+ malloc_size) * ESTIMATE_MAGIC) / (1024.0 * 1024.0));
+
+ log_zone_info("Zone %s: %zu RRs, used memory estimation is %zuMB.\n",
+ zone->name, est.record_count, zone_size);
+ file_loader_free(loader);
+ total_size += zone_size;
+ }
+
+ if (argc == 0) { // for all zones
+ log_zone_info("Estimated memory consumption for all zones is %zuMB.\n", total_size);
}
- free(tasks);
return rc;
}
diff --git a/src/knot/ctl/process.c b/src/knot/ctl/process.c
index 94306c2..f5db3ca 100644
--- a/src/knot/ctl/process.c
+++ b/src/knot/ctl/process.c
@@ -25,19 +25,22 @@
#include <unistd.h>
#include <assert.h>
#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/ctl/process.h"
#include "knot/conf/conf.h"
+#include "common/mempattern.h"
char* pid_filename()
{
rcu_read_lock();
/* Read configuration. */
- char* ret = 0;
- if (conf() && conf()->pidfile != NULL) {
- ret = strdup(conf()->pidfile);
+ char* ret = NULL;
+ if (conf() && conf()->rundir != NULL) {
+ ret = strcdup(conf()->rundir, "/knot.pid");
}
rcu_read_unlock();
@@ -74,7 +77,8 @@ pid_t pid_read(const char* fn)
// Convert pid
char* ep = 0;
unsigned long pid = strtoul(buf, &ep, 10);
- if ((errno == ERANGE) || (*ep && !isspace(*ep))) {
+ if ((errno == ERANGE) ||
+ (*ep && !isspace((unsigned char)(*ep)))) {
return KNOT_ERANGE;
}
@@ -86,37 +90,33 @@ pid_t pid_read(const char* fn)
int pid_write(const char* fn)
{
- if (!fn) {
+ if (!fn)
return KNOT_EINVAL;
- }
- // Convert
+ /* Convert. */
char buf[64];
- int wbytes = 0;
- wbytes = snprintf(buf, sizeof(buf), "%lu", (unsigned long) getpid());
- if (wbytes < 0) {
+ int len = 0;
+ len = snprintf(buf, sizeof(buf), "%lu", (unsigned long) getpid());
+ if (len < 0)
return KNOT_EINVAL;
- }
- // Write
- FILE *fp = fopen(fn, "w");
- if (fp) {
- int rc = fwrite(buf, wbytes, 1, fp);
- fclose(fp);
- if (rc < 0) {
- return KNOT_ERROR;
- }
-
- return 0;
+ /* Create file. */
+ int ret = KNOT_EOK;
+ int fd = open(fn, O_RDWR|O_CREAT, 0644);
+ if (fd >= 0) {
+ if (write(fd, buf, len) != len)
+ ret = KNOT_ERROR;
+ close(fd);
+ } else {
+ ret = knot_map_errno(errno);
}
- return KNOT_ENOENT;
+ return ret;
}
int pid_remove(const char* fn)
{
if (unlink(fn) < 0) {
- perror("unlink");
return KNOT_EINVAL;
}
@@ -128,11 +128,11 @@ int pid_running(pid_t pid)
return kill(pid, 0) == 0;
}
-void proc_update_privileges(int uid, int gid)
+int proc_update_privileges(int uid, int gid)
{
#ifdef HAVE_SETGROUPS
/* Drop supplementary groups. */
- if (uid != getuid() || gid != getgid()) {
+ if ((uid_t)uid != getuid() || (gid_t)gid != getgid()) {
if (setgroups(0, NULL) < 0) {
log_server_warning("Failed to drop supplementary groups"
" for uid '%d' (%s).\n",
@@ -140,93 +140,64 @@ void proc_update_privileges(int uid, int gid)
}
}
#endif
-
+
/* Watch uid/gid. */
- if (gid != getgid()) {
+ if ((gid_t)gid != getgid()) {
log_server_info("Changing group id to '%d'.\n", gid);
if (setregid(gid, gid) < 0) {
log_server_error("Failed to change gid to '%d'.\n",
gid);
}
}
- if (uid != getuid()) {
+ if ((uid_t)uid != getuid()) {
log_server_info("Changing user id to '%d'.\n", uid);
if (setreuid(uid, uid) < 0) {
log_server_error("Failed to change uid to '%d'.\n",
uid);
}
}
-
+
/* Check storage writeability. */
+ int ret = KNOT_EOK;
char *lfile = strcdup(conf()->storage, "/knot.lock");
assert(lfile != NULL);
FILE* fp = fopen(lfile, "w");
if (fp == NULL) {
log_server_warning("Storage directory '%s' is not writeable.\n",
conf()->storage);
+ ret = KNOT_EACCES;
} else {
fclose(fp);
unlink(lfile);
}
- free(lfile);
-}
-pid_t pid_wait(pid_t proc, int *rc)
-{
- /* Wait for finish. */
- sigset_t newset;
- sigfillset(&newset);
- sigprocmask(SIG_BLOCK, &newset, 0);
- proc = waitpid(proc, rc, 0);
- sigprocmask(SIG_UNBLOCK, &newset, 0);
- return proc;
+ free(lfile);
+ return ret;
}
-
-pid_t pid_start(const char *argv[], int argc, int drop_privs)
+char *pid_check_and_create()
{
- pid_t chproc = fork();
- if (chproc == 0) {
-
- /* Alter privileges. */
- if (drop_privs) {
- proc_update_privileges(conf()->uid, conf()->gid);
- }
-
- /* Duplicate, it doesn't run from stack address anyway. */
- char **args = malloc((argc + 1) * sizeof(char*));
- memset(args, 0, (argc + 1) * sizeof(char*));
- int ci = 0;
- for (int i = 0; i < argc; ++i) {
- if (strlen(argv[i]) > 0) {
- args[ci++] = strdup(argv[i]);
- }
- }
- args[ci] = 0;
-
- /* Execute command. */
- fflush(stdout);
- fflush(stderr);
- execvp(args[0], args);
-
- /* Execute failed. */
- log_server_error("Failed to run executable '%s'\n", args[0]);
- for (int i = 0; i < argc; ++i) {
- free(args[i]);
- }
- free(args);
+ struct stat st;
+ char* pidfile = pid_filename();
+ pid_t pid = pid_read(pidfile);
+
+ /* Check PID for existence and liveness. */
+ if (pid > 0 && pid_running(pid)) {
+ log_server_error("Server PID found, already running.\n");
+ free(pidfile);
+ return NULL;
+ } else if (stat(pidfile, &st) == 0) {
+ log_server_warning("Removing stale PID file '%s'.\n", pidfile);
+ pid_remove(pidfile);
+ }
- exit(1);
- return -1;
+ /* Create a PID file. */
+ int ret = pid_write(pidfile);
+ if (ret != KNOT_EOK) {
+ log_server_error("Couldn't create a PID file '%s'.\n", pidfile);
+ free(pidfile);
+ return NULL;
}
-
- return chproc;
-}
-int cmd_exec(const char *argv[], int argc)
-{
- int ret = 0;
- pid_t proc = pid_start(argv, argc, 0);
- pid_wait(proc, &ret);
- return ret;
+ return pidfile;
}
diff --git a/src/knot/ctl/process.h b/src/knot/ctl/process.h
index b80b968..410a2e1 100644
--- a/src/knot/ctl/process.h
+++ b/src/knot/ctl/process.h
@@ -89,41 +89,18 @@ int pid_running(pid_t pid);
* \param uid New user ID.
* \param gid New group ID.
*
+ * \retval KNOT_EOK on success.
+ * \retval KNOT_EACCESS if storage is not writeable.
*/
-void proc_update_privileges(int uid, int gid);
+int proc_update_privileges(int uid, int gid);
-/*!
- * \brief Wait for process to finish.
- *
- * \param proc Process ID.
- * \param rc Destination for return code.
- *
- * \return PID of finished process.
- */
-pid_t pid_wait(pid_t proc, int *rc);
/*!
- * \brief Start command with given parameters.
- *
- * Set drop_privs = 1 to change privileges according to conf().
- *
- * \param argv Parameter list.
- * \param argc Parameter count.
- * \param drop_privs Set to 1 to alter privileges.
- *
- * \return PID of started process.
- */
-pid_t pid_start(const char *argv[], int argc, int drop_privs);
-
-/*!
- * \brief Execute command and wait for finish.
- *
- * \param argv Parameter list.
- * \param argc Parameter count.
- *
- * \return Return code.
+ * \brief Check if PID file exists and create it if possible.
+ * \retval NULL if failed
+ * \retval Created PID file path
*/
-int cmd_exec(const char *argv[], int argc);
+char *pid_check_and_create();
#endif // _KNOTD_PROCESS_H_
diff --git a/src/knot/ctl/remote.c b/src/knot/ctl/remote.c
index ac8bc25..7de68b5 100644
--- a/src/knot/ctl/remote.c
+++ b/src/knot/ctl/remote.c
@@ -14,17 +14,19 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "remote.h"
#include "common/log.h"
#include "common/fdset.h"
#include "common/prng.h"
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/conf/conf.h"
#include "knot/server/socket.h"
#include "knot/server/tcp-handler.h"
#include "knot/server/zones.h"
#include "libknot/util/wire.h"
#include "libknot/packet/query.h"
+#include "common/descriptor.h"
#include "libknot/packet/response.h"
#include "libknot/nameserver/name-server.h"
#include "libknot/tsig-op.h"
@@ -56,6 +58,8 @@ typedef struct remote_cmd_t {
} remote_cmd_t;
/* Forward decls. */
+static int remote_c_stop(server_t *s, remote_cmdargs_t* a);
+static int remote_c_restart(server_t *s, remote_cmdargs_t* a);
static int remote_c_reload(server_t *s, remote_cmdargs_t* a);
static int remote_c_refresh(server_t *s, remote_cmdargs_t* a);
static int remote_c_status(server_t *s, remote_cmdargs_t* a);
@@ -64,6 +68,8 @@ static int remote_c_flush(server_t *s, remote_cmdargs_t* a);
/*! \brief Table of remote commands. */
struct remote_cmd_t remote_cmd_tbl[] = {
+ { "stop", &remote_c_stop },
+ { "restart", &remote_c_restart },
{ "reload", &remote_c_reload },
{ "refresh", &remote_c_refresh },
{ "status", &remote_c_status },
@@ -80,39 +86,32 @@ static int remote_rdata_apply(server_t *s, remote_cmdargs_t* a, remote_zonef_t *
if (!s || !a || !cb) {
return KNOT_EINVAL;
}
-
+
knot_nameserver_t *ns = s->nameserver;
knot_zone_t *zone = NULL;
int ret = KNOT_EOK;
-
+
/* Refresh specific zones. */
for (unsigned i = 0; i < a->argc; ++i) {
- rcu_read_lock();
-
/* Process all zones in data section. */
const knot_rrset_t *rr = a->arg[i];
- if (knot_rrset_type(rr) != KNOT_RRTYPE_CNAME) {
+ if (knot_rrset_type(rr) != KNOT_RRTYPE_NS) {
continue;
}
-
- const knot_rdata_t *rd = knot_rrset_rdata(rr);
- while (rd != NULL) {
- /* Skip empty nodes. */
- if (knot_rdata_item_count(rd) < 1) {
- rd = knot_rrset_rdata_next(rr, rd);
- continue;
- }
+
+ for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rr); i++) {
/* Refresh zones. */
- const knot_dname_t *dn = knot_rdata_item(rd, 0)->dname;
+ const knot_dname_t *dn =
+ knot_rrset_rdata_ns_name(rr, i);
+ rcu_read_lock();
zone = knot_zonedb_find_zone(ns->zone_db, dn);
if (cb(s, zone) != KNOT_EOK) {
a->rc = KNOT_RCODE_SERVFAIL;
}
- rd = knot_rrset_rdata_next(rr, rd);
+ rcu_read_unlock();
}
- rcu_read_unlock();
}
-
+
return ret;
}
@@ -122,21 +121,21 @@ static int remote_zone_refresh(server_t *s, const knot_zone_t *z)
if (!s || !z) {
return KNOT_EINVAL;
}
-
+
knot_nameserver_t *ns = s->nameserver;
evsched_t *sch = ((server_t *)knot_ns_get_data(ns))->sched;
zonedata_t *zd = (zonedata_t *)knot_zone_data(z);
if (!sch || !zd) {
return KNOT_EINVAL;
}
-
+
/* Expire REFRESH timer. */
if (zd->xfr_in.timer) {
evsched_cancel(sch, zd->xfr_in.timer);
evsched_schedule(sch, zd->xfr_in.timer,
tls_rand() * 1000);
}
-
+
return KNOT_EOK;
}
@@ -146,41 +145,47 @@ static int remote_zone_flush(server_t *s, const knot_zone_t *z)
if (!s || !z) {
return KNOT_EINVAL;
}
-
+
knot_nameserver_t *ns = s->nameserver;
evsched_t *sch = ((server_t *)knot_ns_get_data(ns))->sched;
zonedata_t *zd = (zonedata_t *)knot_zone_data(z);
if (!sch || !zd) {
return KNOT_EINVAL;
}
-
+
/* Expire IXFR sync timer. */
if (zd->ixfr_dbsync) {
evsched_cancel(sch, zd->ixfr_dbsync);
evsched_schedule(sch, zd->ixfr_dbsync,
tls_rand() * 1000);
}
-
+
return KNOT_EOK;
}
-/*! \brief Helper to build RDATA from RDATA item. */
-knot_rdata_t* remote_build_rdata(knot_rdata_item_t *i, unsigned c)
+/*!
+ * \brief Remote command 'stop' handler.
+ *
+ * QNAME: stop
+ * DATA: NULL
+ */
+static int remote_c_stop(server_t *s, remote_cmdargs_t* a)
{
- /* Create RDATA. */
- knot_rdata_t *rd = knot_rdata_new();
- if (!rd) {
- return NULL;
- }
-
- /* Set RDATA items. */
- int ret = knot_rdata_set_items(rd, i, c);
- if (ret != KNOT_EOK) {
- knot_rdata_free(&rd);
- return NULL;
- }
-
- return rd;
+ UNUSED(a);
+ UNUSED(s);
+ return KNOT_CTL_STOP;
+}
+
+/*!
+ * \brief Remote command 'restart' handler.
+ *
+ * QNAME: restart
+ * DATA: NULL
+ */
+static int remote_c_restart(server_t *s, remote_cmdargs_t* a)
+{
+ UNUSED(a);
+ return KNOT_CTL_RESTART;
}
/*!
@@ -191,6 +196,7 @@ knot_rdata_t* remote_build_rdata(knot_rdata_item_t *i, unsigned c)
*/
static int remote_c_reload(server_t *s, remote_cmdargs_t* a)
{
+ UNUSED(a);
return server_reload(s, conf()->filename);
}
@@ -202,6 +208,8 @@ static int remote_c_reload(server_t *s, remote_cmdargs_t* a)
*/
static int remote_c_status(server_t *s, remote_cmdargs_t* a)
{
+ UNUSED(s);
+ UNUSED(a);
/*! \todo #2035 Add some TXT RRs with stats. */
dbg_server("remote: %s\n", __func__);
return KNOT_EOK;
@@ -218,32 +226,25 @@ static int remote_c_zonestatus(server_t *s, remote_cmdargs_t* a)
dbg_server("remote: %s\n", __func__);
char *dst = a->resp;
size_t rb = sizeof(a->resp) - 1;
-
+
int ret = KNOT_EOK;
rcu_read_lock();
knot_nameserver_t *ns = s->nameserver;
const knot_zone_t **zones = knot_zonedb_zones(ns->zone_db);
for (unsigned i = 0; i < knot_zonedb_zone_count(ns->zone_db); ++i) {
zonedata_t *zd = (zonedata_t *)zones[i]->data;
-
+
/* Fetch latest serial. */
const knot_rrset_t *soa_rrs = 0;
- const knot_rdata_t *soa_rr = 0;
uint32_t serial = 0;
knot_zone_contents_t *contents = knot_zone_get_contents(zones[i]);
if (contents) {
soa_rrs = knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
assert(soa_rrs != NULL);
-
- soa_rr = knot_rrset_rdata(soa_rrs);
-
- int64_t serial_ret = knot_rdata_soa_serial(soa_rr);
- if (serial_ret > 0) {
- serial = (uint32_t)serial_ret;
- }
+ serial = knot_rrset_rdata_soa_serial(soa_rrs);
}
-
+
/* Evalute zone type. */
const char *state = NULL;
if (serial == 0) {
@@ -251,15 +252,11 @@ static int remote_c_zonestatus(server_t *s, remote_cmdargs_t* a)
} else if (zd->xfr_in.has_master) {
state = "xfer";
}
-
+
/* Evaluate zone state. */
char *when = NULL;
- int locked = pthread_mutex_trylock(&zd->xfr_in.lock);
- if (locked == 0) pthread_mutex_unlock(&zd->xfr_in.lock);
- if (locked != 0) {
+ if (zd->xfr_in.state == XFR_PENDING) {
when = strdup("pending");
- } else if (zd->xfr_in.scheduled) {
- when = strdup("scheduled");
} else if (zd->xfr_in.timer) {
struct timeval now, dif;
gettimeofday(&now, 0);
@@ -269,7 +266,12 @@ static int remote_c_zonestatus(server_t *s, remote_cmdargs_t* a)
ret = KNOT_ENOMEM;
break;
}
- if (snprintf(when, 64, "in %luh%lum%lus",
+ /*! Workaround until proper zone fetching API and locking
+ * is implemented (ref #31)
+ */
+ if (dif.tv_sec < 0) {
+ memcpy(when, "busy", 5);
+ } else if (snprintf(when, 64, "in %luh%lum%lus",
dif.tv_sec/3600,
(dif.tv_sec % 3600)/60,
dif.tv_sec % 60) < 0) {
@@ -283,28 +285,29 @@ static int remote_c_zonestatus(server_t *s, remote_cmdargs_t* a)
/* Workaround, some platforms ignore 'size' with snprintf() */
char buf[256];
- int n = snprintf(buf, sizeof(buf), "%s\ttype=%s | serial=%u | %s %s\n",
+ int n = snprintf(buf, sizeof(buf),
+ "%s\ttype=%s | serial=%u | %s %s\n",
zd->conf->name,
zd->xfr_in.has_master ? "slave" : "master",
serial,
state ? state : "",
when ? when : "");
free(when);
- if (n > rb) {
+ if (n < 0 || (size_t)n > rb) {
*dst = '\0';
ret = KNOT_ESPACE;
break;
}
-
+
memcpy(dst, buf, n);
rb -= n;
dst += n;
-
-
+
+
}
rcu_read_unlock();
free(zones);
-
+
a->rlen = sizeof(a->resp) - 1 - rb;
return ret;
}
@@ -324,7 +327,7 @@ static int remote_c_refresh(server_t *s, remote_cmdargs_t* a)
dbg_server_verb("remote: refreshing all zones\n");
return server_refresh(s);
}
-
+
/* Refresh specific zones. */
return remote_rdata_apply(s, a, &remote_zone_refresh);
}
@@ -353,11 +356,25 @@ static int remote_c_flush(server_t *s, remote_cmdargs_t* a)
free(zones);
return ret;
}
-
+
/* Flush specific zones. */
return remote_rdata_apply(s, a, &remote_zone_flush);
}
+/*!
+ * \brief Prepare and send error response.
+ * \param c Client fd.
+ * \param buf Query buffer.
+ * \param buflen Query size.
+ * \return number of bytes sent
+ */
+static int remote_senderr(int c, uint8_t *qbuf, size_t buflen)
+{
+ knot_wire_set_qr(qbuf);
+ knot_wire_set_rcode(qbuf, KNOT_RCODE_REFUSED);
+ return tcp_send(c, qbuf, buflen);
+}
+
/* Public APIs. */
int remote_bind(conf_iface_t *desc)
@@ -365,29 +382,26 @@ int remote_bind(conf_iface_t *desc)
if (!desc) {
return -1;
}
-
+
/* Create new socket. */
- int s = socket_create(desc->family, SOCK_STREAM);
+ int s = socket_create(desc->family, SOCK_STREAM, 0);
if (s < 0) {
log_server_error("Couldn't create socket for remote "
- "control interface - %s",
- knot_strerror(s));
+ "control interface - %s", knot_strerror(s));
return KNOT_ERROR;
}
-
+
/* Bind to interface and start listening. */
int r = socket_bind(s, desc->family, desc->address, desc->port);
if (r == KNOT_EOK) {
r = socket_listen(s, TCP_BACKLOG_SIZE);
}
if (r != KNOT_EOK) {
+ log_server_error("Could not bind to remote control interface.\n");
socket_close(s);
- log_server_error("Could not bind to "
- "remote control interface %s port %d.\n",
- desc->address, desc->port);
return r;
}
-
+
return s;
}
@@ -396,7 +410,7 @@ int remote_unbind(int r)
if (r < 0) {
return KNOT_EINVAL;
}
-
+
return socket_close(r);
}
@@ -405,7 +419,7 @@ int remote_poll(int r)
if (r < 0) {
return -1;
}
-
+
/* Wait for events. */
fd_set rfds;
FD_ZERO(&rfds);
@@ -429,7 +443,7 @@ int remote_recv(int r, sockaddr_t *a, uint8_t* buf, size_t *buflen)
socket_close(c);
return KNOT_ECONNREFUSED;
}
-
+
return c;
}
@@ -441,16 +455,17 @@ int remote_parse(knot_packet_t* pkt, const uint8_t* buf, size_t buflen)
dbg_server("remote: failed to parse packet\n");
return KNOT_EINVAL;
}
- ret = knot_packet_parse_rest(pkt);
+ ret = knot_packet_parse_rest(pkt, 0);
if (ret != KNOT_EOK) {
dbg_server("remote: failed to parse packet data\n");
return KNOT_EINVAL;
}
-
+
return ret;
}
-static int tmp_send(int c, knot_packet_t *pkt, const char* d, uint16_t dlen, uint8_t* rwire, size_t rlen)
+static int remote_send_chunk(int c, knot_packet_t *pkt, const char* d,
+ uint16_t dlen, uint8_t* rwire, size_t rlen)
{
int ret = KNOT_ERROR;
knot_packet_t *resp = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
@@ -482,24 +497,28 @@ static int tmp_send(int c, knot_packet_t *pkt, const char* d, uint16_t dlen, uin
if (len == 0) {
return KNOT_ERROR;
}
-
+
/* Evaluate output. */
- int rr_count = 0;
+ uint16_t rr_count = 0;
knot_rrset_t *rr = remote_build_rr("result.", KNOT_RRTYPE_TXT);
- knot_rdata_t *rd = remote_create_txt(d, dlen);
- knot_rrset_add_rdata(rr, rd);
+ remote_create_txt(rr, d, dlen);
+
size_t rrlen = rlen;
- knot_rrset_to_wire(rr, rwire + len, &rrlen, &rr_count);
+ ret = knot_rrset_to_wire(rr, rwire + len, &rrlen, rlen, &rr_count, NULL);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&rr, 1, 1);
+ return ret;
+ }
knot_wire_set_nscount(rwire, rr_count);
len += rrlen;
rlen -= rrlen;
- knot_rrset_deep_free(&rr, 1, 1, 1);
-
+ knot_rrset_deep_free(&rr, 1, 1);
+
if (len > 0) {
return tcp_send(c, rwire, len);
}
-
+
return len;
}
@@ -508,7 +527,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
if (fd < 0 || !s || !pkt || !rwire) {
return KNOT_EINVAL;
}
-
+
/* Prerequisites:
* QCLASS: CH
* QNAME: <CMD>.KNOT_CTL_REALM.
@@ -518,7 +537,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
dbg_server("remote: qclass != CH\n");
return KNOT_EMALF;
}
-
+
knot_dname_t *realm = knot_dname_new_from_str(KNOT_CTL_REALM,
KNOT_CTL_REALM_LEN, NULL);
if (!knot_dname_is_subdomain(qname, realm) != 0) {
@@ -527,7 +546,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
return KNOT_EMALF;
}
knot_dname_free(&realm);
-
+
/* Command:
* QNAME: leftmost label of QNAME
*/
@@ -548,7 +567,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
args->arg = pkt->authority;
args->argc = knot_packet_authority_rrset_count(pkt);
args->rc = KNOT_RCODE_NOERROR;
-
+
remote_cmd_t *c = remote_cmd_tbl;
while(c->name != NULL) {
if (strcmp(cmd, c->name) == 0) {
@@ -557,46 +576,42 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
}
++c;
}
-
+
/* Prepare response. */
if (ret != KNOT_EOK || args->rlen == 0) {
args->rlen = strlen(knot_strerror(ret));
strncpy(args->resp, knot_strerror(ret), args->rlen);
}
-
+
unsigned p = 0;
size_t chunk = 16384;
for (; p + chunk < args->rlen; p += chunk) {
- tmp_send(fd, pkt, args->resp + p, chunk, rwire, rlen);
+ remote_send_chunk(fd, pkt, args->resp + p, chunk, rwire, rlen);
}
+
unsigned r = args->rlen - p;
if (r > 0) {
- tmp_send(fd, pkt, args->resp + p, r, rwire, rlen);
+ remote_send_chunk(fd, pkt, args->resp + p, r, rwire, rlen);
}
-
-
+
free(args);
free(cmd);
return ret;
}
-int remote_process(server_t *s, int r, uint8_t* buf, size_t buflen)
+int remote_process(server_t *s, conf_iface_t *ctl_if, int r,
+ uint8_t* buf, size_t buflen)
{
knot_packet_t *pkt = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
if (!pkt) {
dbg_server("remote: not enough space to allocate query\n");
return KNOT_ENOMEM;
}
-
+
/* Initialize remote party address. */
- rcu_read_lock();
sockaddr_t a;
- conf_iface_t *ctl_if = conf()->ctl.iface;
- if (ctl_if) {
- sockaddr_init(&a, ctl_if->family);
- }
- rcu_read_unlock();
-
+ sockaddr_prep(&a);
+
/* Accept incoming connection and read packet. */
size_t wire_len = buflen;
int c = remote_recv(r, &a, buf, &wire_len);
@@ -605,14 +620,16 @@ int remote_process(server_t *s, int r, uint8_t* buf, size_t buflen)
knot_packet_free(&pkt);
return c;
}
-
+
/* Parse packet and answer if OK. */
int ret = remote_parse(pkt, buf, wire_len);
- if (ret == KNOT_EOK) {
-
+ if (ret == KNOT_EOK && ctl_if->family != AF_UNIX) {
+
/* Check ACL list. */
- rcu_read_lock();
- knot_key_t *k = NULL;
+ char straddr[SOCKADDR_STRLEN];
+ sockaddr_tostr(&a, straddr, sizeof(straddr));
+ int rport = sockaddr_portnum(&a);
+ knot_tsig_key_t *k = NULL;
acl_key_t *m = NULL;
knot_rcode_t ts_rc = 0;
uint16_t ts_trc = 0;
@@ -620,63 +637,71 @@ int remote_process(server_t *s, int r, uint8_t* buf, size_t buflen)
const knot_rrset_t *tsig_rr = knot_packet_tsig(pkt);
if (acl_match(conf()->ctl.acl, &a, &m) == ACL_DENY) {
knot_packet_free(&pkt);
+ log_server_warning("Denied remote control for '%s@%d' "
+ "(doesn't match ACL).\n",
+ straddr, rport);
+ remote_senderr(c, buf, wire_len);
socket_close(c);
- rcu_read_unlock();
return KNOT_EACCES;
}
if (m && m->val) {
k = ((conf_iface_t *)m->val)->key;
}
- rcu_read_unlock();
-
+
/* Check TSIG. */
if (k) {
if (!tsig_rr) {
+ log_server_warning("Denied remote control for '%s@%d' "
+ "(key required).\n",
+ straddr, rport);
knot_packet_free(&pkt);
+ remote_senderr(c, buf, wire_len);
socket_close(c);
return KNOT_EACCES;
}
ret = zones_verify_tsig_query(pkt, k, &ts_rc,
&ts_trc, &ts_tmsigned);
if (ret != KNOT_EOK) {
- dbg_server("remote: failed to verify TSIG, "
- "RC: %u TSIG_RC: %u\n",
- ts_rc, ts_trc);
+ log_server_warning("Denied remote control for '%s@%d' "
+ "(key verification failed).\n",
+ straddr, rport);
knot_packet_free(&pkt);
+ remote_senderr(c, buf, wire_len);
socket_close(c);
return KNOT_EACCES;
}
}
-
- /* Answer packet. */
- remote_answer(c, s, pkt, buf, buflen);
}
-
+
+ /* Answer packet. */
+ if (ret == KNOT_EOK)
+ ret = remote_answer(c, s, pkt, buf, buflen);
+
knot_packet_free(&pkt);
socket_close(c);
return ret;
}
-knot_packet_t* remote_query(const char *query, const knot_key_t *key)
+knot_packet_t* remote_query(const char *query, const knot_tsig_key_t *key)
{
if (!query) {
return NULL;
}
-
+
knot_packet_t *qr = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
if (!qr) {
return NULL;
}
-
+
knot_packet_set_max_size(qr, 512);
knot_query_init(qr);
knot_packet_set_random_id(qr);
-
+
/* Reserve space for TSIG. */
if (key) {
knot_packet_set_tsig_size(qr, tsig_wire_maxsize(key));
}
-
+
/* Question section. */
knot_question_t q;
char *qname = strcdup(query, KNOT_CTL_REALM_EXT);
@@ -692,13 +717,13 @@ knot_packet_t* remote_query(const char *query, const knot_key_t *key)
/* Cannot return != KNOT_EOK, but still. */
if (knot_query_set_question(qr, &q) != KNOT_EOK) {
knot_packet_free(&qr);
- free(qname);
- return NULL;
+ free(qname);
+ return NULL;
}
knot_dname_release(q.qname);
free(qname);
-
+
return qr;
}
@@ -707,42 +732,38 @@ int remote_query_append(knot_packet_t *qry, knot_rrset_t *data)
if (!qry || !data) {
return KNOT_EINVAL;
}
-
+
uint8_t *sp = qry->wireformat + qry->size;
- uint8_t *np = qry->wireformat + qry->max_size;
- uint8_t *p = sp;
- const knot_rdata_t *rd = knot_rrset_rdata(data);
- while (rd != NULL) {
- int ret = knot_query_rr_to_wire(data, rd, &p, np);
- if (ret == KNOT_EOK) {
- qry->header.nscount += 1;
- }
- rd = knot_rrset_rdata_next(data, rd);
+ uint16_t rrs = 0;
+ size_t bsize = 0;
+ int ret = knot_rrset_to_wire(data, sp, &bsize, qry->max_size, &rrs, 0);
+ if (ret == KNOT_EOK) {
+ qry->header.nscount += rrs;
}
/* Finalize packet size. */
- qry->size += (p - sp);
+ qry->size += bsize;
return KNOT_EOK;
}
int remote_query_sign(uint8_t *wire, size_t *size, size_t maxlen,
- const knot_key_t *key)
+ const knot_tsig_key_t *key)
{
if (!wire || !size || !key) {
return KNOT_EINVAL;
}
-
- size_t dlen = tsig_alg_digest_length(key->algorithm);
+
+ size_t dlen = knot_tsig_digest_length(key->algorithm);
uint8_t *digest = malloc(dlen);
if (!digest) {
return KNOT_ENOMEM;
}
-
+
int ret = knot_tsig_sign(wire, size, maxlen, NULL, 0, digest, &dlen,
key, 0, 0);
free(digest);
-
+
return ret;
}
@@ -751,38 +772,30 @@ knot_rrset_t* remote_build_rr(const char *k, uint16_t t)
if (!k) {
return NULL;
}
-
+
/* Assert K is FQDN. */
- knot_dname_t *key = remote_dname_fqdn(k);
+ knot_dname_t *key = knot_dname_new_from_nonfqdn_str(k, strlen(k), 0);
if (!key) {
return NULL;
}
-
+
/* Create RRSet. */
knot_rrset_t *rr = knot_rrset_new(key, t, KNOT_CLASS_CH, 0);
knot_dname_release(key);
return rr;
}
-knot_rdata_t* remote_create_txt(const char *v, size_t v_len)
+int remote_create_txt(knot_rrset_t *rr, const char *v, size_t v_len)
{
- if (!v) {
- return NULL;
+ if (!rr || !v) {
+ return KNOT_EINVAL;
}
-
+
/* Number of chunks. */
const size_t K = 255;
unsigned chunks = v_len / K + 1;
+ uint8_t *raw = knot_rrset_create_rdata(rr, v_len + chunks);
- /* Create raw_data item. */
- knot_rdata_item_t rditem;
- rditem.raw_data = malloc(sizeof(uint16_t) + chunks + v_len);
- if (!rditem.raw_data) {
- return NULL;
- }
- rditem.raw_data[0] = v_len + chunks;
- uint8_t *raw = (uint8_t*)(rditem.raw_data + 1);
-
/* Write TXT item. */
unsigned p = 0;
if (v_len > K) {
@@ -799,50 +812,43 @@ knot_rdata_t* remote_create_txt(const char *v, size_t v_len)
raw += K;
}
- knot_rdata_t *rd = remote_build_rdata(&rditem, 1);
- if (!rd) {
- free(rditem.raw_data);
- }
-
- return rd;
+ return KNOT_EOK;
}
-knot_rdata_t* remote_create_cname(const char *d)
+int remote_create_ns(knot_rrset_t *rr, const char *d)
{
- if (!d) {
- return NULL;
+ if (!rr || !d) {
+ return KNOT_EINVAL;
+ }
+
+ /* Create dname. */
+ knot_dname_t *dn = knot_dname_new_from_nonfqdn_str(d, strlen(d), NULL);
+ if (!dn) {
+ return KNOT_ERROR;
}
- /* Create dname item. */
- knot_rdata_item_t i;
- knot_dname_t *dn = remote_dname_fqdn(d);
- i.dname = dn;
-
/* Build RDATA. */
- knot_rdata_t *rd = remote_build_rdata(&i, 1);
- if (!rd) {
- knot_dname_release(dn);
+ uint8_t *rdata = knot_rrset_create_rdata(rr, sizeof(knot_dname_t *));
+ if (!rdata) {
+ knot_dname_free(&dn);
+ return KNOT_ERROR;
}
-
- return rd;
+ memcpy(rdata, &dn, sizeof(knot_dname_t *));
+
+ return KNOT_EOK;
}
-int remote_print_txt(const knot_rdata_t *rd)
+int remote_print_txt(const knot_rrset_t *rr, uint16_t i)
{
- if (!rd || knot_rdata_count(rd) < 1) {
- return KNOT_EINVAL;
- }
-
- const knot_rdata_item_t *ri = knot_rdata_item(rd, 0);
- if (!ri) {
- return KNOT_EINVAL;
+ if (!rr || knot_rrset_rdata_rr_count(rr) < 1) {
+ return -1;
}
-
+
/* Packet parser should have already checked the packet validity. */
char buf[256];
uint16_t parsed = 0;
- uint16_t rlen = ri->raw_data[0];
- uint8_t *p = (uint8_t*)(ri->raw_data + 1);
+ uint16_t rlen = rrset_rdata_item_size(rr, i);
+ uint8_t *p = knot_rrset_get_rdata(rr, i);
while (parsed < rlen) {
memcpy(buf, (const char*)(p+1), *p);
buf[*p] = '\0';
@@ -852,19 +858,3 @@ int remote_print_txt(const knot_rdata_t *rd)
}
return KNOT_EOK;
}
-
-knot_dname_t* remote_dname_fqdn(const char *k)
-{
- /*! \todo #2035 knot_dname_new_from_str() should ensure final '.' */
- knot_dname_t *key = NULL;
- size_t key_len = strlen(k);
- if (k[key_len - 1] != '.') {
- char *fqdn = strcdup(k, ".");
- key = knot_dname_new_from_str(fqdn, key_len + 1, NULL);
- free(fqdn);
- } else {
- key = knot_dname_new_from_str(k, key_len, NULL);
- }
- return key;
-}
-
diff --git a/src/knot/ctl/remote.h b/src/knot/ctl/remote.h
index 55c6d5a..bfc9f1c 100644
--- a/src/knot/ctl/remote.h
+++ b/src/knot/ctl/remote.h
@@ -27,15 +27,14 @@
#ifndef _KNOTD_REMOTE_H_
#define _KNOTD_REMOTE_H_
-#include <config.h>
#include "knot/conf/conf.h"
#include "libknot/packet/packet.h"
#include "libknot/rrset.h"
-#include "libknot/rdata.h"
+#include "libknot/sign/key.h"
#include "knot/server/server.h"
/*! \brief Default remote control tool port. */
-#define REMOTE_DPORT 5553
+#define REMOTE_DPORT 5533
/*!
* \brief Bind RC interface according to configuration.
@@ -111,6 +110,7 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
* \note This should be used as a high-level API for workers.
*
* \param s Server instance.
+ * \param ctl_if Control interface.
* \param r RC interface socket.
* \param buf Buffer for commands/responses.
* \param buflen Maximum buffer size.
@@ -118,7 +118,8 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
* \retval KNOT_EOK on success.
* \retval knot_error else.
*/
-int remote_process(server_t *s, int r, uint8_t* buf, size_t buflen);
+int remote_process(server_t *s, conf_iface_t *ctl_if, int r,
+ uint8_t* buf, size_t buflen);
/* Functions for creating RC packets. */
@@ -133,7 +134,7 @@ int remote_process(server_t *s, int r, uint8_t* buf, size_t buflen);
* \retval KNOT_EOK on success.
* \retval knot_error else.
*/
-knot_packet_t* remote_query(const char *query, const knot_key_t *key);
+knot_packet_t* remote_query(const char *query, const knot_tsig_key_t *key);
/*!
* \brief Append extra data to RC command packet.
@@ -158,7 +159,7 @@ int remote_query_append(knot_packet_t *qry, knot_rrset_t *data);
* \retval knot_error else.
*/
int remote_query_sign(uint8_t *wire, size_t *size, size_t maxlen,
- const knot_key_t *key);
+ const knot_tsig_key_t *key);
/*! \todo #1291 RR building should be a part of DNS library. */
@@ -178,28 +179,22 @@ knot_rrset_t* remote_build_rr(const char *k, uint16_t t);
* \param v_len Text length.
* \return Created rdata or NULL.
*/
-knot_rdata_t* remote_create_txt(const char *v, size_t v_len);
+int remote_create_txt(knot_rrset_t *rr, const char *v, size_t v_len);
+
/*!
* \brief Create a CNAME rdata.
* \param d Domain name as a string.
* \return Created rdata or NULL.
*/
-knot_rdata_t* remote_create_cname(const char *d);
+int remote_create_ns(knot_rrset_t *rr, const char *d);
/*!
* \brief Print TXT rdata to stdout.
* \param rd TXT rdata.
* \return KNOT_EOK
*/
-int remote_print_txt(const knot_rdata_t *rd);
-
-/*!
- * \brief Create dname from str and make sure the name is FQDN.
- * \param k Domain name as string.
- * \return Created FQDN or NULL.
- */
-knot_dname_t* remote_dname_fqdn(const char *k);
+int remote_print_txt(const knot_rrset_t *rrset, uint16_t i);
#endif // _KNOTD_REMOTE_H_
diff --git a/src/knot/knot.h b/src/knot/knot.h
new file mode 100644
index 0000000..fb0f9fd
--- /dev/null
+++ b/src/knot/knot.h
@@ -0,0 +1,76 @@
+/* Copyright (C) 2011 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 knot.h
+ *
+ * \author Lubos Slovak <lubos.slovak@nic.cz>
+ *
+ * \brief Common macros, includes and utilities.
+ *
+ * \addtogroup server
+ * @{
+ */
+
+#ifndef _KNOTD_KNOT_H_
+#define _KNOTD_KNOT_H_
+
+#include <signal.h>
+#include <stdint.h>
+
+/*
+ * Common types and constants.
+ */
+
+#define PROJECT_EXENAME "knotd"
+#define PROJECT_EXEC SBINDIR "/" PROJECT_EXENAME /*!< \brief Project executable. */
+#define PID_FILE "knot.pid" /*!< \brief Server PID file name. */
+
+/*
+ * Server.
+ */
+
+#define CPU_ESTIMATE_MAGIC 0 /*!< \brief Extra threads to the number of cores.*/
+#define DEFAULT_THR_COUNT 2 /*!< \brief Default thread count. */
+#define TCP_BACKLOG_SIZE 10 /*!< \brief TCP listen backlog size. */
+#define XFR_THREADS_COUNT 3 /*!< \brief Number of threads for XFR handler. */
+#define RECVMMSG_BATCHLEN 64 /*!< \brief Define for recvmmsg() batch size. */
+
+///*! \brief If defined, the statistics module will be enabled. */
+//#define STAT_COMPILE
+
+/*
+ * Common includes.
+ */
+
+#include "common/print.h"
+#include "common/log.h"
+#include "common/errcode.h"
+#include "knot/other/debug.h"
+
+/* Workarounds for clock_gettime() not available on some platforms. */
+#ifdef HAVE_CLOCK_GETTIME
+#define time_now(x) clock_gettime(CLOCK_MONOTONIC, (x))
+typedef struct timespec timev_t;
+#elif HAVE_GETTIMEOFDAY
+#define time_now(x) gettimeofday((x), NULL)
+typedef struct timeval timev_t;
+#else
+#error Neither clock_gettime() nor gettimeofday() found. At least one is required.
+#endif
+
+#endif /* _KNOTD_KNOT_H_ */
+
+/*! @} */
diff --git a/src/knot/main.c b/src/knot/main.c
index c433007..c5e693c 100644
--- a/src/knot/main.c
+++ b/src/knot/main.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
+#include <sys/stat.h>
#include <limits.h>
#ifdef HAVE_CAP_NG_H
@@ -27,7 +28,7 @@
#include "common.h"
#include "common/evqueue.h"
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/server/server.h"
#include "knot/ctl/process.h"
#include "knot/ctl/remote.h"
@@ -40,10 +41,14 @@
/* Signal flags. */
static volatile short sig_req_stop = 0;
+static volatile short sig_req_rst = 0;
static volatile short sig_req_reload = 0;
static volatile short sig_req_refresh = 0;
static volatile short sig_stopping = 0;
+// Cleanup handler
+static int do_cleanup(server_t *server, char *configf, char *pidf);
+
// SIGINT signal handler
void interrupt_handle(int s)
{
@@ -52,13 +57,13 @@ void interrupt_handle(int s)
sig_req_reload = 1;
return;
}
-
+
// Refresh
if (s == SIGUSR2) {
sig_req_refresh = 1;
return;
}
-
+
// Stop server
if (s == SIGINT || s == SIGTERM) {
if (sig_stopping == 0) {
@@ -70,7 +75,7 @@ void interrupt_handle(int s)
}
}
-void help(int argc, char **argv)
+void help(void)
{
printf("Usage: %sd [parameters]\n",
PACKAGE_NAME);
@@ -89,7 +94,7 @@ int main(int argc, char **argv)
int verbose = 0;
int daemonize = 0;
char* config_fn = NULL;
-
+
/* Long options. */
struct option opts[] = {
{"config", required_argument, 0, 'c'},
@@ -99,7 +104,7 @@ int main(int argc, char **argv)
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
-
+
while ((c = getopt_long(argc, argv, "c:dvVh", opts, &li)) != -1) {
switch (c)
{
@@ -117,9 +122,12 @@ int main(int argc, char **argv)
return 0;
case 'h':
case '?':
+ free(config_fn);
+ help();
+ return 0;
default:
free(config_fn);
- help(argc, argv);
+ help();
return 1;
}
}
@@ -179,7 +187,7 @@ int main(int argc, char **argv)
config_fn = rpath;
}
}
-
+
// Create server
server_t *server = server_create();
@@ -188,33 +196,33 @@ int main(int argc, char **argv)
conf_add_hook(conf(), CONF_LOG, log_conf_hook, 0);
conf_add_hook(conf(), CONF_ALL, server_conf_hook, server);
rcu_read_unlock();
-
+
/* POSIX 1003.1e capabilities. */
#ifdef HAVE_CAP_NG_H
-
+
/* Drop all capabilities. */
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
capng_clear(CAPNG_SELECT_BOTH);
-
-
+
+
/* Retain ability to set capabilities and FS access. */
capng_type_t tp = CAPNG_EFFECTIVE|CAPNG_PERMITTED;
capng_update(CAPNG_ADD, tp, CAP_SETPCAP);
capng_update(CAPNG_ADD, tp, CAP_DAC_OVERRIDE);
capng_update(CAPNG_ADD, tp, CAP_CHOWN); /* Storage ownership. */
-
+
/* Allow binding to privileged ports.
* (Not inheritable)
*/
capng_update(CAPNG_ADD, tp, CAP_NET_BIND_SERVICE);
-
+
/* Allow setuid/setgid. */
capng_update(CAPNG_ADD, tp, CAP_SETUID);
capng_update(CAPNG_ADD, tp, CAP_SETGID);
-
+
/* Allow priorities changing. */
capng_update(CAPNG_ADD, tp, CAP_SYS_NICE);
-
+
/* Apply */
if (capng_apply(CAPNG_SELECT_BOTH) < 0) {
log_server_error("Couldn't set process capabilities - "
@@ -232,15 +240,12 @@ int main(int argc, char **argv)
if (conf_ret != KNOT_EOK) {
if (conf_ret == KNOT_ENOENT) {
log_server_error("Couldn't open configuration file "
- "'%s'.\n", config_fn);
+ "'%s'.\n", config_fn);
} else {
log_server_error("Failed to load configuration '%s'.\n",
- config_fn);
+ config_fn);
}
- server_wait(server);
- server_destroy(&server);
- free(config_fn);
- return 1;
+ return do_cleanup(server, config_fn, NULL);
} else {
log_server_info("Configured %d interfaces and %d zones.\n",
conf()->ifaces_count, conf()->zones_count);
@@ -249,45 +254,35 @@ int main(int argc, char **argv)
/* Alter privileges. */
log_update_privileges(conf()->uid, conf()->gid);
- proc_update_privileges(conf()->uid, conf()->gid);
-
+ if (proc_update_privileges(conf()->uid, conf()->gid) != KNOT_EOK)
+ return do_cleanup(server, config_fn, NULL);
+
+ /* Check and create PID file. */
+ long pid = (long)getpid();
+ char *pidf = NULL;
+ char *cwd = NULL;
+ if (daemonize) {
+ if ((pidf = pid_check_and_create()) == NULL)
+ return do_cleanup(server, config_fn, pidf);
+ log_server_info("Server started as a daemon, PID = %ld\n", pid);
+ log_server_info("PID stored in '%s'\n", pidf);
+ if ((cwd = malloc(PATH_MAX)) != NULL)
+ cwd = getcwd(cwd, PATH_MAX);
+ if (chdir("/") != 0)
+ log_server_warning("Server can't change working directory.\n");
+ } else {
+ log_server_info("Server started in foreground, PID = %ld\n", pid);
+ log_server_info("Server running without PID file.\n");
+ }
+
/* Load zones and add hook. */
zones_ns_conf_hook(conf(), server->nameserver);
conf_add_hook(conf(), CONF_ALL, zones_ns_conf_hook, server->nameserver);
// Run server
int res = 0;
- int has_pid = 0;
- char* pidfile = pid_filename();
log_server_info("Starting server...\n");
if ((server_start(server)) == KNOT_EOK) {
-
- // Save PID
- has_pid = 1;
- int rc = pid_write(pidfile);
- if (rc < 0) {
- has_pid = 0;
- log_server_warning("Failed to create "
- "PID file '%s' (%s).\n",
- pidfile, strerror(errno));
- }
-
- // Change directory if daemonized
- if (daemonize) {
- log_server_info("Server started as a daemon, "
- "PID = %ld\n", (long)getpid());
- if (chdir("/") != 0) {
- res = 1;
- }
- } else {
- log_server_info("Server started in foreground, "
- "PID = %ld\n", (long)getpid());
- }
- if (has_pid) {
- log_server_info("PID stored in %s\n", pidfile);
- } else {
- log_server_warning("Server running without PID file.\n");
- }
size_t zcount = server->nameserver->zone_db->zone_count;
if (!zcount) {
log_server_warning("Server started, but no zones served.\n");
@@ -309,24 +304,43 @@ int main(int argc, char **argv)
/* Bind to control interface. */
uint8_t buf[65535]; /*! \todo #2035 should be on heap */
size_t buflen = sizeof(buf);
- conf_iface_t *ctl_if = conf()->ctl.iface;
int remote = -1;
- if (ctl_if != NULL) {
+ if (conf()->ctl.iface != NULL) {
+ conf_iface_t *ctl_if = conf()->ctl.iface;
+ memset(buf, 0, buflen);
+ if (ctl_if->port)
+ snprintf((char*)buf, buflen, "@%d", ctl_if->port);
+ /* Log control interface description. */
log_server_info("Binding remote control interface "
- "to %s port %d.\n",
- ctl_if->address, ctl_if->port);
+ "to %s%s\n",
+ ctl_if->address, (char*)buf);
remote = remote_bind(ctl_if);
- } else {
- remote = evqueue()->fds[EVQUEUE_READFD];
}
-
-
+ if (remote < 0)
+ remote = evqueue()->fds[EVQUEUE_READFD];
+
+
/* Run event loop. */
for(;;) {
pthread_sigmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
int ret = remote_poll(remote);
pthread_sigmask(SIG_BLOCK, &sa.sa_mask, NULL);
+ /* Events. */
+ if (ret > 0) {
+ ret = remote_process(server, conf()->ctl.iface,
+ remote, buf, buflen);
+ switch(ret) {
+ case KNOT_CTL_RESTART:
+ sig_req_rst = 1; /* Fall through */
+ case KNOT_CTL_STOP:
+ sig_req_stop = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
/* Interrupts. */
if (sig_req_stop) {
sig_req_stop = 0;
@@ -346,17 +360,11 @@ int main(int argc, char **argv)
"slave zones - %s",
knot_strerror(cf_ret));
}
-
- }
-
- /* Events. */
- if (ret > 0) {
- remote_process(server, remote, buf, buflen);
}
}
pthread_sigmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
-
+
/* Close remote control interface */
if (remote > -1) {
close(remote);
@@ -376,31 +384,48 @@ int main(int argc, char **argv)
res = 1;
}
- // Stop server and close log
- server_destroy(&server);
-
- // Remove PID file
- if (has_pid && pid_remove(pidfile) < 0) {
- log_server_warning("Failed to remove PID file.\n");
- }
-
log_server_info("Shut down.\n");
log_close();
- free(pidfile);
-
- // Destroy event loop
- evqueue_t *q = evqueue();
- evqueue_free(&q);
-
- rcu_unregister_thread();
- // Free default config filename if exists
- free(config_fn);
+ /* Cleanup. */
+ if (pidf && pid_remove(pidf) < 0)
+ log_server_warning("Failed to remove PID file.\n");
+ do_cleanup(server, config_fn, pidf);
if (!daemonize) {
fflush(stdout);
fflush(stderr);
}
+ /* Return to original working directory. */
+ if (cwd) {
+ if (chdir(cwd) != 0)
+ log_server_warning("Server can't change working directory.\n");
+ free(cwd);
+ }
+
+ /* Restart hook. */
+ if (sig_req_rst)
+ return execvp(PROJECT_EXEC, argv);
+
return res;
}
+
+static int do_cleanup(server_t *server, char *configf, char *pidf)
+{
+ /* Free alloc'd variables. */
+ if (server) {
+ server_wait(server);
+ server_destroy(&server);
+ }
+ free(configf);
+ free(pidf);
+
+ /* Unhook from RCU */
+ rcu_unregister_thread();
+
+ /* Free event loop. */
+ evqueue_t *q = evqueue();
+ evqueue_free(&q);
+ return 1;
+}
diff --git a/src/knot/other/debug.h b/src/knot/other/debug.h
index c88e166..b5fd9bc 100644
--- a/src/knot/other/debug.h
+++ b/src/knot/other/debug.h
@@ -27,8 +27,6 @@
#ifndef _KNOTD_DEBUG_H_
#define _KNOTD_DEBUG_H_
-#include "config.h" /* autoconf generated */
-
#ifdef KNOTD_SERVER_DEBUG
#define KNOTD_THREADS_DEBUG
#define KNOTD_JOURNAL_DEBUG
@@ -478,7 +476,7 @@
#define dbg_zload_exec_detail(cmds)
#endif
-#ifdef KNOTD_COMPILER_DEBUG
+#ifdef KNOTD_COMPILE_DEBUG
/* Brief messages. */
#ifdef DEBUG_ENABLE_BRIEF
diff --git a/src/knot/server/dthreads.c b/src/knot/server/dthreads.c
index 45fa866..759faf2 100644
--- a/src/knot/server/dthreads.c
+++ b/src/knot/server/dthreads.c
@@ -30,7 +30,7 @@
#include <pthread_np.h>
#endif /* HAVE_PTHREAD_NP_H */
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/server/dthreads.h"
#include "common/log.h"
@@ -138,7 +138,7 @@ static void *thread_ep(void *data)
rcu_register_thread();
dbg_dt("dthreads: [%p] entered ep\n", thread);
-
+
/* Drop capabilities except FS access. */
#ifdef HAVE_CAP_NG_H
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
@@ -444,178 +444,6 @@ void dt_delete(dt_unit_t **unit)
*unit = 0;
}
-int dt_resize(dt_unit_t *unit, int size)
-{
- // Check input
- if (unit == 0 || size <= 0) {
- return KNOT_EINVAL;
- }
-
- // Evaluate delta
- int delta = unit->size - size;
-
- // Same size
- if (delta == 0) {
- return 0;
- }
-
- // Unit expansion
- if (delta < 0) {
-
- // Lock unit
- pthread_mutex_lock(&unit->_notify_mx);
- dt_unit_lock(unit);
-
- // Realloc threads
- dbg_dt("dthreads: growing from %d to %d threads\n",
- unit->size, size);
-
- dthread_t **threads = realloc(unit->threads,
- size * sizeof(dthread_t *));
- if (threads == NULL) {
- dt_unit_unlock(unit);
- pthread_mutex_unlock(&unit->_notify_mx);
- return -1;
- }
-
- // Reassign
- unit->threads = threads;
-
- // Create new threads
- for (int i = unit->size; i < size; ++i) {
- threads[i] = dt_create_thread(unit);
- }
-
- // Update unit
- unit->size = size;
- dt_unit_unlock(unit);
- pthread_mutex_unlock(&unit->_notify_mx);
- return 0;
- }
-
-
- // Unit shrinking
- int remaining = size;
- dbg_dt("dthreads: shrinking from %d to %d threads\n",
- unit->size, size);
-
- // New threads vector
- dthread_t **threads = malloc(size * sizeof(dthread_t *));
- if (threads == 0) {
- return KNOT_ENOMEM;
- }
-
- // Lock unit
- pthread_mutex_lock(&unit->_notify_mx);
- dt_unit_lock(unit);
-
- // Iterate while there is space in new unit
- memset(threads, 0, size * sizeof(dthread_t *));
- int threshold = ThreadActive;
- for (;;) {
-
- // Find threads matching given criterias
- int inspected = 0;
- for (int i = 0; i < unit->size; ++i) {
-
- // Get thread
- dthread_t *thread = unit->threads[i];
- if (thread == 0) {
- continue;
- }
-
- // Count thread as inspected
- ++inspected;
-
- lock_thread_rw(thread);
-
- // Populate with matching threads
- if ((remaining > 0) &&
- (!threshold || (thread->state & threshold))) {
-
- // Append to new vector
- threads[size - remaining] = thread;
- --remaining;
-
- // Invalidate in old vector
- unit->threads[i] = 0;
- dbg_dt_verb("dthreads: [%p] dt_resize: elected\n",
- thread);
-
- } else if (remaining <= 0) {
-
- // Not enough space, delete thread
- if (thread->state & ThreadDead) {
- unlock_thread_rw(thread);
- --inspected;
- continue;
- }
-
- // Signalize thread to stop
- thread->state = ThreadDead | ThreadCancelled;
- dt_signalize(thread, SIGALRM);
- dbg_dt_verb("dthreads: [%p] dt_resize: "
- "is discarded\n", thread);
- }
-
- // Unlock thread and continue
- unlock_thread_rw(thread);
- }
-
- // Finished inspecting running threads
- if (inspected == 0) {
- break;
- }
-
- // Lower threshold
- switch (threshold) {
- case ThreadActive:
- threshold = ThreadIdle;
- break;
- case ThreadIdle:
- threshold = ThreadDead;
- break;
- default:
- threshold = ThreadJoined;
- break;
- }
- }
-
- // Notify idle threads to wake up
- pthread_cond_broadcast(&unit->_notify);
- pthread_mutex_unlock(&unit->_notify_mx);
-
- // Join discarded threads
- for (int i = 0; i < unit->size; ++i) {
-
- // Get thread
- dthread_t *thread = unit->threads[i];
- if (thread == 0) {
- continue;
- }
-
- pthread_join(thread->_thr, 0);
- /* Thread is already joined and flagged, but anyway... */
- lock_thread_rw(thread);
- thread->state = ThreadJoined;
- unlock_thread_rw(thread);
-
- // Delete thread
- dt_delete_thread(&thread);
- unit->threads[i] = 0;
- }
-
- // Reassign unit threads vector
- unit->size = size;
- free(unit->threads);
- unit->threads = threads;
-
- // Unlock unit
- dt_unit_unlock(unit);
-
- return 0;
-}
-
int dt_start(dt_unit_t *unit)
{
// Check input
@@ -645,7 +473,7 @@ int dt_start(dt_unit_t *unit)
dt_unit_unlock(unit);
pthread_cond_broadcast(&unit->_notify);
pthread_mutex_unlock(&unit->_notify_mx);
- return 0;
+ return KNOT_EOK;
}
int dt_start_id(dthread_t *thread)
@@ -825,55 +653,16 @@ int dt_stop(dt_unit_t *unit)
return KNOT_EOK;
}
-//int dt_setprio(dthread_t *thread, int prio)
-//{
-// // Check input
-// if (thread == 0) {
-// return KNOT_EINVAL;
-// }
-
-// // Clamp priority
-// int policy = SCHED_FIFO;
-// prio = MIN(MAX(sched_get_priority_min(policy), prio),
-// sched_get_priority_max(policy));
-
-// // Update scheduler policy
-// int ret = pthread_attr_setschedpolicy(&thread->_attr, policy);
-
-// // Update priority
-// if (ret == 0) {
-// struct sched_param sp;
-// sp.sched_priority = prio;
-// ret = pthread_attr_setschedparam(&thread->_attr, &sp);
-// }
-
-// /* Map error codes. */
-// if (ret != 0) {
-// dbg_dt("dthreads: [%p] %s(%d): failed",
-// thread, __func__, prio);
-
-// /* Map "not supported". */
-// if (errno == ENOTSUP) {
-// return KNOT_ENOTSUP;
-// }
-
-// return KNOT_EINVAL;
-// }
-
-// return KNOT_EOK;
-//}
-
-
int dt_setaffinity(dthread_t *thread, unsigned* cpu_id, size_t cpu_count)
{
if (thread == NULL) {
return KNOT_EINVAL;
}
-
+
#ifdef HAVE_PTHREAD_SETAFFINITY_NP
int ret = -1;
-
+
/* Linux, FreeBSD interface. */
#if defined(HAVE_CPUSET_LINUX) || defined(HAVE_CPUSET_BSD)
cpu_set_t set;
@@ -890,7 +679,7 @@ int dt_setaffinity(dthread_t *thread, unsigned* cpu_id, size_t cpu_count)
}
cpuset_zero(set);
for (unsigned i = 0; i < cpu_count; ++i) {
- cpuset_set(cpu_id[i], &set);
+ cpuset_set(cpu_id[i], set);
}
ret = pthread_setaffinity_np(thread->_thr, cpuset_size(set), set);
cpuset_destroy(set);
@@ -903,7 +692,7 @@ int dt_setaffinity(dthread_t *thread, unsigned* cpu_id, size_t cpu_count)
#else /* HAVE_PTHREAD_SETAFFINITY_NP */
return KNOT_ENOTSUP;
#endif
-
+
return KNOT_EOK;
}
@@ -1040,16 +829,11 @@ int dt_optimal_size()
if (ret > 0) {
return ret + CPU_ESTIMATE_MAGIC;
}
-
+
dbg_dt("dthreads: failed to fetch the number of online CPUs.");
return DEFAULT_THR_COUNT;
}
-/*!
- * \note Use memory barriers or asynchronous read-only access, locking
- * poses a thread performance decrease by 1.31%.
- */
-
int dt_is_cancelled(dthread_t *thread)
{
// Check input
@@ -1057,10 +841,7 @@ int dt_is_cancelled(dthread_t *thread)
return 0;
}
- lock_thread_rw(thread);
- int ret = thread->state & ThreadCancelled;
- unlock_thread_rw(thread);
- return ret;
+ return thread->state & ThreadCancelled; /* No need to be locked. */
}
unsigned dt_get_id(dthread_t *thread)
@@ -1070,12 +851,12 @@ unsigned dt_get_id(dthread_t *thread)
}
dt_unit_t *unit = thread->unit;
- for(unsigned tid = 0; tid < unit->size; ++tid) {
+ for(int tid = 0; tid < unit->size; ++tid) {
if (thread == unit->threads[tid]) {
return tid;
}
}
-
+
return 0;
}
diff --git a/src/knot/server/dthreads.h b/src/knot/server/dthreads.h
index 374e399..6c511c5 100644
--- a/src/knot/server/dthreads.h
+++ b/src/knot/server/dthreads.h
@@ -45,9 +45,6 @@
struct dthread_t;
struct dt_unit_t;
-/* Constants. */
-#define DTHREADS_STACKSIZE (1024*1024) /* 1M lightweight stack size. */
-
/*!
* \brief Thread state enumeration.
*/
@@ -144,28 +141,6 @@ dt_unit_t *dt_create_coherent(int count, runnable_t runnable, void *data);
void dt_delete(dt_unit_t **unit);
/*!
- * \brief Resize unit to given number.
- *
- * \note Newly created dthreads will have no runnable or data, their state
- * will be ThreadJoined (that means no thread will be physically created
- * until the next dt_start()).
- *
- * \warning Be careful when shrinking unit, joined and idle threads are
- * reclaimed first, but it may kill your active threads
- * as a last resort.
- * Threads will stop at their nearest cancellation point,
- * so this is potentially an expensive and blocking operation.
- *
- * \param unit Unit to be resized.
- * \param size New unit size.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_EINVAL on invalid parameters.
- * \retval KNOT_ENOMEM out of memory error.
- */
-int dt_resize(dt_unit_t *unit, int size);
-
-/*!
* \brief Start all threads in selected unit.
*
* \param unit Unit to be started.
@@ -236,21 +211,6 @@ int dt_stop_id(dthread_t *thread);
int dt_stop(dt_unit_t *unit);
/*!
- * \brief Modify thread priority.
- *
- * \param thread Target thread instance.
- * \param prio Requested priority (positive integer, default is 0).
- *
- * \warning Thread priority setting is disabled as the compatible scheduler
- * has significant performance deficiencies (SCHED_OTHER).
- * (issue #1809)
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_EINVAL on invalid parameters.
- */
-//int dt_setprio(dthread_t *thread, int prio);
-
-/*!
* \brief Set thread affinity to masked CPU's.
*
* \param thread Target thread instance.
diff --git a/src/knot/server/journal.c b/src/knot/server/journal.c
index 1623bf5..b725083 100644
--- a/src/knot/server/journal.c
+++ b/src/knot/server/journal.c
@@ -20,12 +20,13 @@
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include "common/crc.h"
+#include "common.h"
#include "knot/other/debug.h"
-#include "knot/zone/zone-dump.h"
#include "journal.h"
/*! \brief Infinite file size limit. */
@@ -64,12 +65,12 @@ static int journal_recover(journal_t *j)
if (j == NULL) {
return KNOT_EINVAL;
}
-
+
/* Attempt to recover queue. */
int qstate[2] = { -1, -1 };
unsigned c = 0, p = j->max_nodes - 1;
while (1) {
-
+
/* Fetch previous and current node. */
journal_node_t *np = j->nodes + p;
journal_node_t *nc = j->nodes + c;
@@ -93,7 +94,7 @@ static int journal_recover(journal_t *j)
dbg_journal_verb("journal: recovered qtail=%u\n",
qstate[1]);
}
-
+
/* Both qstates set. */
if (qstate[0] > -1 && qstate[1] > -1) {
break;
@@ -102,33 +103,33 @@ static int journal_recover(journal_t *j)
/* Set prev and next. */
p = c;
c = (c + 1) % j->max_nodes;
-
+
/* All nodes probed. */
if (c == 0) {
dbg_journal("journal: failed to recover node queue\n");
break;
}
}
-
+
/* Evaluate */
if (qstate[0] < 0 || qstate[1] < 0) {
return KNOT_ERANGE;
}
-
+
/* Write back. */
int seek_ret = lseek(j->fd, JOURNAL_HSIZE - 2 * sizeof(uint16_t), SEEK_SET);
if (seek_ret < 0 || !sfwrite(qstate, 2 * sizeof(uint16_t), j->fd)) {
dbg_journal("journal: failed to write back queue state\n");
return KNOT_ERROR;
}
-
+
/* Reset queue state. */
j->qhead = qstate[0];
j->qtail = qstate[1];
dbg_journal("journal: node queue=<%u,%u> recovered\n",
qstate[0], qstate[1]);
-
-
+
+
return KNOT_EOK;
}
@@ -178,7 +179,7 @@ int journal_write_in(journal_t *j, journal_node_t **rn, uint64_t id, size_t len)
j->fsize);
}
}
-
+
/* Evict occupied nodes if necessary. */
while (j->free.len < len ||
j->nodes[jnext].flags > JOURNAL_FREE) {
@@ -188,7 +189,7 @@ int journal_write_in(journal_t *j, journal_node_t **rn, uint64_t id, size_t len)
/* Check if it has been synced to disk. */
if (head->flags & JOURNAL_DIRTY) {
- return KNOT_EAGAIN;
+ return KNOT_EBUSY;
}
/* Write back evicted node. */
@@ -251,7 +252,7 @@ int journal_write_out(journal_t *journal, journal_node_t *n)
journal->free.pos += size;
journal->free.len -= size;
}
-
+
dbg_journal("journal: finishing node=%u id=%llu flags=0x%x, "
"data=<%u, %u> free=<%u, %u>\n",
journal->qtail, (unsigned long long)n->id,
@@ -269,7 +270,7 @@ int journal_write_out(journal_t *journal, journal_node_t *n)
"free segment descriptor\n");
return KNOT_ERROR;
}
-
+
/* Node write successful. */
journal->qtail = jnext;
@@ -293,7 +294,7 @@ int journal_update_crc(int fd)
if (fcntl(fd, F_GETFL) < 0) {
return KNOT_EINVAL;
}
-
+
char buf[4096];
ssize_t rb = 0;
crc_t crc = crc_init();
@@ -310,7 +311,7 @@ int journal_update_crc(int fd)
dbg_journal("journal: couldn't write CRC to fd=%d\n", fd);
return KNOT_ERROR;
}
-
+
return KNOT_EOK;
}
@@ -319,7 +320,7 @@ int journal_create(const char *fn, uint16_t max_nodes)
if (fn == NULL) {
return KNOT_EINVAL;
}
-
+
/* File lock. */
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
@@ -328,14 +329,14 @@ int journal_create(const char *fn, uint16_t max_nodes)
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
-
+
/* Create journal file. */
int fd = open(fn, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
if (fd < 0) {
dbg_journal("journal: failed to create file '%s'\n", fn);
return knot_map_errno(errno);
}
-
+
/* Lock. */
fcntl(fd, F_SETLKW, &fl);
fl.l_type = F_UNLCK;
@@ -375,7 +376,7 @@ int journal_create(const char *fn, uint16_t max_nodes)
remove(fn);
return KNOT_ERROR;
}
-
+
if (!sfwrite(&zval, sizeof(uint16_t), fd)) {
fcntl(fd, F_SETLK, &fl);
close(fd);
@@ -406,19 +407,23 @@ int journal_create(const char *fn, uint16_t max_nodes)
if (!sfwrite(&jn, sizeof(journal_node_t), fd)) {
fcntl(fd, F_SETLK, &fl);
close(fd);
- remove(fn);
+ if (remove(fn) < 0) {
+ dbg_journal("journal: failed to remove journal file after error\n");
+ }
return KNOT_ERROR;
}
}
-
+
/* Recalculate CRC. */
if (journal_update_crc(fd) != KNOT_EOK) {
fcntl(fd, F_SETLK, &fl);
close(fd);
- remove(fn);
+ if(remove(fn) < 0) {
+ dbg_journal("journal: failed to remove journal file after error\n");
+ }
return KNOT_ERROR;
}
-
+
/* Unlock and close. */
fcntl(fd, F_SETLK, &fl);
close(fd);
@@ -434,19 +439,34 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
if (fn == NULL) {
return NULL;
}
-
+
+ /* Check for lazy mode. */
+ if (mode & JOURNAL_LAZY) {
+ dbg_journal("journal: opening journal %s lazily\n", fn);
+ journal_t *j = malloc(sizeof(journal_t));
+ if (j != NULL) {
+ memset(j, 0, sizeof(journal_t));
+ j->fd = -1;
+ j->path = strdup(fn);
+ j->fslimit = fslimit;
+ j->bflags = bflags;
+ j->refs = 1;
+ }
+ return j;
+ }
+
/* Open journal file for r/w (returns error if not exists). */
int fd = open(fn, O_RDWR);
if (fd < 0) {
if (errno == ENOENT) {
- if(journal_create(fn, JOURNAL_NCOUNT) == KNOT_EOK) {
+ if(journal_create(fn, JOURNAL_NCOUNT) == KNOT_EOK) {
return journal_open(fn, fslimit, mode, bflags);
}
}
-
+
return NULL;
}
-
+
/* File lock. */
struct flock fl;
memset(&fl, 0, sizeof(struct flock));
@@ -455,11 +475,11 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
-
+
/* Attempt to lock. */
dbg_journal_verb("journal: locking journal %s\n", fn);
int ret = fcntl(fd, F_SETLK, &fl);
-
+
/* Lock. */
if (ret < 0) {
struct flock efl;
@@ -473,7 +493,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
}
fl.l_type = F_UNLCK;
dbg_journal("journal: locked journal %s (returned %d)\n", fn, ret);
-
+
/* Read magic bytes. */
dbg_journal("journal: reading magic bytes\n");
const char magic_req[MAGIC_LENGTH] = JOURNAL_MAGIC;
@@ -501,7 +521,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
close(fd);
return NULL;
}
-
+
/* Recalculate CRC. */
char buf[4096];
ssize_t rb = 0;
@@ -509,7 +529,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
while((rb = read(fd, buf, sizeof(buf))) > 0) {
crc_calc = crc_update(crc_calc, (const unsigned char *)buf, rb);
}
-
+
/* Compare */
if (crc == crc_calc) {
/* Rewind. */
@@ -528,23 +548,6 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
}
return NULL;
}
-
- /* Check for lazy mode. */
- if (mode & JOURNAL_LAZY) {
- dbg_journal("journal: opening journal %s lazily\n", fn);
- journal_t *j = malloc(sizeof(journal_t));
- if (j != NULL) {
- memset(j, 0, sizeof(journal_t));
- j->fd = -1;
- j->path = strdup(fn);
- j->fslimit = fslimit;
- j->bflags = bflags;
- j->refs = 1;
- }
- fcntl(fd, F_SETLK, &fl);
- close(fd);
- return j;
- }
/* Read maximum number of entries. */
uint16_t max_nodes = 512;
@@ -554,7 +557,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
close(fd);
return NULL;
}
-
+
/* Check max_nodes, but this is riddiculous. */
if (max_nodes == 0) {
dbg_journal_detail("journal: max_nodes is invalid\n");
@@ -596,7 +599,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
free(j);
return NULL;
}
-
+
/* Check head + tail */
if (j->qtail > max_nodes || j->qhead > max_nodes) {
dbg_journal_detail("journal: queue pointers corrupted\n");
@@ -623,7 +626,7 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
free(j);
return NULL;
}
-
+
/* Get journal file size. */
struct stat st;
if (stat(fn, &st) < 0) {
@@ -641,14 +644,14 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
} else {
j->fslimit = (size_t)fslimit;
}
-
+
dbg_journal("journal: opened journal size=%u, queue=<%u, %u>, fd=%d\n",
- max_nodes, j->qhead, j->qtail, j->fd);
-
+ max_nodes, j->qhead, j->qtail, j->fd);
+
/* Check node queue. */
unsigned qtail_free = (jnode_flags(j, j->qtail) <= JOURNAL_FREE);
unsigned qhead_free = j->max_nodes - 1; /* Left of qhead must be free.*/
- if (j->qhead > 0) {
+ if (j->qhead > 0) {
qhead_free = (j->qhead - 1);
}
qhead_free = (jnode_flags(j, qhead_free) <= JOURNAL_FREE);
@@ -681,7 +684,7 @@ int journal_fetch(journal_t *journal, uint64_t id,
if (journal == NULL || dst == NULL) {
return KNOT_EINVAL;
}
-
+
/* Check compare function. */
if (!cf) {
cf = journal_cmp_eq;
@@ -707,7 +710,7 @@ int journal_read(journal_t *journal, uint64_t id, journal_cmp_t cf, char *dst)
if (journal == NULL || dst == NULL) {
return KNOT_EINVAL;
}
-
+
journal_node_t *n = 0;
if(journal_fetch(journal, id, cf, &n) != 0) {
dbg_journal("journal: failed to fetch node with id=%llu\n",
@@ -720,7 +723,7 @@ int journal_read(journal_t *journal, uint64_t id, journal_cmp_t cf, char *dst)
int journal_read_node(journal_t *journal, journal_node_t *n, char *dst)
{
- dbg_journal("journal: reading node with id=%llu, data=<%u, %u>, flags=0x%hx\n",
+ dbg_journal("journal: reading node with id=%"PRIu64", data=<%u, %u>, flags=0x%hx\n",
n->id, n->pos, n->pos + n->len, n->flags);
/* Check valid flag. */
@@ -729,7 +732,7 @@ int journal_read_node(journal_t *journal, journal_node_t *n, char *dst)
"(flags=0x%hx)\n", (unsigned long long)n->id, n->flags);
return KNOT_EINVAL;
}
-
+
/* Seek journal node. */
int seek_ret = lseek(journal->fd, n->pos, SEEK_SET);
@@ -737,7 +740,7 @@ int journal_read_node(journal_t *journal, journal_node_t *n, char *dst)
if (seek_ret < 0 || !sfread(dst, n->len, journal->fd)) {
return KNOT_ERROR;
}
-
+
return KNOT_EOK;
}
@@ -746,7 +749,7 @@ int journal_write(journal_t *journal, uint64_t id, const char *src, size_t size)
if (journal == NULL || src == NULL) {
return KNOT_EINVAL;
}
-
+
/* Prepare journal write. */
journal_node_t *n = NULL;
int ret = journal_write_in(journal, &n, id, size);
@@ -759,7 +762,7 @@ int journal_write(journal_t *journal, uint64_t id, const char *src, size_t size)
if (seek_ret < 0 || !sfwrite(src, size, journal->fd)) {
return KNOT_ERROR;
}
-
+
/* Finalize journal write. */
return journal_write_out(journal, n);
}
@@ -769,7 +772,7 @@ int journal_map(journal_t *journal, uint64_t id, char **dst, size_t size)
if (journal == NULL || dst == NULL) {
return KNOT_EINVAL;
}
-
+
/* Prepare journal write. */
journal_node_t *n = NULL;
int ret = journal_write_in(journal, &n, id, size);
@@ -793,12 +796,12 @@ int journal_map(journal_t *journal, uint64_t id, char **dst, size_t size)
}
size -= wb;
}
-
+
/* Align offset to page size (required). */
const size_t ps = sysconf(_SC_PAGESIZE);
off_t ps_delta = (n->pos % ps);
off_t off = n->pos - ps_delta;
-
+
/* Map file region. */
*dst = mmap(NULL, n->len + ps_delta, PROT_READ | PROT_WRITE, MAP_SHARED,
journal->fd, off);
@@ -807,14 +810,14 @@ int journal_map(journal_t *journal, uint64_t id, char **dst, size_t size)
journal->fd, n->pos, n->pos+n->len, errno);
return KNOT_ERROR;
}
-
+
/* Advise usage of memory. */
#ifdef HAVE_MADVISE
madvise(*dst, n->len + ps_delta, MADV_SEQUENTIAL);
#endif
/* Correct dst pointer to alignment. */
*dst += ps_delta;
-
+
return KNOT_EOK;
}
@@ -823,7 +826,7 @@ int journal_unmap(journal_t *journal, uint64_t id, void *ptr, int finalize)
if (journal == NULL || ptr == NULL) {
return KNOT_EINVAL;
}
-
+
/* Mapped node is on tail. */
journal_node_t *n = journal->nodes + journal->qtail;
if(n->id != id) {
@@ -831,19 +834,19 @@ int journal_unmap(journal_t *journal, uint64_t id, void *ptr, int finalize)
(unsigned long long)id);
return KNOT_ENOENT;
}
-
+
/* Realign memory. */
const size_t ps = sysconf(_SC_PAGESIZE);
off_t ps_delta = (n->pos % ps);
ptr = ((char*)ptr - ps_delta);
-
+
/* Unmap memory. */
if (munmap(ptr, n->len + ps_delta) != 0) {
dbg_journal("journal: couldn't munmap() fd=%d <%u,%u> %d\n",
journal->fd, n->pos, n->pos+n->len, errno);
return KNOT_ERROR;
}
-
+
/* Finalize. */
int ret = KNOT_EOK;
if (finalize) {
@@ -899,17 +902,17 @@ int journal_trans_begin(journal_t *journal)
if (journal == NULL) {
return KNOT_EINVAL;
}
-
+
/* Already pending transactions. */
if (journal->bflags & JOURNAL_TRANS) {
return KNOT_EBUSY;
}
-
+
journal->bflags |= JOURNAL_TRANS;
journal->tmark = journal->qtail;
dbg_journal("journal: starting transaction at qtail=%hu\n",
journal->tmark);
-
+
return KNOT_EOK;
}
@@ -921,7 +924,7 @@ int journal_trans_commit(journal_t *journal)
if ((journal->bflags & JOURNAL_TRANS) == 0) {
return KNOT_ENOENT;
}
-
+
/* Mark affected nodes as commited. */
int ret = KNOT_EOK;
size_t i = journal->tmark;
@@ -934,7 +937,7 @@ int journal_trans_commit(journal_t *journal)
return ret;
}
}
-
+
/* Clear in-transaction flags. */
journal->tmark = 0;
journal->bflags &= (~JOURNAL_TRANS);
@@ -949,7 +952,7 @@ int journal_trans_rollback(journal_t *journal)
if ((journal->bflags & JOURNAL_TRANS) == 0) {
return KNOT_ENOENT;
}
-
+
/* Expand free space and rewind node queue tail. */
/*! \note This shouldn't be relied upon and probably shouldn't
* be written back to file, as crashing anywhere between
@@ -976,7 +979,7 @@ int journal_close(journal_t *journal)
if (journal == NULL) {
return KNOT_EINVAL;
}
-
+
/* Check if lazy. */
int ret = KNOT_EOK;
if (journal->fd < 0) {
@@ -984,7 +987,7 @@ int journal_close(journal_t *journal)
} else {
/* Recalculate CRC. */
ret = journal_update_crc(journal->fd);
-
+
/* Unlock journal file. */
journal->fl.l_type = F_UNLCK;
fcntl(journal->fd, F_SETLK, &journal->fl);
@@ -993,7 +996,7 @@ int journal_close(journal_t *journal)
/* Close file. */
close(journal->fd);
}
-
+
dbg_journal("journal: closed journal %p\n", journal);
/* Free allocated resources. */
@@ -1008,14 +1011,14 @@ journal_t *journal_retain(journal_t *journal)
if (journal != NULL) {
if (journal->fd < 0) {
dbg_journal("journal: retain(), opening for rw\n");
- journal = journal_open(journal->path, journal->fslimit,
+ journal = journal_open(journal->path, journal->fslimit,
0, journal->bflags);
} else {
++journal->refs;
dbg_journal("journal: retain(), ++refcount\n");
}
}
-
+
return journal;
}
diff --git a/src/knot/server/journal.h b/src/knot/server/journal.h
index 9462809..a4218a9 100644
--- a/src/knot/server/journal.h
+++ b/src/knot/server/journal.h
@@ -127,9 +127,11 @@ typedef int (*journal_apply_t)(journal_t *j, journal_node_t *n);
* Journal defaults and constants.
*/
#define JOURNAL_NCOUNT 1024 /*!< Default node count. */
-/* HEADER = magic, crc, max_entries, qhead, qtail */
-#define JOURNAL_HSIZE (MAGIC_LENGTH + sizeof(crc_t) + sizeof(uint16_t) * 3)
#define JOURNAL_MAGIC {'k', 'n', 'o', 't', '1', '0', '5'}
+#define MAGIC_LENGTH 7
+/* HEADER = magic, crc, max_entries, qhead, qtail */
+#define JOURNAL_HSIZE (MAGIC_LENGTH + sizeof(crc_t) + sizeof(uint16_t) * 3)
+
/*!
* \brief Create new journal.
@@ -293,7 +295,7 @@ int journal_update(journal_t *journal, journal_node_t *n);
/*!
* \brief Begin transaction of multiple entries.
- *
+ *
* \note Only one transaction at a time is supported.
*
* \param journal Associated journal.
@@ -306,7 +308,7 @@ int journal_trans_begin(journal_t *journal);
/*!
* \brief Commit pending transaction.
- *
+ *
* \note Only one transaction at a time is supported.
*
* \param journal Associated journal.
@@ -319,7 +321,7 @@ int journal_trans_commit(journal_t *journal);
/*!
* \brief Rollback pending transaction.
- *
+ *
* \note Only one transaction at a time is supported.
*
* \param journal Associated journal.
@@ -344,7 +346,7 @@ int journal_close(journal_t *journal);
* \brief Retain journal for use.
*
* Allows to track usage of lazily-opened journals.
- *
+ *
* \param journal Journal.
*
* \return Retained journal.
diff --git a/src/knot/server/notify.c b/src/knot/server/notify.c
index 3eb99a0..e6c9564 100644
--- a/src/knot/server/notify.c
+++ b/src/knot/server/notify.c
@@ -14,11 +14,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
#include "knot/server/notify.h"
#include "libknot/dname.h"
+#include "common/descriptor.h"
#include "libknot/packet/packet.h"
#include "libknot/rrset.h"
#include "libknot/packet/response.h"
@@ -33,6 +35,11 @@
#include "knot/other/debug.h"
#include "knot/server/server.h"
+
+/* Messages. */
+#define NOTIFY_MSG "NOTIFY of '%s' from %s: "
+#define NOTIFY_XMSG "received serial %u."
+
/*----------------------------------------------------------------------------*/
/* Non-API functions */
/*----------------------------------------------------------------------------*/
@@ -125,7 +132,7 @@ int notify_create_response(knot_packet_t *request, uint8_t *buffer,
if (rc == KNOT_EOK) {
rc = knot_response_init_from_query(response, request, 1);
}
-
+
/* Aggregated result check. */
if (rc != KNOT_EOK) {
dbg_notify("%s: failed to init response packet: %s",
@@ -182,26 +189,16 @@ static int notify_check_and_schedule(knot_nameserver_t *nameserver,
if (zone == NULL || from == NULL || knot_zone_data(zone) == NULL) {
return KNOT_EINVAL;
}
-
+
/* Check ACL for notify-in. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
if (from) {
if (acl_match(zd->notify_in, from, 0) == ACL_DENY) {
/* rfc1996: Ignore request and report incident. */
- char straddr[SOCKADDR_STRLEN];
- sockaddr_tostr(from, straddr, sizeof(straddr));
- log_zone_notice("Unauthorized NOTIFY query "
- "from '%s@%d' to zone '%s'.\n",
- straddr, sockaddr_portnum(from),
- zd->conf->name);
- return KNOT_ERROR;
- } else {
- dbg_notify("notify: authorized NOTIFY query.\n");
+ return KNOT_EDENIED;
}
}
- /*! \todo Packet may contain updated RRs. */
-
/* Cancel REFRESH/RETRY timer. */
evsched_t *sched = ((server_t *)knot_ns_get_data(nameserver))->sched;
event_t *refresh_ev = zd->xfr_in.timer;
@@ -212,7 +209,7 @@ static int notify_check_and_schedule(knot_nameserver_t *nameserver,
/* Set REFRESH timer for now. */
evsched_schedule(sched, refresh_ev, 0);
}
-
+
return KNOT_EOK;
}
@@ -238,7 +235,7 @@ int notify_process_request(knot_nameserver_t *ns,
dbg_notify("notify: parsing rest of the packet\n");
if (notify->parsed < notify->size) {
- if (knot_packet_parse_rest(notify) != KNOT_EOK) {
+ if (knot_packet_parse_rest(notify, 0) != KNOT_EOK) {
dbg_notify("notify: failed to parse NOTIFY query\n");
knot_ns_error_response_from_query(ns, notify,
KNOT_RCODE_FORMERR,
@@ -267,81 +264,59 @@ int notify_process_request(knot_nameserver_t *ns,
return KNOT_EOK;
}
- // find the zone
- rcu_read_lock();
+ /* Process notification. */
+ ret = KNOT_ENOZONE;
+ unsigned serial = 0;
const knot_dname_t *qname = knot_packet_qname(notify);
- const knot_zone_t *z = knot_zonedb_find_zone_for_name(
- ns->zone_db, qname);
- if (z == NULL) {
- rcu_read_unlock();
- dbg_notify("notify: failed to find zone by name\n");
- knot_ns_error_response_from_query(ns, notify,
- KNOT_RCODE_FORMERR, buffer,
- size);
- return KNOT_EOK;
+ rcu_read_lock(); /* z */
+ const knot_zone_t *z = knot_zonedb_find_zone_for_name(ns->zone_db, qname);
+ if (z != NULL) {
+ ret = notify_check_and_schedule(ns, z, from);
+ const knot_rrset_t *soa_rr = NULL;
+ soa_rr = knot_packet_answer_rrset(notify, 0);
+ if (soa_rr && knot_rrset_type(soa_rr) == KNOT_RRTYPE_SOA) {
+ serial = knot_rrset_rdata_soa_serial(soa_rr);
+ }
}
-
- notify_check_and_schedule(ns, z, from);
rcu_read_unlock();
- return KNOT_EOK;
+
+ int rcode = KNOT_RCODE_NOERROR;
+ switch (ret) {
+ case KNOT_ENOZONE: rcode = KNOT_RCODE_NOTAUTH; break;
+ case KNOT_EACCES: rcode = KNOT_RCODE_REFUSED; break;
+ default: break;
+ }
+
+ /* Format resulting log message. */
+ char *qstr = knot_dname_to_str(qname);
+ char *fromstr = xfr_remote_str(from, NULL);
+ if (rcode != KNOT_RCODE_NOERROR) {
+ knot_ns_error_response_from_query(ns, notify, KNOT_RCODE_REFUSED,
+ buffer, size);
+ log_server_warning(NOTIFY_MSG "%s\n", qstr, fromstr, knot_strerror(ret));
+ ret = KNOT_EOK; /* Send response. */
+ } else {
+ log_server_info(NOTIFY_MSG NOTIFY_XMSG "\n", qstr, fromstr, serial);
+ }
+ free(qstr);
+ free(fromstr);
+
+ return ret;
}
/*----------------------------------------------------------------------------*/
-int notify_process_response(knot_nameserver_t *nameserver,
- knot_packet_t *notify,
- sockaddr_t *from,
- uint8_t *buffer, size_t *size)
+int notify_process_response(knot_packet_t *notify, int msgid)
{
- if (nameserver == NULL || notify == NULL || from == NULL
- || buffer == NULL || size == NULL) {
+ if (!notify) {
return KNOT_EINVAL;
}
- /* Assert no response size. */
- *size = 0;
-
- /* Find matching zone. */
- rcu_read_lock();
- const knot_dname_t *zone_name = knot_packet_qname(notify);
- knot_zone_t *zone = knot_zonedb_find_zone(nameserver->zone_db,
- zone_name);
- if (!zone) {
- rcu_read_unlock();
- return KNOT_ENOENT;
- }
- if (!knot_zone_data(zone)) {
- rcu_read_unlock();
- return KNOT_ENOENT;
- }
-
/* Match ID against awaited. */
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- pthread_mutex_lock(&zd->lock);
uint16_t pkt_id = knot_packet_id(notify);
- notify_ev_t *ev = 0, *match = 0;
- WALK_LIST(ev, zd->notify_pending) {
- if ((int)pkt_id == ev->msgid) {
- match = ev;
- break;
- }
- }
-
- /* Found waiting NOTIFY query? */
- if (!match) {
- rcu_read_unlock();
- pthread_mutex_unlock(&zd->lock);
+ if (pkt_id != msgid) {
return KNOT_ERROR;
}
- /* NOTIFY is now finished. */
- zones_cancel_notify(zd, match);
-
- /* Zone was removed/reloaded. */
- pthread_mutex_unlock(&zd->lock);
-
- rcu_read_unlock();
-
return KNOT_EOK;
}
-
diff --git a/src/knot/server/notify.h b/src/knot/server/notify.h
index 91b47d9..4b0c3da 100644
--- a/src/knot/server/notify.h
+++ b/src/knot/server/notify.h
@@ -37,20 +37,7 @@
#include "common/sockaddr.h"
#include "libknot/nameserver/name-server.h"
-/*!
- * \brief Pending NOTIFY event.
- * \see knot_zone_t.notify_pending
- */
-typedef struct notify_ev_t {
- node n;
- int timeout; /*!< Timeout for events. */
- int retries; /*!< Number of retries. */
- int msgid; /*!< ID of pending NOTIFY. */
- sockaddr_t addr; /*!< Slave server address. */
- sockaddr_t saddr; /*!< Transit interface address. */
- struct event_t *timer; /*!< Event timer. */
- knot_zone_t *zone; /*!< Associated zone. */
-} notify_ev_t;
+#define NOTIFY_TIMEOUT 3 /*!< Interval between NOTIFY retries. */
/*!
* \brief Creates a NOTIFY request message for SOA RR of the given zone.
@@ -108,21 +95,14 @@ int notify_process_request(knot_nameserver_t *nameserver,
/*!
* \brief Processes NOTIFY response packet.
*
- * \param nameserver Name server structure to provide the needed data.
- * \param from Address of the response sender.
- * \param packet Parsed response packet.
- * \param response_wire Place for the response in wire format.
- * \param rsize Input: maximum acceptable size of the response. Output: real
- * size of the response.
+ * \param notify Parsed response packet.
+ * \param msgid Expected message ID.
*
* \retval KNOT_EOK if a valid response was created.
* \retval KNOT_EINVAL on invalid parameters or packet.
- * \retval KNOT_EMALF if an error occured and the response is not valid.
+ * \retval KNOT_ERROR on message ID mismatch
*/
-int notify_process_response(knot_nameserver_t *nameserver,
- knot_packet_t *notify,
- sockaddr_t *from,
- uint8_t *buffer, size_t *size);
+int notify_process_response(knot_packet_t *notify, int msgid);
#endif /* _KNOTD_NOTIFY_H_ */
diff --git a/src/knot/server/rrl.c b/src/knot/server/rrl.c
index 84b8c90..f064d8f 100644
--- a/src/knot/server/rrl.c
+++ b/src/knot/server/rrl.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
@@ -21,11 +22,12 @@
#include <assert.h>
#include "knot/server/rrl.h"
-#include "knot/common.h"
+#include "knot/knot.h"
#include "libknot/consts.h"
#include "libknot/util/wire.h"
#include "common/hattrie/murmurhash3.h"
#include "common/prng.h"
+#include "common/descriptor.h"
#include "common/errors.h"
/* Hopscotch defines. */
@@ -95,7 +97,7 @@ static uint8_t rrl_clsid(rrl_req_t *p)
if (ret == CLS_NORMAL && p->flags & KNOT_PF_WILDCARD) {
return CLS_WILDCARD;
}
-
+
/* Check query type for spec. classes. */
if (p->qst) {
switch(p->qst->qtype) {
@@ -144,21 +146,21 @@ static int rrl_clsname(char *dst, size_t maxlen, uint8_t cls,
if (p->qst) dn = p->qst->qname;
break;
}
-
+
if (dn) { /* Check used dname. */
assert(dn); /* Should be always set. */
n = knot_dname_name(dn);
nb = (int)knot_dname_size(dn);
}
-
+
/* Write to wire */
- if (nb > maxlen) return KNOT_ESPACE;
+ if ((size_t)nb > maxlen) return KNOT_ESPACE;
if (memcpy(dst, n, nb) == NULL) {
dbg_rrl("%s: failed to serialize name=%p len=%u\n",
__func__, n, nb);
return KNOT_ERROR;
}
-
+
return nb;
}
@@ -168,15 +170,15 @@ static int rrl_classify(char *dst, size_t maxlen, const sockaddr_t *a,
if (!dst || !p || !a || maxlen == 0) {
return KNOT_EINVAL;
}
-
+
/* Class */
uint8_t cls = rrl_clsid(p);
*dst = cls;
int blklen = sizeof(cls);
-
+
/* Address (in network byteorder, adjust masks). */
uint64_t nb = 0;
- if (a->family == AF_INET6) { /* Take the /56 prefix. */
+ if (sockaddr_family(a) == AF_INET6) { /* Take the /56 prefix. */
nb = *((uint64_t*)&a->addr6.sin6_addr) & RRL_V6_PREFIX;
} else { /* Take the /24 prefix */
nb = (uint32_t)a->addr4.sin_addr.s_addr & RRL_V4_PREFIX;
@@ -192,13 +194,13 @@ static int rrl_classify(char *dst, size_t maxlen, const sockaddr_t *a,
if (len < 0) return len;
*nlen = len;
blklen += len;
-
+
/* Seed. */
if (blklen + sizeof(seed) > maxlen) return KNOT_ESPACE;
if (memcpy(dst + blklen, (void*)&seed, sizeof(seed)) == 0) {
blklen += sizeof(seed);
}
-
+
return blklen;
}
@@ -228,7 +230,7 @@ static int find_free(rrl_table_t *t, unsigned i, uint32_t now)
return (b - t->arr) + (t->size - i);
}
}
-
+
/* this happens if table is full... force vacate current elm */
dbg_rrl("%s: out of free buckets, freeing bucket %u\n", __func__, i);
return i;
@@ -271,7 +273,7 @@ static inline unsigned reduce_dist(rrl_table_t *t, unsigned id, unsigned d, unsi
}
--rd;
}
-
+
assert(rd == 0); /* this happens with p=1/fact(HOP_LEN) */
*f = id;
d = 0; /* force vacate initial element */
@@ -289,7 +291,7 @@ static void rrl_log_state(const sockaddr_t *a, uint16_t flags, uint8_t cls)
if (flags & RRL_BF_ELIMIT) {
what = "enters";
}
-
+
log_server_notice("Address '%s' %s rate-limiting (class '%s').\n",
saddr, what, rrl_clsstr(cls));
#endif
@@ -300,7 +302,7 @@ rrl_table_t *rrl_create(size_t size)
if (size == 0) {
return NULL;
}
-
+
const size_t tbl_len = sizeof(rrl_table_t) + size * sizeof(rrl_item_t);
rrl_table_t *t = malloc(tbl_len);
if (!t) return NULL;
@@ -330,16 +332,16 @@ int rrl_setlocks(rrl_table_t *rrl, unsigned granularity)
if (!rrl) return KNOT_EINVAL;
assert(!rrl->lk); /* Cannot change while locks are used. */
assert(granularity <= rrl->size / 10); /* Due to int. division err. */
-
+
if (pthread_mutex_init(&rrl->ll, NULL) < 0) {
return KNOT_ENOMEM;
}
-
+
/* Alloc new locks. */
rrl->lk = malloc(granularity * sizeof(pthread_mutex_t));
if (!rrl->lk) return KNOT_ENOMEM;
memset(rrl->lk, 0, granularity * sizeof(pthread_mutex_t));
-
+
/* Initialize. */
for (size_t i = 0; i < granularity; ++i) {
if (pthread_mutex_init(rrl->lk + i, NULL) < 0) break;
@@ -356,8 +358,8 @@ int rrl_setlocks(rrl_table_t *rrl, unsigned granularity)
dbg_rrl("%s: failed to init locks\n", __func__);
return KNOT_ERROR;
}
-
- dbg_rrl("%s: set granularity to '%zu'\n", __func__, granularity);
+
+ dbg_rrl("%s: set granularity to '%u'\n", __func__, granularity);
return KNOT_EOK;
}
@@ -369,9 +371,9 @@ rrl_item_t* rrl_hash(rrl_table_t *t, const sockaddr_t *a, rrl_req_t *p,
if (len < 0) {
return NULL;
}
-
+
uint32_t id = hash(buf, len) % t->size;
-
+
/* Lock for lookup. */
pthread_mutex_lock(&t->ll);
@@ -387,13 +389,13 @@ rrl_item_t* rrl_hash(rrl_table_t *t, const sockaddr_t *a, rrl_req_t *p,
if (d > HOP_LEN) { /* not an exact match, find free element [f] */
d = find_free(t, id, stamp);
}
-
+
/* Reduce distance to fit <id, id + HOP_LEN) */
unsigned f = (id + d) % t->size;
while (d >= HOP_LEN) {
d = reduce_dist(t, id, d, &f);
}
-
+
/* Assign granular lock and unlock lookup. */
*lock = f % t->lk_count;
rrl_lock(t, *lock);
@@ -422,7 +424,7 @@ rrl_item_t* rrl_hash(rrl_table_t *t, const sockaddr_t *a, rrl_req_t *p,
dbg_rrl("%s: bucket '%4x' slow-start\n", __func__, id);
}
}
-
+
return b;
}
@@ -430,7 +432,7 @@ int rrl_query(rrl_table_t *rrl, const sockaddr_t *a, rrl_req_t *req,
const knot_zone_t *zone)
{
if (!rrl || !req || !a) return KNOT_EINVAL;
-
+
/* Calculate hash and fetch */
int ret = KNOT_EOK;
int lock = -1;
@@ -441,7 +443,7 @@ int rrl_query(rrl_table_t *rrl, const sockaddr_t *a, rrl_req_t *req,
if (lock > -1) rrl_unlock(rrl, lock);
return KNOT_ERROR;
}
-
+
/* Calculate rate for dT */
uint32_t dt = now - b->time;
if (dt > RRL_CAPACITY) {
@@ -458,7 +460,7 @@ int rrl_query(rrl_table_t *rrl, const sockaddr_t *a, rrl_req_t *req,
b->flags &= ~RRL_BF_ELIMIT;
rrl_log_state(a, b->flags, b->cls);
}
-
+
/* Add new tokens. */
uint32_t dn = rrl->rate * dt;
if (b->flags & RRL_BF_SSTART) { /* Bucket in slow-start. */
@@ -471,7 +473,7 @@ int rrl_query(rrl_table_t *rrl, const sockaddr_t *a, rrl_req_t *req,
b->ntok = RRL_CAPACITY * rrl->rate;
}
}
-
+
/* Last item taken. */
if (b->ntok == 1 && !(b->flags & RRL_BF_ELIMIT)) {
b->flags |= RRL_BF_ELIMIT;
@@ -484,7 +486,7 @@ int rrl_query(rrl_table_t *rrl, const sockaddr_t *a, rrl_req_t *req,
} else if (b->ntok == 0) {
ret = KNOT_ELIMIT;
}
-
+
if (lock > -1) rrl_unlock(rrl, lock);
return ret;
}
@@ -499,7 +501,7 @@ int rrl_destroy(rrl_table_t *rrl)
}
free(rrl->lk);
}
-
+
free(rrl);
return KNOT_EOK;
}
@@ -513,18 +515,18 @@ int rrl_reseed(rrl_table_t *rrl)
rrl_lock(rrl, i);
}
}
-
+
memset(rrl->arr, 0, rrl->size * sizeof(rrl_item_t));
rrl->seed = (uint32_t)(tls_rand() * (double)UINT32_MAX);
dbg_rrl("%s: reseed to '%u'\n", __func__, rrl->seed);
-
+
if (rrl->lk_count > 0) {
for (unsigned i = 0; i < rrl->lk_count; ++i) {
rrl_unlock(rrl, i);
}
pthread_mutex_unlock(&rrl->ll);
}
-
+
return KNOT_EOK;
}
diff --git a/src/knot/server/rrl.h b/src/knot/server/rrl.h
index 6ced2f8..59ac9a6 100644
--- a/src/knot/server/rrl.h
+++ b/src/knot/server/rrl.h
@@ -51,7 +51,7 @@ typedef struct rrl_item {
/*!
* \brief RRL hash bucket table.
- *
+ *
* Table is fixed size, so collisions may occur and are dealt with
* in a way, that hashbucket rate is reset and enters slow-start for 1 dt.
* When a bucket is in a slow-start mode, it cannot reset again for the time
@@ -60,7 +60,7 @@ typedef struct rrl_item {
* To avoid lock contention, N locks are created and distributed amongst buckets.
* As of now lock K for bucket N is calculated as K = N % (num_buckets).
*/
-
+
typedef struct rrl_table {
uint32_t rate; /* Configured RRL limit */
uint32_t seed; /* Pseudorandom seed for hashing. */
@@ -145,7 +145,7 @@ int rrl_query(rrl_table_t *rrl, const sockaddr_t *a, rrl_req_t *req,
/*!
* \brief Destroy RRL table.
* \param rrl RRL table.
- * \return KNOT_EOK
+ * \return KNOT_EOK
*/
int rrl_destroy(rrl_table_t *rrl);
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index 4ac919d..cef3801 100644
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -24,7 +24,7 @@
#include <assert.h>
#include "common/prng.h"
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/server/server.h"
#include "knot/server/udp-handler.h"
#include "knot/server/tcp-handler.h"
@@ -39,8 +39,7 @@
/*! \brief Event scheduler loop. */
static int evsched_run(dthread_t *thread)
{
- iohandler_t *sched_h = (iohandler_t *)thread->data;
- evsched_t *s = (evsched_t*)sched_h->data;
+ evsched_t *s = (evsched_t*)thread->data;
if (!s) {
return KNOT_EINVAL;
}
@@ -84,23 +83,13 @@ typedef struct pnode_t {
static void server_remove_iface(iface_t *iface)
{
/* Free UDP handler. */
- iohandler_t *handler = iface->handler[UDP_ID];
- if (handler) {
- server_remove_handler(handler->server, handler);
- } else {
- if (iface->fd[UDP_ID] > -1) {
- close(iface->fd[UDP_ID]);
- }
+ if (iface->fd[IO_UDP] > -1) {
+ close(iface->fd[IO_UDP]);
}
/* Free TCP handler. */
- handler = iface->handler[TCP_ID];
- if (handler) {
- server_remove_handler(handler->server, handler);
- } else {
- if (iface->fd[TCP_ID] > -1) {
- close(iface->fd[TCP_ID]);
- }
+ if (iface->fd[IO_TCP] > -1) {
+ close(iface->fd[IO_TCP]);
}
/* Free interface. */
@@ -125,21 +114,30 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
int ret = 0;
int sock = 0;
char errbuf[256] = {0};
- int opt = 1024 * 1024;
- int snd_opt = 1024 * 1024;
memset(new_if, 0, sizeof(iface_t));
/* Create UDP socket. */
- ret = socket_create(cfg_if->family, SOCK_DGRAM);
+ ret = socket_create(cfg_if->family, SOCK_DGRAM, IPPROTO_UDP);
if (ret < 0) {
- strerror_r(errno, errbuf, sizeof(errbuf));
- log_server_error("Could not create UDP socket: %s.\n",
- errbuf);
+ if (strerror_r(errno, errbuf, sizeof(errbuf)) == 0) {
+ log_server_error("Could not create UDP socket: %s.\n",
+ errbuf);
+ }
return ret;
} else {
sock = ret;
}
-
+
+ /* Set socket options. */
+ int flag = 1;
+#ifndef DISABLE_IPV6
+ if (cfg_if->family == AF_INET6) {
+ /* Disable dual-stack for performance reasons. */
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0) {
+ dbg_net("udp: failed to set IPV6_V6ONLY to socket, using default config\n");
+ }
+ }
+#endif
ret = socket_bind(sock, cfg_if->family, cfg_if->address, cfg_if->port);
if (ret < 0) {
socket_close(sock);
@@ -149,36 +147,36 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
return ret;
}
- new_if->fd[UDP_ID] = sock;
- new_if->type[UDP_ID] = cfg_if->family;
-
- /* Set socket options - voluntary. */
- char ebuf[256] = {0};
- if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &snd_opt, sizeof(snd_opt)) < 0) {
- strerror_r(errno, ebuf, sizeof(ebuf));
-// log_server_warning("Failed to configure socket "
-// "write buffers: %s.\n", ebuf);
- }
- if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
- strerror_r(errno, ebuf, sizeof(ebuf));
-// log_server_warning("Failed to configure socket read buffers: %s.\n", ebuf);
- }
+ new_if->fd[IO_UDP] = sock;
+ new_if->type = cfg_if->family;
+ new_if->port = cfg_if->port;
+ new_if->addr = strdup(cfg_if->address);
/* Create TCP socket. */
- ret = socket_create(cfg_if->family, SOCK_STREAM);
+ ret = socket_create(cfg_if->family, SOCK_STREAM, IPPROTO_TCP);
if (ret < 0) {
- socket_close(new_if->fd[UDP_ID]);
- strerror_r(errno, errbuf, sizeof(errbuf));
- log_server_error("Could not create TCP socket: %s.\n",
- errbuf);
+ socket_close(new_if->fd[IO_UDP]);
+ if (strerror_r(errno, errbuf, sizeof(errbuf)) == 0) {
+ log_server_error("Could not create TCP socket: %s.\n",
+ errbuf);
+ }
return ret;
} else {
sock = ret;
}
+ /* Set socket options. */
+#ifndef DISABLE_IPV6
+ if (cfg_if->family == AF_INET6) {
+ if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag)) < 0) {
+ dbg_net("tcp: failed to set IPV6_V6ONLY to socket, using default config\n");
+ }
+ }
+#endif
ret = socket_bind(sock, cfg_if->family, cfg_if->address, cfg_if->port);
if (ret < 0) {
- socket_close(new_if->fd[UDP_ID]);
+ free(new_if->addr);
+ socket_close(new_if->fd[IO_UDP]);
socket_close(sock);
log_server_error("Could not bind to "
"TCP interface %s port %d.\n",
@@ -188,7 +186,8 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
ret = socket_listen(sock, TCP_BACKLOG_SIZE);
if (ret < 0) {
- socket_close(new_if->fd[UDP_ID]);
+ free(new_if->addr);
+ socket_close(new_if->fd[IO_UDP]);
socket_close(sock);
log_server_error("Failed to listen on "
"TCP interface %s port %d.\n",
@@ -196,20 +195,35 @@ static int server_init_iface(iface_t *new_if, conf_iface_t *cfg_if)
return ret;
}
- new_if->fd[TCP_ID] = sock;
- new_if->type[TCP_ID] = cfg_if->family;
- new_if->port = cfg_if->port;
- new_if->addr = strdup(cfg_if->address);
+ new_if->fd[IO_TCP] = sock;
return KNOT_EOK;
}
+static void remove_ifacelist(struct ref_t *p)
+{
+ ifacelist_t *ifaces = (ifacelist_t *)p;
+
+ /* Remove deprecated interfaces. */
+ iface_t *n = NULL, *m = NULL;
+ WALK_LIST_DELSAFE(n, m, ifaces->u) {
+ log_server_info("Removing interface %s port %d.\n",
+ n->addr, n->port);
+ server_remove_iface(n);
+ }
+ WALK_LIST_DELSAFE(n, m, ifaces->l) {
+ free(n);
+ }
+
+ free(ifaces);
+}
+
/*!
* \brief Update bound sockets according to configuration.
*
* \param server Server instance.
* \return number of added sockets.
*/
-static int server_bind_sockets(server_t *server)
+static int server_bind_sockets(server_t *s)
{
/*! \todo This requires locking to disable parallel updates (issue #278).
* However, this is only used when RCU is read-locked, so count with that.
@@ -220,28 +234,18 @@ static int server_bind_sockets(server_t *server)
/* Prepare helper lists. */
int bound = 0;
- node *m = 0;
- list *newlist, unmatched;
- newlist = malloc(sizeof(list));
- init_list(newlist);
- init_list(&unmatched);
+ iface_t *m = 0;
+ ifacelist_t *newlist = malloc(sizeof(ifacelist_t));
+ ref_init(&newlist->ref, &remove_ifacelist);
+ ref_retain(&newlist->ref);
+ init_list(&newlist->u);
+ init_list(&newlist->l);
+
/* Duplicate current list. */
/*! \note Pointers to addr, handlers etc. will be shared. */
- list_dup(&unmatched, server->ifaces, sizeof(iface_t));
-
- /* Update pointers. */
- WALK_LIST(m, unmatched) {
-
- /* Interfaces. */
- iface_t *m_if = (iface_t*)m;
- for (int i = 0; i <= TCP_ID; ++i) {
- iohandler_t *h = m_if->handler[i];
- if (h) {
- h->iface = m_if;
- }
-
- }
+ if (s->ifaces) {
+ list_dup(&s->ifaces->u, &s->ifaces->l, sizeof(iface_t));
}
/* Update bound interfaces. */
@@ -251,12 +255,10 @@ static int server_bind_sockets(server_t *server)
/* Find already matching interface. */
int found_match = 0;
conf_iface_t *cfg_if = (conf_iface_t*)n;
- WALK_LIST(m, unmatched) {
- iface_t *srv_if = (iface_t*)m;
-
+ if (s->ifaces) WALK_LIST(m, s->ifaces->u) {
/* Matching port and address. */
- if (cfg_if->port == srv_if->port) {
- if (strcmp(cfg_if->address, srv_if->addr) == 0) {
+ if (cfg_if->port == m->port) {
+ if (strcmp(cfg_if->address, m->addr) == 0) {
found_match = 1;
break;
}
@@ -265,14 +267,14 @@ static int server_bind_sockets(server_t *server)
/* Found already bound interface. */
if (found_match) {
- rem_node(m);
+ rem_node((node *)m);
} else {
log_server_info("Binding to interface %s port %d.\n",
cfg_if->address, cfg_if->port);
/* Create new interface. */
m = malloc(sizeof(iface_t));
- if (server_init_iface((iface_t*)m, cfg_if) < 0) {
+ if (server_init_iface(m, cfg_if) < 0) {
free(m);
m = 0;
}
@@ -280,128 +282,43 @@ static int server_bind_sockets(server_t *server)
/* Move to new list. */
if (m) {
- add_tail(newlist, m);
+ add_tail(&newlist->l, (node *)m);
++bound;
}
}
+ /* Publish new list. */
+ ifacelist_t *oldlist = rcu_xchg_pointer(&s->ifaces, newlist);
+
/* Unlock configuration. */
rcu_read_unlock();
- /* Publish new list. */
- list* oldlist = rcu_xchg_pointer(&server->ifaces, newlist);
-
/* Ensure no one is reading old interfaces. */
synchronize_rcu();
- /* Remove deprecated interfaces. */
- WALK_LIST_DELSAFE(n, m, unmatched) {
- iface_t *rm_if = (iface_t*)n;
- log_server_info("Removing interface %s port %d.\n",
- rm_if->addr, rm_if->port);
- server_remove_iface(rm_if);
- }
-
- /* Free original list. */
- WALK_LIST_DELSAFE(n, m, *oldlist) {
- /*! \note Need to keep internal pointers, as they are shared
- * with the newly published list. */
- free(n);
- }
- free(oldlist);
-
- return bound;
-}
-
-/*!
- * \brief Update socket handlers according to configuration.
- *
- * \param server Server instance.
- * \retval 0 if successful (EOK).
- * \retval <0 on errors (EINVAL).
- */
-static int server_bind_handlers(server_t *server)
-{
- if (!server || !server->ifaces) {
- return KNOT_EINVAL;
- }
-
- /* Lock config. */
- rcu_read_lock();
-
- /* Estimate number of threads/manager. */
- int thr_count = 0;
- int tcp_unit_size = 0;
- if (conf()->workers < 1) {
- thr_count = dt_optimal_size();
- tcp_unit_size = (thr_count * 2) + 1; /* Will be always odd. */
- } else {
- thr_count = conf()->workers;
- tcp_unit_size = thr_count + 1; /* Force configured value. */
- }
-
- dbg_server("server: configured %d worker%s per UDP iface\n",
- thr_count, thr_count > 1 ? "s" : "");
- dbg_server("server: configured %d worker%s per TCP iface\n",
- tcp_unit_size - 1, (tcp_unit_size - 1) > 1 ? "s" : "");
-
- /* Create socket handlers. */
- node *n = 0;
- iohandler_t* h = 0;
- WALK_LIST(n, *server->ifaces) {
-
- iface_t *iface = (iface_t*)n;
- assert(iface);
-
- /* Create UDP handlers. */
- dt_unit_t *unit = 0;
- if (!iface->handler[UDP_ID]) {
- unit = dt_create_coherent(thr_count, &udp_master, 0);
- if (!unit) {
- continue;
- }
- h = server_create_handler(server, iface->fd[UDP_ID], unit);
- if (!h) {
- dt_delete(&unit);
- continue;
- }
- h->type = iface->type[UDP_ID];
- h->iface = iface;
-
- /* Save pointer. */
- iface->handler[UDP_ID] = h; /* No need for cmpxchg */
- dbg_server("server: creating UDP socket handlers for '%s:%d'\n",
- iface->addr, iface->port);
-
- }
-
- /* Create TCP handlers. */
- if (!iface->handler[TCP_ID]) {
- unit = dt_create(tcp_unit_size);
- if (!unit) {
- continue;
- }
- h = server_create_handler(server, iface->fd[TCP_ID], unit);
- if (!h) {
- dt_delete(&unit);
- continue;
- }
- tcp_loop_unit(h, unit);
- h->type = iface->type[TCP_ID];
- h->iface = iface;
-
- /* Save pointer. */
- iface->handler[TCP_ID] = h; /* No need for cmpxchg */
- dbg_server("server: creating TCP socket handlers for '%s:%d'\n",
- iface->addr, iface->port);
+ /* Update UDP ifacelist (reload all threads). */
+ dt_unit_t *tu = s->h[IO_UDP].unit;
+ for (unsigned i = 0; i < tu->size; ++i) {
+ ref_retain((ref_t *)newlist);
+ s->h[IO_UDP].state[i].s |= ServerReload;
+ if (s->state & ServerRunning) {
+ dt_activate(tu->threads[i]);
+ dt_signalize(tu->threads[i], SIGALRM);
}
+ }
+ /* Update TCP ifacelist (reload master thread). */
+ tu = s->h[IO_TCP].unit;
+ ref_retain((ref_t *)newlist);
+ s->h[IO_TCP].state[0].s |= ServerReload;
+ if (s->state & ServerRunning) {
+ dt_activate(tu->threads[0]);
+ dt_signalize(tu->threads[0], SIGALRM);
}
- /* Unlock config. */
- rcu_read_unlock();
+ ref_release(&oldlist->ref);
- return KNOT_EOK;
+ return bound;
}
server_t *server_create()
@@ -414,18 +331,10 @@ server_t *server_create()
}
memset(server, 0, sizeof(server_t));
- server->state = ServerIdle;
- init_list(&server->handlers);
- server->ifaces = malloc(sizeof(list));
- init_list(server->ifaces);
-
// Create event scheduler
dbg_server("server: creating event scheduler\n");
server->sched = evsched_new();
- dt_unit_t *unit = dt_create_coherent(1, evsched_run, 0);
- iohandler_t *h = server_create_handler(server, -1, unit);
-
- h->data = server->sched;
+ server->iosched = dt_create_coherent(1, evsched_run, server->sched);
// Create name server
dbg_server("server: creating Name Server structure\n");
@@ -439,8 +348,8 @@ server_t *server_create()
OpenSSL_add_all_digests();
// Create XFR handler
- server->xfr_h = xfr_create(XFR_THREADS_COUNT, server->nameserver);
- if (!server->xfr_h) {
+ server->xfr = xfr_create(XFR_THREADS_COUNT, server->nameserver);
+ if (!server->xfr) {
knot_ns_destroy(&server->nameserver);
free(server);
return NULL;
@@ -450,179 +359,98 @@ server_t *server_create()
return server;
}
-iohandler_t *server_create_handler(server_t *server, int fd, dt_unit_t *unit)
+int server_init_handler(iohandler_t * h, server_t *s, dt_unit_t *tu, void *d)
{
- // Create new worker
- iohandler_t *handler = malloc(sizeof(iohandler_t));
- if (handler == 0) {
- ERR_ALLOC_FAILED;
- return 0;
- }
-
- // Initialize
- handler->fd = fd;
- handler->type = 0;
- handler->state = ServerIdle;
- handler->server = server;
- handler->unit = unit;
- handler->iface = 0;
- handler->data = 0;
- handler->interrupt = 0;
-
- // Update unit data object
- for (int i = 0; i < unit->size; ++i) {
- dthread_t *thread = unit->threads[i];
+ /* Initialize */
+ memset(h, 0, sizeof(iohandler_t));
+ h->server = s;
+ h->unit = tu;
+ h->data = d;
+ h->state = malloc(tu->size * sizeof(iostate_t));
+
+ /* Update unit data object */
+ for (int i = 0; i < tu->size; ++i) {
+ dthread_t *thread = tu->threads[i];
+ h->state[i].h = h;
+ h->state[i].s = 0;
if (thread->run) {
- dt_repurpose(thread, thread->run, handler);
+ dt_repurpose(thread, thread->run, h->state + i);
}
}
- /*! \todo This requires locking to disable parallel updates (issue #278).
- * However, this is only used when RCU is read-locked, so count with that.
- */
-
- /* Lock RCU. */
- rcu_read_lock();
-
- // Update list
- add_tail(&server->handlers, (node*)handler);
-
- /* Unlock RCU. */
- rcu_read_unlock();
-
- return handler;
+ return KNOT_EOK;
}
-int server_remove_handler(server_t *server, iohandler_t *h)
+int server_free_handler(iohandler_t *h)
{
- // Check
- if (h == 0) {
+ if (!h || !h->server) {
return KNOT_EINVAL;
}
- /* Lock RCU. */
- rcu_read_lock();
-
- /*! \todo This requires locking to disable parallel updates (issue #278).
- * However, this is only used when RCU is read-locked, so count with that.
- */
-
- // Remove node
- rem_node((node*)h);
-
- // Wait for dispatcher to finish
- if (h->state & ServerRunning) {
- h->state = ServerIdle;
+ /* Wait for threads to finish */
+ if (h->unit) {
dt_stop(h->unit);
-
- /* Call interrupt handler. */
- if (h->interrupt) {
- h->interrupt(h);
- }
-
dt_join(h->unit);
}
- // Close socket
- if (h->fd >= 0) {
- socket_close(h->fd);
- h->fd = -1;
- }
-
- // Update interface
- if (h->iface) {
- int id = UDP_ID;
- if (h->iface->handler[TCP_ID] == h) {
- id = TCP_ID;
- }
-
- h->iface->fd[id] = h->fd;
- h->iface->handler[id] = 0;
+ /* Destroy worker context. */
+ if (h->dtor) {
+ h->dtor(h->data);
+ h->data = NULL;
}
-
- /* Unlock RCU. */
- rcu_read_unlock();
-
- /* RCU synchronize. */
- synchronize_rcu();
-
- // Destroy dispatcher and worker
dt_delete(&h->unit);
- free(h);
+ free(h->state);
+ memset(h, 0, sizeof(iohandler_t));
return KNOT_EOK;
}
-int server_start(server_t *server)
+int server_start(server_t *s)
{
// Check server
- if (server == 0) {
+ if (s == 0) {
return KNOT_EINVAL;
}
dbg_server("server: starting server instance\n");
/* Start XFR handler. */
- xfr_start(server->xfr_h);
+ xfr_start(s->xfr);
- /* Lock configuration. */
- rcu_read_lock();
+ /* Start evsched handler. */
+ dt_start(s->iosched);
- // Start dispatchers
+ /* Start I/O handlers. */
int ret = KNOT_EOK;
- server->state |= ServerRunning;
- iohandler_t *h = 0;
- WALK_LIST(h, server->handlers) {
-
- /* Already running. */
- if (h->state & ServerRunning) {
- continue;
- }
-
- h->state = ServerRunning;
- ret = dt_start(h->unit);
- if (ret < 0) {
- break;
+ s->state |= ServerRunning;
+ if (s->tu_size > 0) {
+ for (unsigned i = 0; i < IO_COUNT; ++i) {
+ ret = dt_start(s->h[i].unit);
}
}
- /* Unlock configuration. */
- rcu_read_unlock();
dbg_server("server: server started\n");
return ret;
}
-int server_wait(server_t *server)
+int server_wait(server_t *s)
{
- /* Join threading unit. */
- xfr_join(server->xfr_h);
-
- /* Lock RCU. */
- rcu_read_lock();
+ if (!s) return KNOT_EINVAL;
- // Wait for handlers to finish
- int ret = 0;
- iohandler_t *h = 0, *nxt = 0;
- WALK_LIST_DELSAFE(h, nxt, server->handlers) {
-
- /* Unlock RCU. */
- rcu_read_unlock();
+ xfr_join(s->xfr);
+ dt_join(s->iosched);
+ if (s->tu_size == 0) {
+ return KNOT_EOK;
+ }
- /* Remove handler. */
- int dret = dt_join(h->unit);
- if (dret < 0) {
- ret = dret;
+ int ret = KNOT_EOK;
+ for (unsigned i = 0; i < IO_COUNT; ++i) {
+ if ((ret = server_free_handler(s->h + i)) != KNOT_EOK) {
+ break;
}
- server_remove_handler(server, h);
-
- /* Relock RCU. */
- rcu_read_lock();
}
- /* Unlock RCU. */
- rcu_read_unlock();
-
return ret;
}
@@ -631,7 +459,7 @@ int server_refresh(server_t *server)
if (server == NULL || server->nameserver == NULL) {
return KNOT_EINVAL;
}
-
+
/* Lock RCU and fetch zones. */
rcu_read_lock();
knot_nameserver_t *ns = server->nameserver;
@@ -641,7 +469,7 @@ int server_refresh(server_t *server)
rcu_read_unlock();
return KNOT_ENOMEM;
}
-
+
/* REFRESH zones. */
for (unsigned i = 0; i < knot_zonedb_zone_count(ns->zone_db); ++i) {
zonedata_t *zd = (zonedata_t *)zones[i]->data;
@@ -656,7 +484,7 @@ int server_refresh(server_t *server)
/* Cumulative delay. */
}
}
-
+
/* Unlock RCU. */
rcu_read_unlock();
free(zones);
@@ -668,7 +496,7 @@ int server_reload(server_t *server, const char *cf)
if (!server || !cf) {
return KNOT_EINVAL;
}
-
+
log_server_info("Reloading configuration...\n");
int cf_ret = conf_open(cf);
switch (cf_ret) {
@@ -687,82 +515,53 @@ int server_reload(server_t *server, const char *cf)
"reload failed.\n");
break;
}
-
+
/*! \todo Close and bind to new remote control. */
return cf_ret;
}
void server_stop(server_t *server)
{
- dbg_server("server: stopping server\n");
-
+ log_server_info("Stopping server...\n");
+
/* Send termination event. */
evsched_schedule_term(server->sched, 0);
/* Interrupt XFR handler execution. */
- if (server->xfr_h->interrupt) {
- server->xfr_h->interrupt(server->xfr_h);
- }
-
- /* Lock RCU. */
- rcu_read_lock();
+ xfr_stop(server->xfr);
- /* Notify servers to stop. */
- log_server_info("Stopping server...\n");
+ /* Clear 'running' flag. */
server->state &= ~ServerRunning;
- iohandler_t *h = 0;
- WALK_LIST(h, server->handlers) {
- h->state = ServerIdle;
- dt_stop(h->unit);
-
- /* Call interrupt handler. */
- if (h->interrupt) {
- h->interrupt(h);
- }
- }
-
- /* Unlock RCU. */
- rcu_read_unlock();
}
void server_destroy(server_t **server)
{
// Check server
- if (!server) {
+ if (!server || !*server) {
return;
}
- if (!*server) {
- return;
- }
-
+
dbg_server("server: destroying server instance\n");
-
- // Free XFR master
- xfr_free((*server)->xfr_h);
-
- // Free interfaces
- node *n = 0, *nxt = 0;
- if ((*server)->ifaces) {
- WALK_LIST_DELSAFE(n, nxt, *(*server)->ifaces) {
- iface_t *iface = (iface_t*)n;
- server_remove_iface(iface);
+
+ /* Free remaining interfaces. */
+ ifacelist_t *ifaces = (*server)->ifaces;
+ iface_t *n = NULL, *m = NULL;
+ if (ifaces) {
+ WALK_LIST_DELSAFE(n, m, ifaces->l) {
+ server_remove_iface(n);
}
- free((*server)->ifaces);
+ free(ifaces);
+ (*server)->ifaces = NULL;
}
+ xfr_free((*server)->xfr);
stat_static_gath_free();
knot_ns_destroy(&(*server)->nameserver);
-
- // Delete event scheduler
evsched_delete(&(*server)->sched);
-
- /* Delete rate limiting table. */
+ dt_delete(&(*server)->iosched);
rrl_destroy((*server)->rrl);
-
free(*server);
-
EVP_cleanup();
-
*server = NULL;
}
@@ -773,7 +572,37 @@ int server_conf_hook(const struct conf_t *conf, void *data)
if (!server) {
return KNOT_EINVAL;
}
-
+
+ /* Estimate number of threads/manager. */
+ int ret = KNOT_EOK;
+ int tu_size = conf->workers;
+ if (tu_size < 1) {
+ tu_size = dt_optimal_size();
+ }
+ if ((unsigned)tu_size != server->tu_size) {
+ /* Free old handlers */
+ if (server->tu_size > 0) {
+ for (unsigned i = 0; i < IO_COUNT; ++i) {
+ ret = server_free_handler(server->h + i);
+ }
+ }
+
+ /* Initialize I/O handlers. */
+ size_t udp_size = tu_size;
+ if (udp_size < 2) udp_size = 2;
+ dt_unit_t *tu = dt_create_coherent(udp_size, &udp_master, NULL);
+ server_init_handler(server->h + IO_UDP, server, tu, NULL);
+ tu = dt_create(tu_size * 2);
+ server_init_handler(server->h + IO_TCP, server, tu, NULL);
+ tcp_loop_unit(server->h + IO_TCP, tu);
+ if (server->state & ServerRunning) {
+ for (unsigned i = 0; i < IO_COUNT; ++i) {
+ ret = dt_start(server->h[i].unit);
+ }
+ }
+ server->tu_size = tu_size;
+ }
+
/* Rate limiting. */
if (!server->rrl && conf->rrl > 0) {
server->rrl = rrl_create(conf->rrl_size);
@@ -784,7 +613,7 @@ int server_conf_hook(const struct conf_t *conf, void *data)
}
}
if (server->rrl) {
- if (rrl_rate(server->rrl) != conf->rrl) {
+ if (rrl_rate(server->rrl) != (uint32_t)conf->rrl) {
rrl_setrate(server->rrl, conf->rrl);
log_server_info("Rate limiting set to %u responses/sec.\n",
conf->rrl);
@@ -792,39 +621,29 @@ int server_conf_hook(const struct conf_t *conf, void *data)
}
/* Update bound sockets. */
- int ret = KNOT_EOK;
if ((ret = server_bind_sockets(server)) < 0) {
log_server_error("Failed to bind configured "
"interfaces.\n");
- } else {
- /* Update handlers. */
- if ((ret = server_bind_handlers(server)) < 0) {
- log_server_error("Failed to create handlers for "
- "configured interfaces.\n");
- }
}
- /* Exit if the server is not running. */
- if (ret != KNOT_EOK || !(server->state & ServerRunning)) {
- return KNOT_ENOTRUNNING;
- }
+ return ret;
+}
- /* Start new handlers. */
- iohandler_t *h = 0;
- WALK_LIST(h, server->handlers) {
- if (!(h->state & ServerRunning)) {
- h->state = ServerRunning;
- ret = dt_start(h->unit);
- if (ret < 0) {
- log_server_error("Handler for '%s@%d' "
- "has failed to start.\n",
- h->iface->addr,
- h->iface->port);
- break;
- }
+ref_t *server_set_ifaces(server_t *s, fdset_t **fds, int *count, int type)
+{
+ iface_t *i = NULL;
+ *count = 0;
+
+ rcu_read_lock();
+ fdset_destroy(*fds);
+ *fds = fdset_new();
+ if (s->ifaces) {
+ WALK_LIST(i, s->ifaces->l) {
+ fdset_add(*fds, i->fd[type], OS_EV_READ);
+ *count += 1;
}
- }
- return ret;
+ }
+ rcu_read_unlock();
+ return (ref_t *)s->ifaces;
}
-
diff --git a/src/knot/server/server.h b/src/knot/server/server.h
index 6d2e06c..84a32e3 100644
--- a/src/knot/server/server.h
+++ b/src/knot/server/server.h
@@ -36,7 +36,6 @@
#ifndef _KNOTD_SERVER_H_
#define _KNOTD_SERVER_H_
-#include "knot/common.h"
#include "libknot/nameserver/name-server.h"
#include "knot/server/xfr-handler.h"
#include "knot/server/socket.h"
@@ -48,23 +47,23 @@
/* Forwad declarations. */
struct iface_t;
-struct iohandler_t;
struct server_t;
struct conf_t;
+typedef struct iostate {
+ volatile unsigned s;
+ struct iohandler* h;
+} iostate_t;
+
/*! \brief I/O handler structure.
*/
-typedef struct iohandler_t {
- struct node *next, *prev;
- int fd; /*!< I/O filedescriptor */
- int type; /*!< Descriptor type/family. */
- unsigned state; /*!< Handler state */
+typedef struct iohandler {
+ struct node n;
dt_unit_t *unit; /*!< Threading unit */
- struct iface_t *iface; /*!< Reference to associated interface. */
struct server_t *server; /*!< Reference to server */
void *data; /*!< Persistent data for I/O handler. */
- void (*interrupt)(struct iohandler_t *h); /*!< Interrupt handler. */
-
+ iostate_t *state;
+ void (*dtor)(void *data); /*!< Data destructor. */
} iohandler_t;
/*! \brief Round-robin mechanism of switching.
@@ -76,24 +75,33 @@ typedef struct iohandler_t {
*/
typedef enum {
ServerIdle = 0 << 0, /*!< Server is idle. */
- ServerRunning = 1 << 0 /*!< Server is running. */
+ ServerRunning = 1 << 0, /*!< Server is running. */
+ ServerReload = 1 << 1 /*!< Server reload requested. */
} server_state;
/*!
* \brief Server interface structure.
*/
typedef struct iface_t {
- struct node *next, *prev;
- int fd[2]; /*!< \brief Socket filedescriptors (UDP, TCP). */
- int type[2]; /*!< \brief Socket type. */
+ struct node n;
+ int fd[2];
+ int type;
int port; /*!< \brief Socket port. */
char* addr; /*!< \brief Socket address. */
- iohandler_t* handler[2]; /*!< \brief Associated I/O handlers. */
} iface_t;
-/* Interface indexes. */
-#define UDP_ID 0
-#define TCP_ID 1
+/* Handler types. */
+#define IO_COUNT 2
+enum {
+ IO_UDP = 0,
+ IO_TCP = 1
+};
+
+typedef struct ifacelist {
+ ref_t ref;
+ list l;
+ list u;
+} ifacelist_t;
/*!
* \brief Main server structure.
@@ -108,18 +116,18 @@ typedef struct server_t {
/*! \brief Reference to the name server structure. */
knot_nameserver_t *nameserver;
- /*! \brief XFR handler. */
- xfrhandler_t *xfr_h;
+ /*! \brief I/O handlers. */
+ unsigned tu_size;
+ xfrhandler_t *xfr;
+ iohandler_t h[IO_COUNT];
/*! \brief Event scheduler. */
+ dt_unit_t *iosched;
evsched_t *sched;
- /*! \brief I/O handlers list. */
- list handlers;
-
/*! \brief List of interfaces. */
- list* ifaces;
-
+ ifacelist_t* ifaces;
+
/*! \brief Rate limiting. */
rrl_table_t *rrl;
@@ -136,30 +144,27 @@ typedef struct server_t {
server_t *server_create();
/*!
- * \brief Create and bind handler to given filedescriptor.
+ * \brief Create I/O handler.
*
- * Pointer to handler instance is used as native unique identifier.
- * This requests instance not to be reallocated.
- *
- * \param server Server structure to be used for operation.
- * \param fd I/O filedescriptor.
- * \param unit Threading unit to serve given filedescriptor.
+ * \param h Initialized handler.
+ * \param s Server structure to be used for operation.
+ * \param u Threading unit to serve given filedescriptor.
+ * \param d Handler data.
*
* \retval Handler instance if successful.
* \retval NULL If an error occured.
*/
-iohandler_t *server_create_handler(server_t *server, int fd, dt_unit_t *unit);
+int server_init_handler(iohandler_t * h, server_t *s, dt_unit_t *u, void *d);
/*!
* \brief Delete handler.
*
- * \param server Server structure to be used for operation.
- * \param ref I/O handler instance.
+ * \param ref I/O handler instance.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EINVAL on invalid parameters.
*/
-int server_remove_handler(server_t *server, iohandler_t *ref);
+int server_free_handler(iohandler_t *h);
/*!
* \brief Starts the server.
@@ -197,7 +202,7 @@ int server_refresh(server_t *server);
*
* \param server Server instance.
* \param cf Config file path.
- * \return
+ * \return
*/
int server_reload(server_t *server, const char *cf);
@@ -227,6 +232,16 @@ void server_destroy(server_t **server);
*/
int server_conf_hook(const struct conf_t *conf, void *data);
+/*!
+ * \brief Update fdsets from current interfaces list.
+ * \param s Server.
+ * \param fds Filedescriptor set.
+ * \param count Number of ifaces (will be set to N).
+ * \param type I/O type (UDP/TCP).
+ * \return new interface list
+ */
+ref_t *server_set_ifaces(server_t *s, fdset_t **fds, int *count, int type);
+
#endif // _KNOTD_SERVER_H_
/*! @} */
diff --git a/src/knot/server/socket.c b/src/knot/server/socket.c
index db39a0d..c6dff63 100644
--- a/src/knot/server/socket.c
+++ b/src/knot/server/socket.c
@@ -25,20 +25,22 @@
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
#ifdef HAVE_NETINET_IN_SYSTM_H
#include <netinet/in_systm.h>
#endif
#include <netinet/in.h>
-#include <netinet/ip.h>
#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <assert.h>
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/server/socket.h"
-int socket_create(int family, int type)
+int socket_create(int family, int type, int proto)
{
/* Create socket. */
- int ret = socket(family, type, 0);
+ int ret = socket(family, type, proto);
if (ret < 0) {
return knot_map_errno(EACCES, EINVAL, ENOMEM);
}
@@ -46,7 +48,7 @@ int socket_create(int family, int type)
return ret;
}
-int socket_connect(int fd, const char *addr, unsigned short port)
+int socket_connect(int fd, int family, const char *addr, unsigned short port)
{
/* NULL address => any */
if (!addr) {
@@ -55,44 +57,52 @@ int socket_connect(int fd, const char *addr, unsigned short port)
/* Resolve address. */
int ret = KNOT_EOK;
- struct addrinfo hints, *res;
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- if ((ret = getaddrinfo(addr, NULL, &hints, &res)) != 0) {
- return KNOT_EINVAL;
- }
-
- /* Evaluate address type. */
+ struct sockaddr_un uaddr;
struct sockaddr *saddr = 0;
socklen_t addrlen = 0;
+ struct addrinfo hints, *res = NULL;
+ if (family == AF_UNIX) {
+ saddr = (struct sockaddr *)&uaddr;
+ addrlen = sizeof(struct sockaddr_un);
+
+ memset(&uaddr, 0, sizeof(struct sockaddr_un));
+ uaddr.sun_family = AF_UNIX;
+ strncpy(uaddr.sun_path, addr, sizeof(uaddr.sun_path) - 1);
+ } else {
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((ret = getaddrinfo(addr, NULL, &hints, &res)) != 0) {
+ return KNOT_EINVAL;
+ }
+
+ /* Evaluate address type. */
#ifndef DISABLE_IPV6
- if (res->ai_family == AF_INET6) {
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)res->ai_addr;
- ipv6->sin6_port = htons(port);
- saddr = (struct sockaddr*)ipv6;
- addrlen = sizeof(struct sockaddr_in6);
- }
+ if (res->ai_family == AF_INET6) {
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
+ ipv6->sin6_port = htons(port);
+ saddr = (struct sockaddr*)ipv6;
+ addrlen = sizeof(struct sockaddr_in6);
+ }
#endif
- if (res->ai_family == AF_INET) {
- struct sockaddr_in *ipv4 = (struct sockaddr_in*)res->ai_addr;
- ipv4->sin_port = htons(port);
- saddr = (struct sockaddr*)ipv4;
- addrlen = sizeof(struct sockaddr_in);
+ if (res->ai_family == AF_INET) {
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
+ ipv4->sin_port = htons(port);
+ saddr = (struct sockaddr*)ipv4;
+ addrlen = sizeof(struct sockaddr_in);
+ }
}
/* Connect. */
- ret = -1;
ret = connect(fd, saddr, addrlen);
if (ret < 0) {
ret = knot_map_errno(EACCES, EADDRINUSE, EAGAIN,
ECONNREFUSED, EISCONN);
}
-
-
/* Free addresses. */
- freeaddrinfo(res);
+ if (res)
+ freeaddrinfo(res);
return ret;
}
@@ -104,6 +114,7 @@ int socket_bind(int socket, int family, const char *addr, unsigned short port)
int ret = 0;
struct sockaddr* paddr = 0;
socklen_t addrlen = 0;
+ struct sockaddr_un uaddr;
struct sockaddr_in saddr;
#ifndef DISABLE_IPV6
struct sockaddr_in6 saddr6;
@@ -129,7 +140,7 @@ int socket_bind(int socket, int family, const char *addr, unsigned short port)
}
- } else {
+ } else if (family == AF_INET6) {
#ifdef DISABLE_IPV6
log_server_error("ipv6 support disabled\n");
@@ -166,11 +177,23 @@ int socket_bind(int socket, int family, const char *addr, unsigned short port)
}
#endif /* IPV6_V6ONLY */
#endif /* DISABLE_IPV6 */
+ } else if (family == AF_UNIX) {
+ paddr = (struct sockaddr*)&uaddr;
+ addrlen = sizeof(struct sockaddr_un);
+
+ /* Prepare AF_UNIX sockaddr struct. */
+ memset(&uaddr, 0, sizeof(struct sockaddr_un));
+ uaddr.sun_family = AF_UNIX;
+ strncpy(uaddr.sun_path, addr, sizeof(uaddr.sun_path) - 1);
+
+ /* Unlink existing socket. */
+ unlink(addr);
+ } else {
+ assert(0); /* Shouldn't be supported. */
}
/* Reuse old address if taken. */
- ret = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR,
- &flag, sizeof(flag));
+ ret = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
if (ret < 0) {
return KNOT_EINVAL;
}
@@ -178,8 +201,7 @@ int socket_bind(int socket, int family, const char *addr, unsigned short port)
/* Bind to specified address. */
int res = bind(socket, paddr, addrlen);
if (res < 0) {
- log_server_error("Cannot bind to socket (errno %d).\n",
- errno);
+ log_server_error("Cannot bind to socket (errno %d).\n", errno);
return knot_map_errno(EADDRINUSE, EINVAL, EACCES, ENOMEM);
}
diff --git a/src/knot/server/socket.h b/src/knot/server/socket.h
index 153b066..1849f1d 100644
--- a/src/knot/server/socket.h
+++ b/src/knot/server/socket.h
@@ -55,12 +55,13 @@ typedef enum {
* \retval KNOT_EACCES process does not have appropriate privileges.
* \retval KNOT_ERROR unspecified error.
*/
-int socket_create(int family, int type);
+int socket_create(int family, int type, int proto);
/*!
* \brief Connect to remote host.
*
* \param fd Socket filedescriptor.
+ * \param family Socket family.
* \param addr Requested address.
* \param port Requested port.
*
@@ -73,7 +74,7 @@ int socket_create(int family, int type);
* \retval KNOT_EISCONN already connected.
* \retval KNOT_ERROR unspecified error.
*/
-int socket_connect(int fd, const char *addr, unsigned short port);
+int socket_connect(int fd, int family, const char *addr, unsigned short port);
/*!
* \brief Listen on given socket.
diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index 8f3a324..f8fe90b 100644
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -32,7 +32,7 @@
#include "common/sockaddr.h"
#include "common/skip-list.h"
#include "common/fdset.h"
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/server/tcp-handler.h"
#include "knot/server/xfr-handler.h"
#include "knot/server/zones.h"
@@ -45,7 +45,7 @@
/*! \brief TCP worker data. */
typedef struct tcp_worker_t {
iohandler_t *ioh; /*!< Shortcut to I/O handler. */
- fdset_t *fdset; /*!< File descriptor set. */
+ fdset_t *fdset; /*!< File descriptor set. */
int pipe[2]; /*!< Master-worker signalization pipes. */
} tcp_worker_t;
@@ -58,19 +58,7 @@ typedef struct tcp_worker_t {
/*! \brief Calculate TCP throttle time (random). */
static inline int tcp_throttle() {
//(TCP_THROTTLE_LO + (int)(tls_rand() * TCP_THROTTLE_HI));
- return (rand() % TCP_THROTTLE_HI) + TCP_THROTTLE_LO;
-}
-
-/*! \brief Wrapper for TCP send. */
-static int xfr_send_cb(int session, sockaddr_t *addr, uint8_t *msg, size_t msglen)
-{
- UNUSED(addr);
- int ret = tcp_send(session, msg, msglen);
- if (ret < 0) {
- return KNOT_ECONN;
- }
-
- return ret;
+ return (rand() % TCP_THROTTLE_HI) + TCP_THROTTLE_LO;
}
/*! \brief Send reply. */
@@ -90,7 +78,7 @@ static int tcp_reply(int fd, uint8_t *qbuf, size_t resp_len)
"socket_send()",
res, errno);
}
-
+
return res;
}
@@ -98,7 +86,7 @@ static int tcp_reply(int fd, uint8_t *qbuf, size_t resp_len)
static void tcp_sweep(fdset_t *set, int fd, void* data)
{
UNUSED(data);
-
+
char r_addr[SOCKADDR_STRLEN] = { '\0' };
int r_port = 0;
struct sockaddr_storage addr;
@@ -120,7 +108,7 @@ static void tcp_sweep(fdset_t *set, int fd, void* data)
inet_ntop(AF_INET6, &s->sin6_addr, r_addr, sizeof(r_addr));
#endif
}
-
+
log_server_notice("Connection with '%s@%d' was terminated due to "
"inactivity.\n", r_addr, r_port);
fdset_remove(set, fd);
@@ -148,7 +136,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
dbg_net("tcp: tcp_handle(%p, %d) - invalid parameters\n", w, fd);
return KNOT_EINVAL;
}
-
+
dbg_net("tcp: handling TCP event on fd=%d in thread %p.\n",
fd, (void*)pthread_self());
@@ -156,12 +144,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
/* Check address type. */
sockaddr_t addr;
- if (sockaddr_init(&addr, w->ioh->type) != KNOT_EOK) {
- log_server_error("Socket type %d is not supported, "
- "IPv6 support is probably disabled.\n",
- w->ioh->type);
- return KNOT_EINVAL;
- }
+ sockaddr_prep(&addr);
/* Receive data. */
int n = tcp_recv(fd, qbuf, qbuf_maxlen, &addr);
@@ -183,8 +166,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
/* Parse query. */
size_t resp_len = qbuf_maxlen; // 64K
knot_packet_type_t qtype = KNOT_QUERY_NORMAL;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
+ knot_packet_t *packet = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
if (packet == NULL) {
int ret = knot_ns_error_response_from_query_wire(ns, qbuf, n,
KNOT_RCODE_SERVFAIL,
@@ -213,7 +195,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
/* Handle query. */
int xfrt = -1;
- knot_ns_xfr_t xfr;
+ knot_ns_xfr_t *xfr = NULL;
int res = KNOT_ERROR;
switch(qtype) {
@@ -233,25 +215,25 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
} else {
xfrt = XFR_TYPE_AOUT;
}
-
- /* Prepare context. */
- res = xfr_request_init(&xfr, xfrt, XFR_FLAG_TCP, packet);
- if (res != KNOT_EOK) {
+
+ /* Answer from query. */
+ xfr = xfr_task_create(NULL, xfrt, XFR_FLAG_TCP);
+ if (xfr == NULL) {
knot_ns_error_response_from_query(ns, packet,
KNOT_RCODE_SERVFAIL,
qbuf, &resp_len);
res = KNOT_EOK;
break;
}
- xfr.send = xfr_send_cb;
- xfr.session = fd;
- xfr.wire = qbuf;
- xfr.wire_size = qbuf_maxlen;
- memcpy(&xfr.addr, &addr, sizeof(sockaddr_t));
-
- /* Answer. */
- return xfr_answer(ns, &xfr);
-
+ xfr->session = fd;
+ xfr->wire = qbuf;
+ xfr->wire_size = qbuf_maxlen;
+ xfr->query = packet;
+ xfr_task_setaddr(xfr, &addr, NULL);
+ res = xfr_answer(ns, xfr);
+ knot_packet_free(&packet);
+ return res;
+
case KNOT_QUERY_UPDATE:
// knot_ns_error_response_from_query(ns, packet,
// KNOT_RCODE_NOTIMPL,
@@ -260,12 +242,12 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
fd, NS_TRANSPORT_TCP);
// res = KNOT_EOK;
break;
-
+
case KNOT_QUERY_NOTIFY:
res = notify_process_request(ns, packet, &addr,
qbuf, &resp_len);
break;
-
+
/* Unhandled opcodes. */
case KNOT_RESPONSE_NOTIFY: /*!< Only in UDP. */
case KNOT_RESPONSE_NORMAL: /*!< TCP handler doesn't send queries. */
@@ -276,7 +258,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
qbuf, &resp_len);
res = KNOT_EOK;
break;
-
+
/* Unknown opcodes. */
default:
knot_ns_error_response_from_query(ns, packet,
@@ -320,7 +302,7 @@ int tcp_accept(int fd)
throttle);
sleep(throttle);
}
-
+
}
} else {
dbg_net("tcp: accepted connection fd=%d\n", incoming);
@@ -349,14 +331,14 @@ tcp_worker_t* tcp_worker_create()
dbg_net("tcp: out of memory when creating worker\n");
return NULL;
}
-
+
/* Create signal pipes. */
memset(w, 0, sizeof(tcp_worker_t));
if (pipe(w->pipe) < 0) {
free(w);
return NULL;
}
-
+
/* Create fdset. */
w->fdset = fdset_new();
if (!w->fdset) {
@@ -365,9 +347,9 @@ tcp_worker_t* tcp_worker_create()
free(w);
return NULL;
}
-
+
fdset_add(w->fdset, w->pipe[0], OS_EV_READ);
-
+
return w;
}
@@ -376,16 +358,27 @@ void tcp_worker_free(tcp_worker_t* w)
if (!w) {
return;
}
-
+
/* Destroy fdset. */
fdset_destroy(w->fdset);
-
+
/* Close pipe write end and worker. */
close(w->pipe[0]);
close(w->pipe[1]);
free(w);
}
+/* Free workers and associated data. */
+static void tcp_loop_free(void *data)
+{
+ tcp_worker_t **worker = (tcp_worker_t **)data;
+ iohandler_t *ioh = worker[0]->ioh;
+ for (unsigned i = 0; i < ioh->unit->size - 1; ++i)
+ tcp_worker_free(worker[i]);
+
+ free(worker);
+}
+
/*
* Public APIs.
*/
@@ -418,7 +411,9 @@ int tcp_send(int fd, uint8_t *msg, size_t msglen)
/* Uncork only if corked successfuly. */
if (uncork == 0) {
cork = 0;
- setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
+ if (setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork)) < 0) {
+ dbg_net("tcp: failed to uncork socket\n");
+ }
}
#endif
return sent;
@@ -451,11 +446,10 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr)
if (len < pktsize) {
return KNOT_ENOMEM;
}
-
+
/* Get peer name. */
if (addr) {
- socklen_t alen = addr->len;
- if (getpeername(fd, addr->ptr, &alen) < 0) {
+ if (getpeername(fd, (struct sockaddr *)addr, &addr->len) < 0) {
return KNOT_EMALF;
}
}
@@ -477,46 +471,72 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr)
int tcp_loop_master(dthread_t *thread)
{
- iohandler_t *handler = (iohandler_t *)thread->data;
- dt_unit_t *unit = thread->unit;
-
- /* Check socket. */
- if (!handler || handler->fd < 0 || handler->data == NULL) {
- dbg_net("tcp: failed to initialize master thread\n");
+ if (!thread || !thread->data) {
return KNOT_EINVAL;
}
-
- tcp_worker_t **workers = handler->data;
+
+ iostate_t *st = (iostate_t *)thread->data;
+ iohandler_t *h = st->h;
+ dt_unit_t *unit = thread->unit;
+ tcp_worker_t **workers = h->data;
+
+ /* Prepare structures for bound sockets. */
+ fdset_it_t it;
+ fdset_t *fds = NULL;
+ ref_t *ref = NULL;
+ int if_cnt = 0;
/* Accept connections. */
int id = 0;
dbg_net("tcp: created 1 master with %d workers, backend is '%s' \n",
unit->size - 1, fdset_method());
- while(1) {
+ for(;;) {
+
+ /* Check handler state. */
+ if (knot_unlikely(st->s & ServerReload)) {
+ st->s &= ~ServerReload;
+ ref_release(ref);
+ ref = server_set_ifaces(h->server, &fds, &if_cnt, IO_TCP);
+ if (if_cnt == 0) break;
+ }
+
/* Check for cancellation. */
if (dt_is_cancelled(thread)) {
break;
}
- /* Accept client. */
- int client = tcp_accept(handler->fd);
- if (client < 0) {
- continue;
+ /* Wait for events. */
+ int nfds = fdset_wait(fds, OS_EV_FOREVER);
+ if (nfds <= 0) {
+ if (errno == EINTR) continue;
+ break;
}
- /* Add to worker in RR fashion. */
- if (write(workers[id]->pipe[1], &client, sizeof(int)) < 0) {
- dbg_net("tcp: failed to register fd=%d to worker=%d\n",
- client, id);
- close(client);
- continue;
+ fdset_begin(fds, &it);
+ while(nfds > 0) {
+ /* Accept client. */
+ int client = tcp_accept(it.fd);
+ if (client > -1) {
+ /* Add to worker in RR fashion. */
+ if (write(workers[id]->pipe[1], &client, sizeof(int)) < 0) {
+ dbg_net("tcp: failed to register fd=%d to worker=%d\n",
+ client, id);
+ close(client);
+ continue;
+ }
+ id = get_next_rr(id, unit->size - 1);
+ }
+
+ if (fdset_next(fds, &it) != 0) {
+ break;
+ }
}
- id = get_next_rr(id, unit->size - 1);
}
dbg_net("tcp: master thread finished\n");
- free(workers);
-
+ fdset_destroy(fds);
+ ref_release(ref);
+
return KNOT_EOK;
}
@@ -526,14 +546,14 @@ int tcp_loop_worker(dthread_t *thread)
if (!w) {
return KNOT_EINVAL;
}
-
+
/* Allocate buffer for requests. */
uint8_t *qbuf = malloc(TCP_BUFFER_SIZE);
if (qbuf == NULL) {
dbg_net("tcp: failed to allocate buffers for TCP worker\n");
return KNOT_EINVAL;
}
-
+
/* Drop all capabilities on workers. */
#ifdef HAVE_CAP_NG_H
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
@@ -541,7 +561,7 @@ int tcp_loop_worker(dthread_t *thread)
capng_apply(CAPNG_SELECT_BOTH);
}
#endif /* HAVE_CAP_NG_H */
-
+
/* Next sweep time. */
timev_t next_sweep;
time_now(&next_sweep);
@@ -561,7 +581,7 @@ int tcp_loop_worker(dthread_t *thread)
if (nfds < 0) {
continue;
}
-
+
/* Establish timeouts. */
rcu_read_lock();
int max_idle = conf()->max_conn_idle;
@@ -574,7 +594,7 @@ int tcp_loop_worker(dthread_t *thread)
fdset_it_t it;
fdset_begin(w->fdset, &it);
while(nfds > 0) {
-
+
/* Handle incoming clients. */
if (it.fd == w->pipe[0]) {
int client = 0;
@@ -586,8 +606,7 @@ int tcp_loop_worker(dthread_t *thread)
"client %d\n",
w, client);
fdset_add(w->fdset, client, OS_EV_READ);
- fdset_set_watchdog(w->fdset, client,
- max_hs);
+ fdset_set_watchdog(w->fdset, client, max_hs);
dbg_net("tcp: watchdog for fd=%d set to %ds\n",
client, max_hs);
} else {
@@ -607,15 +626,15 @@ int tcp_loop_worker(dthread_t *thread)
close(it.fd);
break;
}
-
+
}
-
+
/* Check if next exists. */
if (fdset_next(w->fdset, &it) != 0) {
break;
}
}
-
+
/* Sweep inactive. */
timev_t now;
if (time_now(&now) == 0) {
@@ -630,7 +649,6 @@ int tcp_loop_worker(dthread_t *thread)
/* Stop whole unit. */
free(qbuf);
dbg_net_verb("tcp: worker %p finished\n", w);
- tcp_worker_free(w);
return KNOT_EOK;
}
@@ -639,7 +657,7 @@ int tcp_loop_unit(iohandler_t *ioh, dt_unit_t *unit)
if (unit->size < 1) {
return KNOT_EINVAL;
}
-
+
/* Create unit data. */
tcp_worker_t **workers = malloc((unit->size - 1) *
sizeof(tcp_worker_t *));
@@ -658,28 +676,31 @@ int tcp_loop_unit(iohandler_t *ioh, dt_unit_t *unit)
workers[i]->ioh = ioh;
++allocated;
}
-
+
/* Check allocated workers. */
if (allocated != unit->size - 1) {
for (unsigned i = 0; i < allocated; ++i) {
tcp_worker_free(workers[i]);
}
-
+
free(workers);
dbg_net("tcp: cannot create workers\n");
return KNOT_EINVAL;
}
-
+
/* Store worker data. */
ioh->data = workers;
-
+
/* Repurpose workers. */
for (unsigned i = 0; i < allocated; ++i) {
dt_repurpose(unit->threads[i + 1], tcp_loop_worker, workers[i]);
}
/* Repurpose first thread as master (unit controller). */
- dt_repurpose(unit->threads[0], tcp_loop_master, ioh);
+ dt_repurpose(unit->threads[0], tcp_loop_master, ioh->state + 0);
+
+ /* Create data destructor. */
+ ioh->dtor = tcp_loop_free;
return KNOT_EOK;
}
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index 7b5e701..259ac5a 100644
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -14,30 +14,33 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE /* Required for RTLD_DEFAULT. */
-#endif
-
-#include <dlfcn.h>
#include <config.h>
+#include <dlfcn.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/poll.h>
#include <sys/syscall.h>
-#include <netinet/in.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
+#include <limits.h>
+#include <sys/param.h>
+#ifdef HAVE_SYS_UIO_H /* 'struct iovec' for OpenBSD */
+#include <sys/uio.h>
+#endif /* HAVE_SYS_UIO_H */
#ifdef HAVE_CAP_NG_H
#include <cap-ng.h>
#endif /* HAVE_CAP_NG_H */
#include "common/sockaddr.h"
-#include "knot/common.h"
+#include "common/mempattern.h"
+#include "common/mempool.h"
+#include "knot/knot.h"
#include "knot/server/udp-handler.h"
#include "libknot/nameserver/name-server.h"
#include "knot/stat/stat.h"
@@ -48,28 +51,55 @@
#include "knot/server/zones.h"
#include "knot/server/notify.h"
-/* Check for sendmmsg syscall. */
-#ifdef HAVE_SENDMMSG
- #define ENABLE_SENDMMSG 1
+/* FD_COPY macro compat. */
+#ifndef FD_COPY
+#define FD_COPY(src, dest) memcpy((dest), (src), sizeof(fd_set))
+#endif
+
+/* Mirror mode (no answering). */
+/* #define MIRROR_MODE 1 */
+
+/* PPS measurement. */
+/* #define MEASURE_PPS 1 */
+
+/* PPS measurement */
+#ifdef MEASURE_PPS
+
+/* Not thread-safe, used only for RX thread. */
+static struct timeval __pps_t0, __pps_t1;
+volatile static unsigned __pps_rx = 0;
+static inline void udp_pps_begin()
+{
+ gettimeofday(&__pps_t0, NULL);
+}
+
+static inline void udp_pps_sample(unsigned n, unsigned thr_id)
+{
+ __pps_rx += n;
+ if (thr_id == 0) {
+ gettimeofday(&__pps_t1, NULL);
+ if (time_diff(&__pps_t0, &__pps_t1) >= 1000.0) {
+ unsigned pps = __pps_rx;
+ memcpy(&__pps_t0, &__pps_t1, sizeof(struct timeval));
+ __pps_rx = 0;
+ log_server_info("RX rate %u p/s.\n", pps);
+ }
+ }
+}
#else
- #ifdef SYS_sendmmsg
- #define ENABLE_SENDMMSG 1
- #endif
+static inline void udp_pps_begin() {}
+static inline void udp_pps_sample(unsigned n, unsigned thr_id) {}
#endif
-/* UDP request struct. */
-struct udp_req_t {
- sockaddr_t *addr;
- uint8_t *qbuf;
- size_t qbuflen;
- size_t *resplen;
- rrl_table_t *rrl;
+
+/* Answering context. */
+struct answer_ctx
+{
+ server_t *srv;
+ mm_ctx_t *mm;
unsigned slip;
};
-/*! \brief Pointer to selected UDP master implementation. */
-static int (*_udp_master)(dthread_t *, stat_t *) = 0;
-
/*! \brief RRL reject procedure. */
static size_t udp_rrl_reject(const knot_nameserver_t *ns,
const knot_packet_t *packet,
@@ -89,72 +119,55 @@ static size_t udp_rrl_reject(const knot_nameserver_t *ns,
knot_wire_set_tc(resp); /* Set TC=1 */
break;
}
-
+
*slip = 0; /* Restart SLIP interval. */
return rlen;
}
-
+
return 0; /* Discard response. */
}
-int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
- sockaddr_t* addr, knot_nameserver_t *ns, rrl_table_t *rrl, unsigned *slip)
+int udp_handle(struct answer_ctx *ans, int fd,
+ uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
+ sockaddr_t* addr)
{
#ifdef DEBUG_ENABLE_BRIEF
char strfrom[SOCKADDR_STRLEN];
memset(strfrom, 0, sizeof(strfrom));
sockaddr_tostr(addr, strfrom, sizeof(strfrom));
- dbg_net("udp: fd=%d received %zd bytes from '%s@%d'.\n", fd, qbuflen,
+ dbg_net("udp: received %zd bytes from '%s@%d'.\n", qbuflen,
strfrom, sockaddr_portnum(addr));
#endif
-
- knot_packet_type_t qtype = KNOT_QUERY_NORMAL;
+
+ int res = KNOT_EOK;
+ int rcode = KNOT_RCODE_NOERROR;
+ knot_nameserver_t *ns = ans->srv->nameserver;
+ rrl_table_t *rrl = ans->srv->rrl;
+ knot_packet_type_t qtype = KNOT_QUERY_INVALID;
*resp_len = SOCKET_MTU_SZ;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
- if (packet == NULL) {
- dbg_net("udp: failed to create packet on fd=%d\n", fd);
+#ifdef MIRROR_MODE
+ knot_wire_set_qr(qbuf);
+ *resp_len = qbuflen;
+ return KNOT_EOK;
+#endif
+ knot_packet_t *packet = knot_packet_new_mm(KNOT_PACKET_PREALLOC_QUERY, ans->mm);
+ if (packet == NULL) {
+ dbg_net("udp: failed to create packet\n");
int ret = knot_ns_error_response_from_query_wire(ns, qbuf, qbuflen,
KNOT_RCODE_SERVFAIL,
qbuf, resp_len);
-
- if (ret != KNOT_EOK) {
- return KNOT_EMALF;
- }
-
- return KNOT_EOK; /* Created error response. */
+ return ret;
}
-
- /* Prepare RRL structs. */
- rrl_req_t rrl_rq;
- memset(&rrl_rq, 0, sizeof(rrl_req_t));
- rrl_rq.w = qbuf; /* Wire */
-
+
/* Parse query. */
- int res = knot_ns_parse_packet(qbuf, qbuflen, packet, &qtype);
- if (rrl) rrl_rq.qst = &packet->question;
- if (knot_unlikely(res != KNOT_EOK)) {
- dbg_net("udp: failed to parse packet on fd=%d\n", fd);
- if (res > 0) { /* Returned RCODE */
- res = knot_ns_error_response_from_query(
- ns, packet, res, qbuf, resp_len);
- if (res != KNOT_EOK) {
- knot_packet_free(&packet);
- return KNOT_EMALF;
- }
- } else {
- res = knot_ns_error_response_from_query_wire(
- ns, qbuf, qbuflen, KNOT_RCODE_SERVFAIL, qbuf,
- resp_len);
- if (res != KNOT_EOK) {
- knot_packet_free(&packet);
- return res;
- }
- }
+ rcode = knot_ns_parse_packet(qbuf, qbuflen, packet, &qtype);
+ if (rcode < KNOT_RCODE_NOERROR) {
+ dbg_net("udp: failed to parse packet\n");
+ rcode = KNOT_RCODE_SERVFAIL;
}
-
+
/* Handle query. */
switch(qtype) {
case KNOT_QUERY_NORMAL:
@@ -164,210 +177,189 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
case KNOT_QUERY_AXFR:
/* RFC1034, p.28 requires reliable transfer protocol.
* Bind responds with FORMERR.
- */
- knot_ns_error_response_from_query(ns, packet,
- KNOT_RCODE_FORMERR, qbuf,
- resp_len);
- res = KNOT_EOK;
+ */
+ res = knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_FORMERR, qbuf,
+ resp_len);
break;
case KNOT_QUERY_IXFR:
/* According to RFC1035, respond with SOA. */
res = zones_normal_query_answer(ns, packet, addr,
- qbuf, resp_len,
+ qbuf, resp_len,
NS_TRANSPORT_UDP);
break;
case KNOT_QUERY_NOTIFY:
res = notify_process_request(ns, packet, addr,
qbuf, resp_len);
break;
-
+
case KNOT_QUERY_UPDATE:
res = zones_process_update(ns, packet, addr, qbuf, resp_len,
fd, NS_TRANSPORT_UDP);
break;
-
- /* Unhandled opcodes. */
+
+ /* Do not issue response to incoming response to avoid loops. */
case KNOT_RESPONSE_AXFR: /*!< Processed in XFR handler. */
case KNOT_RESPONSE_IXFR: /*!< Processed in XFR handler. */
- knot_ns_error_response_from_query(ns, packet,
- KNOT_RCODE_REFUSED, qbuf,
- resp_len);
+ case KNOT_RESPONSE_NORMAL:
+ case KNOT_RESPONSE_NOTIFY:
+ case KNOT_RESPONSE_UPDATE:
res = KNOT_EOK;
+ *resp_len = 0;
break;
-
/* Unknown opcodes */
default:
- knot_ns_error_response_from_query(ns, packet,
- KNOT_RCODE_FORMERR, qbuf,
- resp_len);
- res = KNOT_EOK;
+ res = knot_ns_error_response_from_query(ns, packet,
+ rcode, qbuf,
+ resp_len);
break;
}
-
+
/* Process RRL. */
- if (rrl) {
+ if (knot_unlikely(rrl != NULL)) {
+ rrl_req_t rrl_rq;
+ memset(&rrl_rq, 0, sizeof(rrl_req_t));
+ rrl_rq.w = qbuf; /* Wire */
+ rrl_rq.qst = &packet->question;
+
rcu_read_lock();
rrl_rq.flags = packet->flags;
if (rrl_query(rrl, addr, &rrl_rq, packet->zone) != KNOT_EOK) {
*resp_len = udp_rrl_reject(ns, packet, qbuf,
SOCKET_MTU_SZ,
knot_wire_get_rcode(qbuf),
- slip);
+ &ans->slip);
}
rcu_read_unlock();
}
-
+
knot_packet_free(&packet);
return res;
}
-static inline int udp_master_recvfrom(dthread_t *thread, stat_t *thread_stat)
-{
- iohandler_t *h = (iohandler_t *)thread->data;
- if (h == NULL || h->server == NULL || h->server->nameserver == NULL) {
- dbg_net("udp: invalid parameters for udp_master_recvfrom\n");
- return KNOT_EINVAL;
- }
-
- /* Set CPU affinity to improve load distribution on multicore systems.
- * Partial overlapping mask to be nice to scheduler.
- */
- int cpcount = dt_online_cpus();
- if (cpcount > 0) {
- unsigned cpu[2];
- cpu[0] = dt_get_id(thread);
- cpu[1] = (cpu[0] + 1) % cpcount;
- cpu[0] = cpu[0] % cpcount;
- dt_setaffinity(thread, cpu, 2);
- }
-
- knot_nameserver_t *ns = h->server->nameserver;
+/* Check for sendmmsg syscall. */
+#ifdef HAVE_SENDMMSG
+ #define ENABLE_SENDMMSG 1
+#else
+ #ifdef SYS_sendmmsg
+ #define ENABLE_SENDMMSG 1
+ #endif
+#endif
- /* Initialize remote party address. */
+/*! \brief Pointer to selected UDP master implementation. */
+static void* (*_udp_init)(void) = 0;
+static int (*_udp_deinit)(void *) = 0;
+static int (*_udp_recv)(int, void *) = 0;
+static int (*_udp_handle)(struct answer_ctx *, void *) = 0;
+static int (*_udp_send)(void *) = 0;
+
+/* UDP recvfrom() request struct. */
+struct udp_recvfrom {
+ int fd;
sockaddr_t addr;
- if (sockaddr_init(&addr, h->type) != KNOT_EOK) {
- log_server_error("Socket type %d is not supported, "
- "IPv6 support is probably disabled.\n",
- h->type);
- return KNOT_ENOTSUP;
- }
-
- /* Allocate buffer for answering. */
- uint8_t *qbuf = malloc(SOCKET_MTU_SZ);
- if (qbuf == NULL) {
- dbg_net("udp: out of memory when allocating buffer.\n");
- return KNOT_ENOMEM;
- }
-
- /* Duplicate socket for performance reasons on some OS's */
- int sock = h->fd;
- int sock_dup = dup(h->fd);
- if (sock_dup < 0) {
- log_server_warning("Couldn't duplicate UDP socket for listening.\n");
- } else {
- sock = sock_dup;
- }
-
- /* Initialize RRL if configured. */
- unsigned rrl_slip = 0;
- rrl_table_t *rrl = h->server->rrl;
-
- /* Loop until all data is read. */
- ssize_t n = 0;
- while (n >= 0) {
-
- /* Receive packet. */
- n = recvfrom(sock, qbuf, SOCKET_MTU_SZ, 0, addr.ptr, &addr.len);
+ struct msghdr msg;
+ struct iovec iov;
+ uint8_t buf[SOCKET_MTU_SZ];
+ size_t buflen;
+};
- /* Cancellation point. */
- if (dt_is_cancelled(thread)) {
- break;
- }
+static void *udp_recvfrom_init(void)
+{
+ struct udp_recvfrom *rq = malloc(sizeof(struct udp_recvfrom));
+ if (rq) {
+ sockaddr_prep(&rq->addr);
+ rq->buflen = SOCKET_MTU_SZ;
+ rq->iov.iov_base = rq->buf;
+ rq->iov.iov_len = rq->buflen;
+ rq->msg.msg_name = &rq->addr;
+ rq->msg.msg_namelen = rq->addr.len;
+ rq->msg.msg_iov = &rq->iov;
+ rq->msg.msg_iovlen = 1;
+ rq->msg.msg_control = NULL;
+ rq->msg.msg_controllen = 0;
+ }
+ return rq;
+}
- /* Error and interrupt handling. */
- if (knot_unlikely(n <= 0)) {
- if (errno != EINTR && errno != 0) {
- dbg_net("udp: recvmsg() failed: %d\n",
- errno);
- }
+static int udp_recvfrom_deinit(void *d)
+{
+ struct udp_recvfrom *rq = (struct udp_recvfrom *)d;
+ free(rq);
+ return 0;
+}
- if (!(h->state & ServerRunning)) {
- break;
- } else {
- continue;
- }
- }
+static int udp_recvfrom_recv(int fd, void *d)
+{
+ struct udp_recvfrom *rq = (struct udp_recvfrom *)d;
+ int ret = recvmsg(fd, &rq->msg, MSG_DONTWAIT);
+ if (ret > 0) {
+ rq->fd = fd;
+ rq->buflen = ret;
+ return 1;
+ }
- /* Handle received pkt. */
- size_t resp_len = 0;
- int rc = udp_handle(sock, qbuf, n, &resp_len, &addr, ns,
- rrl, &rrl_slip);
+ return 0;
+}
- /* Send response. */
- if (rc == KNOT_EOK && resp_len > 0) {
+static int udp_recvfrom_handle(struct answer_ctx *ans, void *d)
+{
+ struct udp_recvfrom *rq = (struct udp_recvfrom *)d;
- dbg_net("udp: on fd=%d, sending answer size=%zd.\n",
- sock, resp_len);
+ /* Process received pkt. */
+ rq->addr.len = rq->msg.msg_namelen;
+ int ret = udp_handle(ans, rq->fd,
+ rq->buf, rq->buflen, &rq->iov.iov_len,
+ &rq->addr);
+ if (ret != KNOT_EOK) {
+ rq->iov.iov_len = 0;
+ }
- // Send datagram
- rc = sendto(sock, qbuf, resp_len,
- 0, addr.ptr, addr.len);
+ return ret;
+}
- // Check result
- if (rc != (int)resp_len) {
- dbg_net("udp: sendto(): failed: %d - %d.\n",
- rc, errno);
- }
- }
+static int udp_recvfrom_send(void *d)
+{
+ struct udp_recvfrom *rq = (struct udp_recvfrom *)d;
+ int rc = 0;
+ if (rq->iov.iov_len > 0) {
+ rc = sendmsg(rq->fd, &rq->msg, 0);
}
- /* Free allocd resources. */
- if (sock_dup >= 0) {
- close(sock_dup);
+ /* Reset buffer size and address len. */
+ rq->iov.iov_len = SOCKET_MTU_SZ;
+ sockaddr_prep(&rq->addr);
+ rq->msg.msg_namelen = rq->addr.len;
+
+ /* Return number of packets sent. */
+ if (rc > 1) {
+ return 1;
}
-
- free(qbuf);
- return KNOT_EOK;
+ return 0;
}
#ifdef ENABLE_RECVMMSG
-#ifdef MSG_WAITFORONE
/*! \brief Pointer to selected UDP send implementation. */
static int (*_send_mmsg)(int, sockaddr_t *, struct mmsghdr *, size_t) = 0;
/*!
* \brief Send multiple packets.
- *
- * Basic, sendto() based implementation.
+ *
+ * Basic, sendmsg() based implementation.
*/
-int udp_sendto(int sock, sockaddr_t * addrs, struct mmsghdr *msgs, size_t count)
+int udp_sendmsg(int sock, sockaddr_t * addrs, struct mmsghdr *msgs, size_t count)
{
+ int sent = 0;
for (unsigned i = 0; i < count; ++i) {
-
- const size_t resp_len = msgs[i].msg_len;
- if (resp_len > 0) {
- dbg_net("udp: on fd=%d, sending answer size=%zd.\n",
- sock, resp_len);
-
- // Send datagram
- sockaddr_t *addr = addrs + i;
- struct iovec *cvec = msgs[i].msg_hdr.msg_iov;
- int res = sendto(sock, cvec->iov_base, resp_len,
- 0, addr->ptr, addr->len);
-
- // Check result
- if (res != (int)resp_len) {
- dbg_net("udp: sendto(): failed: %d - %d.\n",
- res, errno);
- }
+ if (sendmsg(sock, &msgs[i].msg_hdr, 0) > 0) {
+ ++sent;
}
}
-
- return KNOT_EOK;
+
+ return sent;
}
#ifdef ENABLE_SENDMMSG
@@ -382,236 +374,261 @@ static inline int sendmmsg(int fd, struct mmsghdr *mmsg, unsigned vlen,
/*!
* \brief Send multiple packets.
- *
+ *
* sendmmsg() implementation.
*/
int udp_sendmmsg(int sock, sockaddr_t *_, struct mmsghdr *msgs, size_t count)
{
UNUSED(_);
- dbg_net("udp: sending multiple responses\n");
- if (sendmmsg(sock, msgs, count, 0) < 0) {
- return KNOT_ERROR;
- }
-
- return KNOT_EOK;
+ return sendmmsg(sock, msgs, count, 0);
}
#endif
-static inline int udp_master_recvmmsg(dthread_t *thread, stat_t *thread_stat)
+/* UDP recvmmsg() request struct. */
+struct udp_recvmmsg {
+ int fd;
+ char *iobuf;
+ sockaddr_t *addrs;
+ struct iovec *iov;
+ struct mmsghdr *msgs;
+ unsigned rcvd;
+};
+
+static void *udp_recvmmsg_init(void)
{
- iohandler_t *h = (iohandler_t *)thread->data;
- knot_nameserver_t *ns = h->server->nameserver;
- int sock = dup(h->fd);
-
- /* Check socket. */
- if (sock < 0) {
- dbg_net("udp: unable to dup() socket, finishing.\n");
- return KNOT_EINVAL;
+ struct udp_recvmmsg *rq = malloc(sizeof(struct udp_recvmmsg));
+ if (rq) {
+ rq->iobuf = malloc(SOCKET_MTU_SZ * RECVMMSG_BATCHLEN);
+ rq->addrs = malloc(sizeof(sockaddr_t) * RECVMMSG_BATCHLEN);
+ rq->iov = malloc(sizeof(struct iovec) * RECVMMSG_BATCHLEN);
+ rq->msgs = malloc(sizeof(struct mmsghdr) * RECVMMSG_BATCHLEN);
+ if (!rq->iobuf || !rq->addrs || !rq->iov || !rq->msgs) {
+ free(rq->iobuf);
+ free(rq->addrs);
+ free(rq->iov);
+ free(rq->msgs);
+ free(rq);
+ return NULL;
+ }
+ memset(rq->msgs, 0, sizeof(struct mmsghdr) * RECVMMSG_BATCHLEN);
+ for (unsigned i = 0; i < RECVMMSG_BATCHLEN; ++i) {
+ sockaddr_prep(rq->addrs + i);
+ rq->iov[i].iov_base = rq->iobuf + i * SOCKET_MTU_SZ;
+ rq->iov[i].iov_len = SOCKET_MTU_SZ;
+ rq->msgs[i].msg_hdr.msg_iov = rq->iov + i;
+ rq->msgs[i].msg_hdr.msg_iovlen = 1;
+ rq->msgs[i].msg_hdr.msg_name = rq->addrs + i;
+ rq->msgs[i].msg_hdr.msg_namelen = rq->addrs[i].len;
+ }
}
+ return rq;
+}
- /* Allocate batch for N packets. */
- char *iobuf = malloc(SOCKET_MTU_SZ * RECVMMSG_BATCHLEN);
- sockaddr_t *addrs = malloc(sizeof(sockaddr_t) * RECVMMSG_BATCHLEN);
- struct iovec *iov = malloc(sizeof(struct iovec) * RECVMMSG_BATCHLEN);
- struct mmsghdr *msgs = malloc(sizeof(struct mmsghdr) * RECVMMSG_BATCHLEN);
-
- /* Check, free(NULL) is valid, so no need to nitpick. */
- if (iobuf == NULL || addrs == NULL || iov == NULL || msgs == NULL) {
- free(iobuf);
- free(addrs);
- free(iov);
- free(msgs);
- close(sock);
- return KNOT_ENOMEM;
+static int udp_recvmmsg_deinit(void *d)
+{
+ struct udp_recvmmsg *rq = (struct udp_recvmmsg *)d;
+ if (rq) {
+ free(rq->iobuf);
+ free(rq->addrs);
+ free(rq->iov);
+ free(rq->msgs);
+ free(rq);
}
+ return 0;
+}
- /* Prepare batch. */
- memset(msgs, 0, sizeof(struct mmsghdr) * RECVMMSG_BATCHLEN);
- for (unsigned i = 0; i < RECVMMSG_BATCHLEN; ++i) {
- sockaddr_init(addrs + i, h->type);
- iov[i].iov_base = iobuf + i * SOCKET_MTU_SZ;
- iov[i].iov_len = SOCKET_MTU_SZ;
- msgs[i].msg_hdr.msg_iov = iov + i;
- msgs[i].msg_hdr.msg_iovlen = 1;
- msgs[i].msg_hdr.msg_name = addrs[i].ptr;
- msgs[i].msg_hdr.msg_namelen = addrs[i].len;
- }
-
- /* Set CPU affinity to improve load distribution on multicore systems.
- * Partial overlapping mask to be nice to scheduler.
- */
- int cpcount = dt_online_cpus();
- if (cpcount > 0) {
- unsigned cpu[2];
- cpu[0] = dt_get_id(thread);
- cpu[1] = (cpu[0] + 1) % cpcount;
- cpu[0] = cpu[0] % cpcount;
- dt_setaffinity(thread, cpu, 2);
+static int udp_recvmmsg_recv(int fd, void *d)
+{
+ struct udp_recvmmsg *rq = (struct udp_recvmmsg *)d;
+ int n = recvmmsg(fd, rq->msgs, RECVMMSG_BATCHLEN, MSG_DONTWAIT, NULL);
+ if (n > 0) {
+ rq->fd = fd;
+ rq->rcvd = n;
}
-
- /* Initialize RRL if configured. */
- unsigned rrl_slip = 0;
- rrl_table_t *rrl = h->server->rrl;
-
- /* Loop until all data is read. */
- ssize_t n = 0;
- while (n >= 0) {
-
- /* Receive multiple messages. */
- n = recvmmsg(sock, msgs, RECVMMSG_BATCHLEN, MSG_WAITFORONE, 0);
-
- /* Cancellation point. */
- if (dt_is_cancelled(thread)) {
- break;
- }
-
- /* Error and interrupt handling. */
- if (knot_unlikely(n <= 0)) {
- if (errno != EINTR && errno != 0 && n < 0) {
- log_server_error("I/O failure in UDP - errno %d "
- "(Linux/recvmmsg)", errno);
- dbg_net("udp: recvmmsg() failed: %d\n",
- errno);
- }
-
- if (!(h->state & ServerRunning)) {
- break;
- } else {
- continue;
- }
- }
-
- /* Handle each received msg. */
- int ret = 0;
- for (unsigned i = 0; i < n; ++i) {
- struct iovec *cvec = msgs[i].msg_hdr.msg_iov;
- size_t resp_len = msgs[i].msg_len;
- ret = udp_handle(sock, cvec->iov_base, resp_len, &resp_len,
- addrs + i, ns, rrl, &rrl_slip);
- if (ret == KNOT_EOK) {
- msgs[i].msg_len = resp_len;
- iov[i].iov_len = resp_len;
- } else {
- msgs[i].msg_len = 0;
- iov[i].iov_len = 0;
- }
-
- }
+ return n;
+}
- /* Gather results. */
- _send_mmsg(sock, addrs, msgs, n);
-
- /* Reset iov buffer size. */
- for (unsigned i = 0; i < n; ++i) {
- iov[i].iov_len = SOCKET_MTU_SZ;
+static int udp_recvmmsg_handle(struct answer_ctx *st, void *d)
+{
+ struct udp_recvmmsg *rq = (struct udp_recvmmsg *)d;
+
+ /* Handle each received msg. */
+ int ret = 0;
+ for (unsigned i = 0; i < rq->rcvd; ++i) {
+ struct iovec *cvec = rq->msgs[i].msg_hdr.msg_iov;
+ size_t rlen = 0;
+ rq->addrs[i].len = rq->msgs[i].msg_hdr.msg_namelen;
+ ret = udp_handle(st, rq->fd, cvec->iov_base,
+ rq->msgs[i].msg_len, &rlen,
+ rq->addrs + i);
+ if (ret != KNOT_EOK) { /* Do not send. */
+ rlen = 0;
}
+ cvec->iov_len = rlen;
}
-
- /* Free allocd resources. */
- free(iobuf);
- free(addrs);
- free(iov);
- free(msgs);
- close(sock);
return KNOT_EOK;
}
-#endif
+
+static int udp_recvmmsg_send(void *d)
+{
+ struct udp_recvmmsg *rq = (struct udp_recvmmsg *)d;
+ int rc = _send_mmsg(rq->fd, rq->addrs, rq->msgs, rq->rcvd);
+ for (unsigned i = 0; i < rq->rcvd; ++i) {
+ /* Reset buffer size and address len. */
+ struct iovec *cvec = rq->msgs[i].msg_hdr.msg_iov;
+ cvec->iov_len = SOCKET_MTU_SZ;
+
+ sockaddr_prep(rq->addrs + i);
+ rq->msgs[i].msg_hdr.msg_namelen = rq->addrs[i].len;
+ }
+ return rc;
+}
#endif
/*! \brief Initialize UDP master routine on run-time. */
void __attribute__ ((constructor)) udp_master_init()
{
/* Initialize defaults. */
- _udp_master = udp_master_recvfrom;
+ _udp_init = udp_recvfrom_init;
+ _udp_deinit = udp_recvfrom_deinit;
+ _udp_recv = udp_recvfrom_recv;
+ _udp_send = udp_recvfrom_send;
+ _udp_handle = udp_recvfrom_handle;
/* Optimized functions. */
#ifdef ENABLE_RECVMMSG
-#ifdef MSG_WAITFORONE
/* Check for recvmmsg() support. */
if (dlsym(RTLD_DEFAULT, "recvmmsg") != 0) {
- int r = recvmmsg(0, NULL, 0, 0, 0);
+ recvmmsg(0, NULL, 0, 0, 0);
if (errno != ENOSYS) {
- _udp_master = udp_master_recvmmsg;
+ _udp_init = udp_recvmmsg_init;
+ _udp_deinit = udp_recvmmsg_deinit;
+ _udp_recv = udp_recvmmsg_recv;
+ _udp_send = udp_recvmmsg_send;
+ _udp_handle = udp_recvmmsg_handle;
}
}
-
+
/* Check for sendmmsg() support. */
- _send_mmsg = udp_sendto;
+ _send_mmsg = udp_sendmsg;
#ifdef ENABLE_SENDMMSG
sendmmsg(0, 0, 0, 0); /* Just check if syscall exists */
if (errno != ENOSYS) {
_send_mmsg = udp_sendmmsg;
}
#endif /* ENABLE_SENDMMSG */
-#endif /* MSG_WAITFORONE */
#endif /* ENABLE_RECVMMSG */
}
-
-
-int udp_master(dthread_t *thread)
+
+int udp_reader(iohandler_t *h, dthread_t *thread)
{
- iohandler_t *handler = (iohandler_t *)thread->data;
- int sock = handler->fd;
- /* Check socket. */
- if (sock < 0) {
- dbg_net("udp: null socket recevied, finishing.\n");
- return KNOT_EINVAL;
- }
+ iostate_t *st = (iostate_t *)thread->data;
- /* Set socket options. */
- int flag = 1;
-#ifndef DISABLE_IPV6
- if (handler->type == AF_INET6) {
- /* Disable dual-stack for performance reasons. */
- setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &flag, sizeof(flag));
-
- /* UDP packets will not exceed a minimum MTU size. */
- /*flag = IPV6_MIN_MTU;
- setsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &flag, sizeof(flag));
- flag = 1; */
- }
-#endif
- if (handler->type == AF_INET) {
-
-//#ifdef IP_PMTUDISC_DONT
-// /* Disable fragmentation. */
-// flag = IP_PMTUDISC_DONT;
-// setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &flag, sizeof(flag));
-// flag = 1;
-//#endif
- }
+ /* Prepare structures for bound sockets. */
+ unsigned thr_id = dt_get_id(thread);
+ void *rq = _udp_init();
+ ifacelist_t *ref = NULL;
- /* in case of STAT_COMPILE the following code will declare thread_stat
- * variable in following fashion: stat_t *thread_stat;
- */
+ /* Create memory pool context. */
+ struct mempool *pool = mp_new(64 * 1024);
+ mm_ctx_t mm;
+ mm.ctx = pool;
+ mm.alloc = (mm_alloc_t)mp_alloc;
+ mm.free = NULL;
- stat_t *thread_stat = 0;
- STAT_INIT(thread_stat); //XXX new stat instance every time.
- stat_set_protocol(thread_stat, stat_UDP);
-
- /* Drop all capabilities on workers. */
-#ifdef HAVE_CAP_NG_H
- if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
- capng_clear(CAPNG_SELECT_BOTH);
- capng_apply(CAPNG_SELECT_BOTH);
- }
-#endif /* HAVE_CAP_NG_H */
+ /* Create UDP answering context. */
+ struct answer_ctx ans_ctx;
+ ans_ctx.srv = h->server;
+ ans_ctx.slip = 0;
+ ans_ctx.mm = &mm;
+ /* Chose select as epoll/kqueue has larger overhead for a
+ * single or handful of sockets. */
+ fd_set fds;
+ FD_ZERO(&fds);
+ int minfd = 0, maxfd = 0;
+ int rcvd = 0;
- /* Execute proper handler. */
- dbg_net_verb("udp: thread started (worker %p).\n", thread);
- int ret = _udp_master(thread, thread_stat);
- if (ret != KNOT_EOK) {
- log_server_warning("UDP answering module finished "
- "with an error (%s).\n",
- knot_strerror(ret));
+ udp_pps_begin();
+
+ /* Loop until all data is read. */
+ for (;;) {
+
+ /* Check handler state. */
+ if (knot_unlikely(st->s & ServerReload)) {
+ st->s &= ~ServerReload;
+ maxfd = 0;
+ minfd = INT_MAX;
+ FD_ZERO(&fds);
+
+ rcu_read_lock();
+ ref_release((ref_t *)ref);
+ ref = h->server->ifaces;
+ if (ref) {
+ iface_t *i = NULL;
+ WALK_LIST(i, ref->l) {
+ int fd = i->fd[IO_UDP];
+ FD_SET(fd, &fds);
+ maxfd = MAX(fd, maxfd);
+ minfd = MIN(fd, minfd);
+ }
+ }
+ rcu_read_unlock();
+ }
+
+ /* Cancellation point. */
+ if (dt_is_cancelled(thread)) {
+ break;
+ }
+
+ /* Wait for events. */
+ fd_set rfds;
+ FD_COPY(&fds, &rfds);
+ int nfds = select(maxfd + 1, &rfds, NULL, NULL, NULL);
+ if (nfds <= 0) {
+ if (errno == EINTR) continue;
+ break;
+ }
+ /* Bound sockets will be usually closely coupled. */
+ for (unsigned fd = minfd; fd <= maxfd; ++fd) {
+ if (FD_ISSET(fd, &rfds)) {
+ while ((rcvd = _udp_recv(fd, rq)) > 0) {
+ _udp_handle(&ans_ctx, rq);
+ _udp_send(rq);
+ mp_flush(mm.ctx);
+ udp_pps_sample(rcvd, thr_id);
+ }
+ }
+ }
}
- stat_free(thread_stat);
- dbg_net_verb("udp: worker %p finished.\n", thread);
-
-
- return ret;
+ _udp_deinit(rq);
+ ref_release((ref_t *)ref);
+ mp_delete(mm.ctx);
+ return KNOT_EOK;
}
+int udp_master(dthread_t *thread)
+{
+ unsigned cpu = dt_online_cpus();
+ if (cpu > 1) {
+ unsigned cpu_mask[2];
+ cpu_mask[0] = dt_get_id(thread) % cpu;
+ cpu_mask[1] = (cpu_mask[0] + 2) % cpu;
+ dt_setaffinity(thread, cpu_mask, 2);
+ }
+
+ /* Drop all capabilities on all workers. */
+#ifdef HAVE_CAP_NG_H
+ if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
+ capng_clear(CAPNG_SELECT_BOTH);
+ capng_apply(CAPNG_SELECT_BOTH);
+ }
+#endif /* HAVE_CAP_NG_H */
+
+ iostate_t *st = (iostate_t *)thread->data;
+ if (!st) return KNOT_EINVAL;
+ iohandler_t *h = st->h;
+ return udp_reader(h, thread);
+}
diff --git a/src/knot/server/udp-handler.h b/src/knot/server/udp-handler.h
index 8292072..92b32a4 100644
--- a/src/knot/server/udp-handler.h
+++ b/src/knot/server/udp-handler.h
@@ -36,25 +36,14 @@
#include "knot/server/dthreads.h"
/*!
- * \brief Handle single packet.
- *
- * Function processses packet and prepares answer to qbuf,
- * response length is set to resp_len.
- *
- * \param sock
- * \param qbuf
- * \param qbuflen
- * \param resp_len
- * \param addr
- * \param ns
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_ERROR
- * \retval KNOT_ENOMEM
+ * \brief Create UDP handler context.
+ */
+void* udp_create_ctx(void);
+
+/*!
+ * \brief Destroy UDP handler context.
*/
-int udp_handle(int sock, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
- sockaddr_t* addr, knot_nameserver_t *ns,
- rrl_table_t *rrl, unsigned *slip);
+void udp_free_ctx(void *ctx);
/*!
* \brief UDP handler thread runnable.
diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index 8e403c0..c7c1abf 100644
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -28,7 +28,7 @@
#include <assert.h>
#include <urcu.h>
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/server/xfr-handler.h"
#include "libknot/nameserver/name-server.h"
#include "knot/server/socket.h"
@@ -40,239 +40,536 @@
#include "libknot/tsig-op.h"
#include "common/evsched.h"
#include "common/prng.h"
+#include "common/descriptor.h"
+#include "libknot/rrset.h"
/* Constants */
+#define XFR_CHUNKLEN 3 /*! Number of requests assigned in a single pass. */
#define XFR_SWEEP_INTERVAL 2 /*! [seconds] between sweeps. */
#define XFR_BUFFER_SIZE 65535 /*! Do not change this - maximum value for UDP packet length. */
#define XFR_MSG_DLTTR 9 /*! Index of letter differentiating IXFR/AXFR in log msg. */
-/*! \brief Send interrupt to all workers. */
-void xfr_interrupt(xfrhandler_t *h)
+/* Messages */
+
+static knot_lookup_table_t xfr_type_table[] = {
+ { XFR_TYPE_AIN, "Incoming AXFR of '%s' with %s:" },
+ { XFR_TYPE_IIN, "Incoming IXFR of '%s' with %s:" },
+ { XFR_TYPE_AOUT, "Outgoing AXFR of '%s' to %s:" },
+ { XFR_TYPE_IOUT, "Outgoing IXFR of '%s' to %s:" },
+ { XFR_TYPE_NOTIFY, "NOTIFY of '%s' to %s:" },
+ { XFR_TYPE_SOA, "SOA query of '%s' to %s:" },
+ { XFR_TYPE_FORWARD, "UPDATE forwarded query of '%s' to %s:" },
+ { XFR_TYPE_AIN, NULL }
+};
+static knot_lookup_table_t xfr_result_table[] = {
+ { XFR_TYPE_AIN, "Started" },
+ { XFR_TYPE_IIN, "Started" },
+ { XFR_TYPE_SOA, "Query issued" },
+ { XFR_TYPE_NOTIFY, "Query issued" },
+ { XFR_TYPE_FORWARD, "Forwarded query" },
+ { XFR_TYPE_AIN, NULL }
+};
+
+/* I/O wrappers */
+
+static int xfr_send_tcp(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
+{ return tcp_send(fd, msg, msglen); }
+
+static int xfr_send_udp(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
+{ return sendto(fd, msg, msglen, 0, (struct sockaddr *)addr, addr->len); }
+
+static int xfr_recv_tcp(int fd, sockaddr_t *addr, uint8_t *buf, size_t buflen)
+{ return tcp_recv(fd, buf, buflen, addr); }
+
+static int xfr_recv_udp(int fd, sockaddr_t *addr, uint8_t *buf, size_t buflen)
+{ return recvfrom(fd, buf, buflen, 0, (struct sockaddr *)addr, &addr->len); }
+
+/* Context fetching. */
+
+static knot_ns_xfr_t* xfr_task_get(xfrworker_t *w, int fd)
{
- for(unsigned i = 0; i < h->unit->size; ++i) {
- evqueue_t *q = h->workers[i]->q;
- if (evqueue_write(q, "", 1) == 1) {
- close(q->fds[EVQUEUE_WRITEFD]);
- q->fds[EVQUEUE_WRITEFD] = -1;
- } else {
- dt_stop_id(h->unit->threads[i]);
- }
- }
+ value_t *val = ahtable_tryget(w->pool.t, (const char*)&fd, sizeof(int));
+ if (!val) return NULL;
+ return *val;
}
-/*! \brief Deinitialize allocated values from xfer descriptor. */
-static void xfr_request_deinit(knot_ns_xfr_t *r)
+static void xfr_task_set(xfrworker_t *w, int fd, knot_ns_xfr_t *rq)
{
- if (r) {
- free(r->msgpref);
- r->msgpref = NULL;
- }
+ fdset_add(w->pool.fds, fd, OS_EV_READ);
+ value_t *val = ahtable_get(w->pool.t, (const char*)&fd, sizeof(int));
+ *val = rq;
}
-/*!
- * \brief Clean pending transfer data.
- */
-static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
+static void xfr_task_clear(xfrworker_t *w, int fd)
+{
+ ahtable_del(w->pool.t, (const char*)&fd, sizeof(int));
+ fdset_remove(w->pool.fds, fd);
+}
+
+/*! \brief Wrapper function for answering AXFR/OUT. */
+static int xfr_answer_axfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
+{
+ int ret = knot_ns_answer_axfr(ns, xfr);
+ dbg_xfr("xfr: ns_answer_axfr() = %d.\n", ret);
+ return ret;
+}
+
+/*! \brief Wrapper function for answering IXFR/OUT. */
+static int xfr_answer_ixfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
{
+ /* Check serial differences. */
int ret = KNOT_EOK;
- knot_changesets_t *chs = 0;
+ uint32_t serial_from = 0;
+ uint32_t serial_to = 0;
+ ret = ns_ixfr_load_serials(xfr, &serial_from, &serial_to);
+ dbg_xfr_verb("xfr: loading changesets for IXFR %u-%u\n",
+ serial_from, serial_to);
+ log_server_info("%s Started (serial %u -> %u).\n",
+ xfr->msg, serial_from, serial_to);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
- dbg_xfr_verb("Cleaning up after XFR-in.\n");
-
- switch(data->type) {
- case XFR_TYPE_AIN:
- if (data->flags & XFR_FLAG_AXFR_FINISHED) {
- knot_zone_contents_deep_free(
- &data->new_contents, 1);
+ /* Load changesets from journal. */
+ int chsload = zones_xfr_load_changesets(xfr, serial_from, serial_to);
+ if (chsload != KNOT_EOK) {
+ /* History cannot be reconstructed, fallback to AXFR. */
+ if (chsload == KNOT_ERANGE || chsload == KNOT_ENOENT) {
+ log_server_info("%s Incomplete history, "
+ "fallback to AXFR.\n",
+ xfr->msg);
+ xfr->type = XFR_TYPE_AOUT;
+ xfr->msg[XFR_MSG_DLTTR] = 'A';
+ return xfr_answer_axfr(ns, xfr);
+ } else if (chsload == KNOT_EMALF) {
+ xfr->rcode = KNOT_RCODE_FORMERR;
} else {
- if (data->data) {
- xfrin_constructed_zone_t *constr_zone =
- (xfrin_constructed_zone_t *)data->data;
- knot_zone_contents_deep_free(
- &(constr_zone->contents), 0);
- xfrin_free_orphan_rrsigs(&(constr_zone->rrsigs));
- free(data->data);
- data->data = 0;
- }
- }
- break;
- case XFR_TYPE_IIN:
- if (data->data) {
- chs = (knot_changesets_t *)data->data;
- knot_free_changesets(&chs);
- data->data = NULL;
+ xfr->rcode = KNOT_RCODE_SERVFAIL;
}
- // this function is called before new contents are created
- assert(data->new_contents == NULL);
-
- break;
+ /* Mark all as generic error. */
+ ret = KNOT_ERROR;
}
- /* Cleanup other data - so that the structure may be reused. */
- data->packet_nr = 0;
- data->tsig_data_size = 0;
+ /* Finally, answer. */
+ if (chsload == KNOT_EOK) {
+ ret = knot_ns_answer_ixfr(ns, xfr);
+ dbg_xfr("xfr: ns_answer_ixfr() = %s.\n", knot_strerror(ret));
+ }
- dbg_xfr_detail("Done.\n");
-
return ret;
}
-/*! \brief Free allocated xfer descriptor (also deinitializes). */
-static void xfr_free_task(knot_ns_xfr_t *task)
+/*! \brief Build string for logging related to given xfer descriptor. */
+static int xfr_task_setmsg(knot_ns_xfr_t *rq, const char *keytag)
{
- if (!task) {
- return;
+ /* Check */
+ if (rq == NULL) {
+ return KNOT_EINVAL;
}
-
- xfrworker_t *w = (xfrworker_t *)task->owner;
- if (!w) {
- free(task);
- return;
+
+ knot_lookup_table_t *xd = knot_lookup_by_id(xfr_type_table, rq->type);
+ if (!xd) {
+ return KNOT_EINVAL;
}
- /* Remove from fdset. */
- if (w->fdset) {
- dbg_xfr("xfr_free_task: freeing fd=%d.\n", task->session);
- fdset_remove(w->fdset, task->session);
+ /* Zone is refcounted, no need for RCU. */
+ char *kstr = NULL;
+ if (keytag) {
+ kstr = xfr_remote_str(&rq->addr, keytag);
+ } else if (rq->tsig_key) {
+ char *tag = knot_dname_to_str(rq->tsig_key->name);
+ kstr = xfr_remote_str(&rq->addr, tag);
+ free(tag);
+ } else {
+ kstr = xfr_remote_str(&rq->addr, NULL);
}
-
- /* Unlock if XFR/IN.*/
- int is_xfer = task->type == XFR_TYPE_AIN || task->type == XFR_TYPE_IIN;
- if (is_xfer) {
- knot_zone_t *zone = task->zone;
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- if (zd) {
- zd->xfr_in.wrkr = 0;
- pthread_mutex_unlock(&zd->xfr_in.lock);
+
+ /* Prepare log message. */
+ const char *zname = rq->zname;
+ if (zname == NULL && rq->zone != NULL) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone);
+ if (zd == NULL) {
+ free(kstr);
+ return KNOT_EINVAL;
+ } else {
+ zname = zd->conf->name;
}
}
-
- /* Free TSIG buffers. */
- if (task->digest) {
- free(task->digest);
- task->digest = NULL;
- task->digest_size = 0;
+
+ rq->msg = sprintf_alloc(xd->name, zname, kstr ? kstr : "'unknown'");
+ free(kstr);
+ return KNOT_EOK;
+}
+
+static int xfr_task_setsig(knot_ns_xfr_t *rq, knot_tsig_key_t *key)
+{
+ if (rq == NULL || key == NULL) {
+ return KNOT_EINVAL;
}
- if (task->tsig_data) {
- free(task->tsig_data);
- task->tsig_data = NULL;
- task->tsig_data_size = 0;
+
+ int ret = KNOT_EOK;
+ rq->tsig_key = key;
+ rq->tsig_size = tsig_wire_maxsize(key);
+ rq->digest_max_size = knot_tsig_digest_length(key->algorithm);
+ rq->digest = malloc(rq->digest_max_size);
+ if (rq->digest == NULL) {
+ rq->tsig_key = NULL;
+ rq->tsig_size = 0;
+ rq->digest_max_size = 0;
+ return KNOT_ENOMEM;
}
-
- if (!task->session_closed) {
- /* Cleanup pending request. */
- if (is_xfer) {
- xfr_xfrin_cleanup(w, task);
+ memset(rq->digest, 0 , rq->digest_max_size);
+ rq->tsig_data = malloc(KNOT_NS_TSIG_DATA_MAX_SIZE);
+ if (rq->tsig_data) {
+ dbg_xfr("xfr: using TSIG for XFR/IN\n");
+ rq->tsig_data_size = 0;
+ } else {
+ free(rq->digest);
+ rq->digest = NULL;
+ rq->tsig_key = NULL;
+ rq->tsig_size = 0;
+ rq->digest_max_size = 0;
+ return KNOT_ENOMEM;
+ }
+ dbg_xfr("xfr: found TSIG key (MAC len=%zu), adding to transfer\n",
+ rq->digest_max_size);
+
+ return ret;
+}
+
+static int xfr_task_connect(knot_ns_xfr_t *rq)
+{
+ /* Create socket by type. */
+ int stype = SOCK_DGRAM;
+ if (rq->flags & XFR_FLAG_TCP) {
+ stype = SOCK_STREAM;
+ }
+ int fd = socket_create(sockaddr_family(&rq->addr), stype, 0);
+ if (fd < 0) {
+ return KNOT_ERROR;
+ }
+
+ /* Bind to specific address - if set. */
+ if (rq->saddr.len > 0) {
+ if (bind(fd, (struct sockaddr *)&rq->saddr, rq->saddr.len) < 0) {
+ socket_close(fd);
+ return KNOT_ERROR;
}
-
- /* Remove fd-related data. */
- xfrhandler_t *h = w->master;
- pthread_mutex_lock(&h->tasks_mx);
- skip_remove(h->tasks, (void*)((size_t)task->session), 0, 0);
- pthread_mutex_unlock(&h->tasks_mx);
- close(task->session);
}
-
- /* No further access to zone. */
- knot_zone_release(task->zone);
-
- /* Deinitialize */
- xfr_request_deinit(task);
- free(task);
+ /* Connect if TCP. */
+ if (rq->flags & XFR_FLAG_TCP) {
+ if (connect(fd, (struct sockaddr *)&rq->addr, rq->addr.len) < 0) {
+ socket_close(fd);
+ return KNOT_ECONNREFUSED;
+ }
+ }
+
+ /* Store new socket descriptor. */
+ rq->session = fd;
+ return KNOT_EOK;
}
-/*!
- * \brief Return xfer descriptor associated with given fd.
- *
- * \param w Current worker.
- * \param fd Requested descriptor.
- *
- * \retval xfer descriptor if found.
- * \retval NULL if no descriptor found.
- */
-static knot_ns_xfr_t *xfr_handler_task(xfrworker_t *w, int fd)
+/*! \brief Clean pending transfer data. */
+static void xfr_task_cleanup(knot_ns_xfr_t *rq)
{
- xfrhandler_t *h = w->master;
- pthread_mutex_lock(&h->tasks_mx);
- knot_ns_xfr_t *data = skip_find(h->tasks, (void*)((size_t)fd));
- pthread_mutex_unlock(&h->tasks_mx);
-
- if (data == NULL) {
- dbg_xfr_verb("xfr: worker=%p processing event on "
- "fd=%d got empty data.\n",
- w, fd);
- fdset_remove(w->fdset, fd);
- close(fd); /* Always dup()'d or created. */
- return NULL;
+ dbg_xfr_verb("Cleaning up after XFR-in.\n");
+ if (rq->type == XFR_TYPE_AIN) {
+ if (rq->flags & XFR_FLAG_AXFR_FINISHED) {
+ knot_zone_contents_deep_free(&rq->new_contents);
+ } else if (rq->data) {
+ xfrin_constructed_zone_t *constr_zone = rq->data;
+ knot_zone_contents_deep_free(&(constr_zone->contents));
+ xfrin_free_orphan_rrsigs(&(constr_zone->rrsigs));
+ free(rq->data);
+ rq->data = NULL;
+ }
+ } else if (rq->type == XFR_TYPE_IIN) {
+ knot_changesets_t *chs = (knot_changesets_t *)rq->data;
+ knot_free_changesets(&chs);
+ rq->data = NULL;
+ assert(rq->new_contents == NULL);
+ } else if (rq->type == XFR_TYPE_FORWARD) {
+ knot_packet_free(&rq->query);
}
-
- return data;
+
+ /* Cleanup other data - so that the structure may be reused. */
+ rq->packet_nr = 0;
+ rq->tsig_data_size = 0;
+ hattrie_clear(rq->lookup_tree);
}
-/*!
- * \brief SOA query timeout handler.
- */
-static int xfr_udp_timeout(knot_ns_xfr_t *data)
+/*! \brief Close and free task. */
+static int xfr_task_close(xfrworker_t *w, int fd)
{
- /* Close socket. */
- rcu_read_lock();
- knot_zone_t *z = data->zone;
- if (z && knot_zone_get_contents(z) && knot_zone_data(z)) {
- if (!(knot_zone_flags(z) & KNOT_ZONE_DISCARDED)) {
- log_zone_info("%s Failed, timeout exceeded.\n",
- data->msgpref);
+ knot_ns_xfr_t *rq = xfr_task_get(w, fd);
+ if (!rq) return KNOT_ENOENT;
+
+ /* Update xfer state. */
+ if (rq->type == XFR_TYPE_AIN || rq->type == XFR_TYPE_IIN) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone);
+ pthread_mutex_lock(&zd->lock);
+ if (zd->xfr_in.state == XFR_PENDING) {
+ zd->xfr_in.state = XFR_IDLE;
}
+ pthread_mutex_unlock(&zd->lock);
}
- rcu_read_unlock();
-
- /* Invalidate pending query. */
- xfr_free_task(data);
+
+ /* Close socket and free task. */
+ xfr_task_clear(w, fd);
+ xfr_task_free(rq);
+ socket_close(fd);
return KNOT_EOK;
}
-/*!
- * \brief Query response event handler function.
- *
- * Handle single query response event.
- *
- * \param loop Associated event pool.
- * \param w Associated socket watcher.
- * \param revents Returned events.
- */
-static int xfr_process_udp_resp(xfrworker_t *w, int fd, knot_ns_xfr_t *data)
+/*! \brief Timeout handler. */
+static int xfr_task_expire(fdset_t *fds, knot_ns_xfr_t *rq)
{
- /* Check if zone is valid. */
- int ret = KNOT_ECONNREFUSED;
- rcu_read_lock();
- if (knot_zone_flags(data->zone) & KNOT_ZONE_DISCARDED) {
- rcu_read_unlock();
+ /* Fetch related zone (refcounted, no RCU). */
+ knot_zone_t *zone = (knot_zone_t *)rq->zone;
+ const knot_zone_contents_t *contents = knot_zone_contents(zone);
+
+ /* Process timeout. */
+ rq->wire_size = rq->wire_maxlen;
+ switch(rq->type) {
+ case XFR_TYPE_NOTIFY:
+ if ((long)--rq->data > 0) { /* Retries */
+ notify_create_request(contents, rq->wire, &rq->wire_size);
+ fdset_set_watchdog(fds, rq->session, NOTIFY_TIMEOUT);
+ rq->send(rq->session, &rq->addr, rq->wire, rq->wire_size);
+ log_zone_info("%s Query issued (serial %u).\n",
+ rq->msg, knot_zone_serial(contents));
+ rq->packet_nr = knot_wire_get_id(rq->wire);
+ return KNOT_EOK; /* Keep state. */
+ }
+ break;
+ default:
+ break;
+ }
+
+ log_zone_info("%s Failed, timeout exceeded.\n", rq->msg);
+ return KNOT_ECONNREFUSED;
+}
+
+/*! \brief Start pending request. */
+static int xfr_task_start(knot_ns_xfr_t *rq)
+{
+ if (!rq || !rq->zone) {
+ return KNOT_EINVAL;
+ }
+
+ /* Zone is refcounted, no need for RCU. */
+ int ret = KNOT_EOK;
+ knot_zone_t *zone = (knot_zone_t *)rq->zone;
+
+ /* Fetch zone contents. */
+ const knot_zone_contents_t *contents = knot_zone_contents(zone);
+ if (!contents && rq->type == XFR_TYPE_IIN) {
+ log_server_warning("%s Refusing to start IXFR on zone with no "
+ "contents.\n", rq->msg);
return KNOT_ECONNREFUSED;
}
- rcu_read_unlock();
-
- /* Receive msg. */
- ssize_t n = -1;
- size_t resp_len = data->wire_size;
- if (data->flags & XFR_FLAG_TCP) {
- n = tcp_recv(data->session, data->wire, resp_len, &data->addr);
- } else {
- n = recvfrom(data->session, data->wire, resp_len,
- 0, data->addr.ptr, &data->addr.len);
+
+ /* Connect to remote. */
+ if (rq->session <= 0) {
+ ret = xfr_task_connect(rq);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
}
-
- if (n <= 0) {
+
+ /* Prepare TSIG key if set. */
+ int add_tsig = 0;
+ if (rq->tsig_key) {
+ ret = xfr_task_setsig(rq, rq->tsig_key);
+ add_tsig = (ret == KNOT_EOK);
+ }
+
+ /* Create XFR query. */
+ switch(rq->type) {
+ case XFR_TYPE_AIN:
+ ret = xfrin_create_axfr_query(zone->name, rq, &rq->wire_size, add_tsig);
+ break;
+ case XFR_TYPE_IIN:
+ ret = xfrin_create_ixfr_query(contents, rq, &rq->wire_size, add_tsig);
+ break;
+ case XFR_TYPE_SOA:
+ ret = xfrin_create_soa_query(zone->name, rq, &rq->wire_size);
+ break;
+ case XFR_TYPE_NOTIFY:
+ rq->wire_size = 0;
+ ret = KNOT_EOK; /* Will be sent on first timeout. */
+ break;
+ case XFR_TYPE_FORWARD:
+ ret = knot_ns_create_forward_query(rq->query, rq->wire, &rq->wire_size);
+ break;
+ default:
+ ret = KNOT_EINVAL;
+ break;
+ }
+
+ /* Handle errors. */
+ if (ret != KNOT_EOK) {
+ dbg_xfr("xfr: failed to create XFR query type %d: %s\n",
+ rq->type, knot_strerror(ret));
return ret;
}
- // parse packet
+ /* Start transfer. */
+ gettimeofday(&rq->t_start, NULL);
+ if (rq->wire_size > 0) {
+ ret = rq->send(rq->session, &rq->addr, rq->wire, rq->wire_size);
+ if (ret != rq->wire_size) {
+ char ebuf[256] = {0};
+ if (strerror_r(errno, ebuf, sizeof(ebuf)) == 0) {
+ log_server_info("%s Failed to send query (%s).\n",
+ rq->msg, ebuf);
+ }
+ return KNOT_ECONNREFUSED;
+ }
+ }
+
+ /* If successful. */
+ if (rq->type == XFR_TYPE_SOA) {
+ rq->packet_nr = knot_wire_get_id(rq->wire);
+ }
+
+ return KNOT_EOK;
+}
+
+static int xfr_task_process(xfrworker_t *w, knot_ns_xfr_t* rq, uint8_t *buf, size_t buflen)
+{
+ /* Check if not already processing, zone is refcounted. */
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone);
+
+ /* Check if the zone is not discarded. */
+ if (!zd || knot_zone_flags(rq->zone) & KNOT_ZONE_DISCARDED) {
+ dbg_xfr_verb("xfr: request on a discarded zone, ignoring\n");
+ return KNOT_EINVAL;
+ }
+
+ /* Update XFR message prefix. */
+ xfr_task_setmsg(rq, NULL);
+
+ /* Update request. */
+ rq->wire = buf;
+ rq->wire_size = buflen;
+ rq->wire_maxlen = buflen;
+ rq->send = &xfr_send_udp;
+ rq->recv = &xfr_recv_udp;
+ if (rq->flags & XFR_FLAG_TCP) {
+ rq->send = &xfr_send_tcp;
+ rq->recv = &xfr_recv_tcp;
+ }
+
+ /* Handle request. */
+ dbg_xfr("%s processing request type '%d'\n", rq->msg, rq->type);
+ int ret = xfr_task_start(rq);
+ const char *msg = knot_strerror(ret);
+ knot_lookup_table_t *xd = knot_lookup_by_id(xfr_result_table, rq->type);
+ if (xd && ret == KNOT_EOK) {
+ msg = xd->name;
+ }
+
+ int bootstrap_fail = 0;
+ switch(rq->type) {
+ case XFR_TYPE_AIN:
+ case XFR_TYPE_IIN:
+ rq->lookup_tree = hattrie_create();
+ if (ret != KNOT_EOK) {
+ pthread_mutex_lock(&zd->lock);
+ zd->xfr_in.state = XFR_IDLE;
+ pthread_mutex_unlock(&zd->lock);
+ bootstrap_fail = !knot_zone_contents(rq->zone);
+ }
+ break;
+ case XFR_TYPE_NOTIFY: /* Send on first timeout <0,5>s. */
+ fdset_set_watchdog(w->pool.fds, rq->session, (int)(tls_rand() * 5));
+ xfr_task_set(w, rq->session, rq);
+ return KNOT_EOK;
+ case XFR_TYPE_SOA:
+ case XFR_TYPE_FORWARD:
+ fdset_set_watchdog(w->pool.fds, rq->session, conf()->max_conn_reply);
+ break;
+ default:
+ break;
+ }
+
+ if (ret == KNOT_EOK) {
+ xfr_task_set(w, rq->session, rq);
+ log_server_info("%s %s.\n", rq->msg, msg);
+ } else if (bootstrap_fail){
+ int tmr_s = AXFR_BOOTSTRAP_RETRY * tls_rand();
+ event_t *ev = zd->xfr_in.timer;
+ if (ev) {
+ evsched_cancel(ev->parent, ev);
+ evsched_schedule(ev->parent, ev, tmr_s);
+ }
+ log_zone_notice("%s Bootstrap failed, next "
+ "attempt in %d seconds.\n",
+ rq->msg, tmr_s / 1000);
+ } else {
+ log_server_error("%s %s.\n", rq->msg, msg);
+ }
+
+ return ret;
+}
+
+/*! \brief Finalize XFR/IN transfer. */
+static int xfr_task_finalize(xfrworker_t *w, knot_ns_xfr_t *rq)
+{
+ int ret = KNOT_EINVAL;
+ knot_nameserver_t *ns = w->master->ns;
+
+ if (rq->type == XFR_TYPE_AIN) {
+ ret = zones_save_zone(rq);
+ if (ret == KNOT_EOK) {
+ ret = knot_ns_switch_zone(ns, rq);
+ if (ret != KNOT_EOK) {
+ log_zone_error("%s %s\n", rq->msg, knot_strerror(ret));
+ log_zone_error("%s Failed to switch in-memory "
+ "zone.\n", rq->msg);
+ }
+ } else {
+ log_zone_error("%s %s\n",
+ rq->msg, knot_strerror(ret));
+ log_zone_error("%s Failed to save zonefile.\n",
+ rq->msg);
+ }
+ } else if (rq->type == XFR_TYPE_IIN) {
+ knot_changesets_t *chs = (knot_changesets_t *)rq->data;
+ ret = zones_store_and_apply_chgsets(chs, rq->zone,
+ &rq->new_contents,
+ rq->msg,
+ XFR_TYPE_IIN);
+ rq->data = NULL; /* Freed or applied in prev function. */
+ }
+
+ if (ret == KNOT_EOK) {
+ struct timeval t_end;
+ gettimeofday(&t_end, NULL);
+ log_zone_info("%s Finished in %.02fs "
+ "(finalization %.02fs).\n",
+ rq->msg,
+ time_diff(&rq->t_start, &t_end) / 1000.0,
+ time_diff(&rq->t_end, &t_end) / 1000.0);
+ rq->new_contents = NULL; /* Do not free. */
+ }
+
+ return ret;
+}
+
+/*! \brief Query response event handler function. */
+static int xfr_task_resp(xfrworker_t *w, knot_ns_xfr_t *rq)
+{
+ knot_nameserver_t *ns = w->master->ns;
knot_packet_t *re = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
if (re == NULL) {
return KNOT_ENOMEM;
}
-
+
knot_packet_type_t rt = KNOT_RESPONSE_NORMAL;
- ret = knot_ns_parse_packet(data->wire, n, re, &rt);
+ int ret = knot_ns_parse_packet(rq->wire, rq->wire_size, re, &rt);
if (ret != KNOT_EOK) {
knot_packet_free(&re);
return KNOT_EOK; /* Ignore */
@@ -289,867 +586,503 @@ static int xfr_process_udp_resp(xfrworker_t *w, int fd, knot_ns_xfr_t *data)
return KNOT_EOK; /* Ignore */
}
- ret = knot_packet_parse_rest(re);
+ ret = knot_packet_parse_rest(re, 0);
if (ret != KNOT_EOK) {
knot_packet_free(&re);
return KNOT_EOK; /* Ignore */
}
-
- // check TSIG
+
+ /* Check TSIG. */
const knot_rrset_t * tsig_rr = knot_packet_tsig(re);
- if (data->tsig_key != NULL) {
+ if (rq->tsig_key != NULL) {
/*! \todo Not sure about prev_time_signed, but this is the first
* reply and we should pass query sign time as the time
* may be different. Leaving to 0.
*/
- ret = knot_tsig_client_check(tsig_rr, data->wire, n,
- data->digest, data->digest_size,
- data->tsig_key, 0);
+ ret = knot_tsig_client_check(tsig_rr, rq->wire, rq->wire_size,
+ rq->digest, rq->digest_size,
+ rq->tsig_key, 0);
if (ret != KNOT_EOK) {
- log_server_error("%s %s\n",
- data->msgpref, knot_strerror(ret));
+ log_server_error("%s %s\n", rq->msg, knot_strerror(ret));
knot_packet_free(&re);
return KNOT_ECONNREFUSED;
}
-
+
}
-
- // process response
- size_t qlen = n;
+
+ /* Process response. */
+ size_t rlen = rq->wire_size;
switch(rt) {
case KNOT_RESPONSE_NORMAL:
- ret = zones_process_response(w->ns, &data->addr, re,
- data->wire, &resp_len);
+ ret = zones_process_response(ns, rq->packet_nr, &rq->addr,
+ re, rq->wire, &rlen);
break;
case KNOT_RESPONSE_NOTIFY:
- ret = notify_process_response(w->ns, re, &data->addr,
- data->wire, &resp_len);
+ ret = notify_process_response(re, rq->packet_nr);
break;
case KNOT_RESPONSE_UPDATE:
- ret = zones_process_update_response(data, data->wire, &qlen);
+ ret = zones_process_update_response(rq, rq->wire, &rlen);
if (ret == KNOT_EOK) {
- log_server_info("%s Forwarded response.\n",
- data->msgpref);
+ log_server_info("%s Forwarded response.\n", rq->msg);
}
break;
default:
+ ret = KNOT_EINVAL;
break;
}
-
+
knot_packet_free(&re);
-
- /* Check up-to-date zone. */
- if (ret == KNOT_EUPTODATE) {
- log_server_info("%s %s\n", data->msgpref, knot_strerror(ret));
+ if (ret == KNOT_EUPTODATE) { /* Check up-to-date zone. */
+ log_server_info("%s %s (serial %u)\n", rq->msg,
+ knot_strerror(ret),
+ knot_zone_serial(knot_zone_contents(rq->zone)));
ret = KNOT_ECONNREFUSED;
- }
-
- /* Invalidate pending query. */
- if (ret == KNOT_EOK) {
+ } else if (ret == KNOT_EOK) { /* Disconnect if everything went well. */
ret = KNOT_ECONNREFUSED;
}
- return ret;
-}
-/*! \brief Sweep non-replied connection. */
-static void xfr_sweep(fdset_t *set, int fd, void *data)
-{
- dbg_xfr("xfr: sweeping fd=%d\n", fd);
-
- if (!set || !data) {
- dbg_xfr("xfr: invalid sweep operation on NULL worker or set\n");
- return;
- }
- knot_ns_xfr_t *t = xfr_handler_task((xfrworker_t *)data, fd);
- if (!t) {
- dbg_xfr("xfr: NULL data to sweep\n");
- return;
- }
-
- /* Skip non-sweepable types. */
- switch(t->type) {
- case XFR_TYPE_SOA:
- case XFR_TYPE_NOTIFY:
- case XFR_TYPE_FORWARD:
- xfr_udp_timeout(t);
- break;
- default:
- dbg_xfr("xfr: sweep request on unsupported type\n");
- break;
- }
+ return ret;
}
-/*!
- * \brief Register task in given worker.
- *
- * \warning Must be freed with xfr_free_task() when finished.
- *
- * \param w Given worker.
- * \param req Pointer to template xfer descriptor.
- *
- * \retval Newly allocated xfer descriptor if success.
- * \retval NULL on error.
+/*! \brief This will fall back to AXFR on active connection.
+ * \note The active connection is expected to be force shut.
*/
-static knot_ns_xfr_t *xfr_register_task(xfrworker_t *w, const knot_ns_xfr_t *req)
+static int xfr_start_axfr(xfrworker_t *w, knot_ns_xfr_t *rq, const char *reason)
{
- knot_ns_xfr_t *t = malloc(sizeof(knot_ns_xfr_t));
- if (!t) {
- return NULL;
- }
-
- memcpy(t, req, sizeof(knot_ns_xfr_t));
- sockaddr_update(&t->addr);
- sockaddr_update(&t->saddr);
+ log_zone_notice("%s %s\n", rq->msg, reason);
- /* Update request. */
- t->wire = 0; /* Invalidate shared buffer. */
- t->wire_size = 0;
- t->data = 0; /* New zone will be built. */
- t->msgpref = strdup(t->msgpref); /* Copy message. */
-
- /* Register data. */
- xfrhandler_t * h = w->master;
- pthread_mutex_lock(&h->tasks_mx);
- int ret = skip_insert(h->tasks, (void*)((ssize_t)t->session), t, 0);
- pthread_mutex_unlock(&h->tasks_mx);
-
- /* Add to set. */
- if (ret == 0) {
- ret = fdset_add(w->fdset, t->session, OS_EV_READ);
- }
- /* Evaluate final return code. */
- if (ret == 0) {
- t->owner = w;
- } else {
- /* Attempt to remove from list anyway. */
- skip_remove(h->tasks, (void*)((ssize_t)t->session), NULL, NULL);
- free(t);
- t = NULL;
+ /* Copy current xfer data. */
+ knot_ns_xfr_t *axfr = xfr_task_create(rq->zone, XFR_TYPE_AIN, XFR_FLAG_TCP);
+ if (axfr == NULL) {
+ log_zone_warning("%s Couldn't fall back to AXFR.\n", rq->msg);
+ return KNOT_ECONNREFUSED; /* Disconnect */
}
- return t;
-}
-
-/*!
- * \brief Finalize XFR/IN transfer.
- *
- * \param w XFR worker.
- * \param data Associated data.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_ERROR
- */
-static int xfr_xfrin_finalize(xfrworker_t *w, knot_ns_xfr_t *data)
-{
- int ret = KNOT_EOK;
-// int apply_ret = KNOT_EOK;
- int switch_ret = KNOT_EOK;
- knot_changesets_t *chs = NULL;
-// journal_t *transaction = NULL;
-
- switch(data->type) {
- case XFR_TYPE_AIN:
- dbg_xfr("xfr: %s Saving new zone file.\n", data->msgpref);
- ret = zones_save_zone(data);
- if (ret != KNOT_EOK) {
- xfr_xfrin_cleanup(w, data);
- log_zone_error("%s Failed to save transferred zone - %s\n",
- data->msgpref, knot_strerror(ret));
- } else {
- dbg_xfr("xfr: %s New zone saved.\n", data->msgpref);
- switch_ret = knot_ns_switch_zone(w->ns, data);
- if (switch_ret != KNOT_EOK) {
- log_zone_error("%s Failed to switch in-memory "
- "zone - %s\n", data->msgpref,
- knot_strerror(switch_ret));
- xfr_xfrin_cleanup(w, data);
- ret = KNOT_ERROR;
- }
- }
- if (ret == KNOT_EOK) {
- log_zone_info("%s Finished.\n", data->msgpref);
- }
- break;
- case XFR_TYPE_IIN:
- chs = (knot_changesets_t *)data->data;
- ret = zones_store_and_apply_chgsets(chs, data->zone,
- &data->new_contents,
- data->msgpref,
- XFR_TYPE_IIN);
- data->data = NULL;
- break;
- default:
- ret = KNOT_EINVAL;
- break;
- }
+ xfr_task_setaddr(axfr, &rq->addr, &rq->saddr);
+ axfr->tsig_key = rq->tsig_key;
- return ret;
+ /* Enqueue new request and close the original. */
+ log_server_notice("%s Retrying with AXFR.\n", rq->msg);
+ xfr_enqueue(w->master, axfr);
+ return KNOT_ECONNREFUSED;
}
-/*!
- * \brief Check TSIG if exists.
- */
-static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode, char **tag)
+/*! \brief This will fall back to AXFR on idle connection. */
+static int xfr_fallback_axfr(knot_ns_xfr_t *rq)
{
- /* Parse rest of the packet. */
- int ret = KNOT_EOK;
- knot_packet_t *qry = xfr->query;
- knot_key_t *key = 0;
- const knot_rrset_t *tsig_rr = 0;
- ret = knot_packet_parse_rest(qry);
+ log_server_notice("%s Retrying with AXFR.\n", rq->msg);
+ rq->wire_size = rq->wire_maxlen; /* Reset maximum bufsize */
+ int ret = xfrin_create_axfr_query(rq->zone->name, rq, &rq->wire_size, 1);
+ /* Send AXFR/IN query. */
if (ret == KNOT_EOK) {
-
- /* Find TSIG key name from query. */
- const knot_dname_t* kname = 0;
- int tsig_pos = knot_packet_additional_rrset_count(qry) - 1;
- if (tsig_pos >= 0) {
- tsig_rr = knot_packet_additional_rrset(qry, tsig_pos);
- if (knot_rrset_type(tsig_rr) == KNOT_RRTYPE_TSIG) {
- dbg_xfr("xfr: found TSIG in AR\n");
- kname = knot_rrset_owner(tsig_rr);
- if (tag) {
- *tag = knot_dname_to_str(kname);
-
- }
- } else {
- tsig_rr = 0;
- }
- }
- if (!kname) {
- dbg_xfr("xfr: TSIG not found in AR\n");
- char *name = knot_dname_to_str(
- knot_zone_name(xfr->zone));
- free(name);
-
- // return REFUSED
- xfr->tsig_key = 0;
- *rcode = KNOT_RCODE_REFUSED;
- return KNOT_EXFRDENIED;
- }
- if (tsig_rr) {
- tsig_algorithm_t alg = tsig_rdata_alg(tsig_rr);
- if (tsig_alg_digest_length(alg) == 0) {
- *rcode = KNOT_RCODE_NOTAUTH;
- xfr->tsig_key = NULL;
- xfr->tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
- xfr->tsig_prev_time_signed =
- tsig_rdata_time_signed(tsig_rr);
- return KNOT_TSIG_EBADKEY;
- }
- }
-
- /* Evaluate configured key for claimed key name.*/
- key = xfr->tsig_key; /* Expects already set key (check_zone) */
- xfr->tsig_key = 0;
- if (key && kname && knot_dname_compare(key->name, kname) == 0) {
- dbg_xfr("xfr: found claimed TSIG key for comparison\n");
+ ret = rq->send(rq->session, &rq->addr,
+ rq->wire, rq->wire_size);
+ /* Switch to AXFR and return. */
+ if (ret == rq->wire_size) {
+ xfr_task_cleanup(rq);
+ rq->type = XFR_TYPE_AIN;
+ rq->msg[XFR_MSG_DLTTR] = 'A';
+ ret = KNOT_EOK;
} else {
-
- /* TSIG is mandatory if configured for interface. */
- /* Configured, but doesn't match. */
- dbg_xfr("xfr: no claimed key configured or not received"
- ", treating as bad key\n");
- *rcode = KNOT_RCODE_NOTAUTH;
- ret = KNOT_TSIG_EBADKEY;
- xfr->tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
- key = 0; /* Invalidate, ret already set to BADKEY */
+ ret = KNOT_ERROR;
}
-
- /* Validate with TSIG. */
- if (key) {
- /* Prepare variables for TSIG */
- xfr_prepare_tsig(xfr, key);
-
- /* Copy MAC from query. */
- dbg_xfr("xfr: validating TSIG from query\n");
- const uint8_t* mac = tsig_rdata_mac(tsig_rr);
- size_t mac_len = tsig_rdata_mac_length(tsig_rr);
- if (mac_len > xfr->digest_max_size) {
- ret = KNOT_EMALF;
- dbg_xfr("xfr: MAC length %zu exceeds digest "
- "maximum size %zu\n",
- mac_len, xfr->digest_max_size);
- } else {
- memcpy(xfr->digest, mac, mac_len);
- xfr->digest_size = mac_len;
-
- /* Check query TSIG. */
- ret = knot_tsig_server_check(
- tsig_rr,
- knot_packet_wireformat(qry),
- knot_packet_size(qry),
- key);
- dbg_xfr("knot_tsig_server_check() returned %s\n",
- knot_strerror(ret));
- }
-
- /* Evaluate TSIG check results. */
- switch(ret) {
- case KNOT_EOK:
- *rcode = KNOT_RCODE_NOERROR;
- break;
- case KNOT_TSIG_EBADKEY:
- xfr->tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
- xfr->tsig_key = NULL;
- *rcode = KNOT_RCODE_NOTAUTH;
- break;
- case KNOT_TSIG_EBADSIG:
- xfr->tsig_rcode = KNOT_TSIG_RCODE_BADSIG;
- xfr->tsig_key = NULL;
- *rcode = KNOT_RCODE_NOTAUTH;
- break;
- case KNOT_TSIG_EBADTIME:
- xfr->tsig_rcode = KNOT_TSIG_RCODE_BADTIME;
- // store the time signed from the query
- assert(tsig_rr != NULL);
- xfr->tsig_prev_time_signed =
- tsig_rdata_time_signed(tsig_rr);
- *rcode = KNOT_RCODE_NOTAUTH;
- break;
- case KNOT_EMALF:
- *rcode = KNOT_RCODE_FORMERR;
- break;
- default:
- *rcode = KNOT_RCODE_SERVFAIL;
- }
- }
- } else {
- dbg_xfr("xfr: failed to parse rest of the packet\n");
- *rcode = KNOT_RCODE_FORMERR;
}
-
+
return ret;
}
-/*!
- * \brief XFR-IN event handler function.
- *
- * Handle single XFR client event.
- *
- * \param w Associated XFR worker.
- * \param fd Associated file descriptor.
- * \param data Transfer data.
- */
-int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf, size_t buflen)
+static int xfr_task_xfer(xfrworker_t *w, knot_ns_xfr_t *rq)
{
- /* Update xfer state. */
- knot_zone_t *zone = (knot_zone_t *)data->zone;
- data->wire = buf;
- data->wire_size = buflen;
-
- /* Handle SOA/NOTIFY responses. */
- switch(data->type) {
- case XFR_TYPE_NOTIFY:
- case XFR_TYPE_SOA:
- case XFR_TYPE_FORWARD:
- return xfr_process_udp_resp(w, fd, data);
+ /* Process incoming packet. */
+ int ret = KNOT_EOK;
+ knot_nameserver_t *ns = w->master->ns;
+ switch(rq->type) {
+ case XFR_TYPE_AIN:
+ ret = knot_ns_process_axfrin(ns, rq);
+ break;
+ case XFR_TYPE_IIN:
+ ret = knot_ns_process_ixfrin(ns, rq);
+ break;
default:
+ ret = KNOT_EINVAL;
break;
}
- /* Read DNS/TCP packet. */
- int ret = 0;
- int rcvd = tcp_recv(fd, buf, buflen, 0);
-
- /* Raise read-lock and check if zone is still valid. */
- rcu_read_lock();
- int zone_discarded = (knot_zone_flags(zone) & KNOT_ZONE_DISCARDED);
-
- /* Handle incoming packet. */
- data->wire_size = rcvd;
- if (rcvd <= 0 || zone_discarded) {
- data->wire_size = 0;
- ret = KNOT_ECONN;
- } else {
-
- /* Process incoming packet. */
- switch(data->type) {
- case XFR_TYPE_AIN:
- ret = knot_ns_process_axfrin(w->ns, data);
- break;
- case XFR_TYPE_IIN:
- ret = knot_ns_process_ixfrin(w->ns, data);
- break;
- default:
- ret = KNOT_EINVAL;
- break;
- }
- }
/* AXFR-style IXFR. */
if (ret == KNOT_ENOIXFR) {
- assert(data->type == XFR_TYPE_IIN);
- log_server_notice("%s Fallback to AXFR.\n", data->msgpref);
- data->type = XFR_TYPE_AIN;
- data->msgpref[XFR_MSG_DLTTR] = 'A';
- ret = knot_ns_process_axfrin(w->ns, data);
+ assert(rq->type == XFR_TYPE_IIN);
+ log_server_notice("%s Fallback to AXFR.\n", rq->msg);
+ xfr_task_cleanup(rq);
+ rq->type = XFR_TYPE_AIN;
+ rq->msg[XFR_MSG_DLTTR] = 'A';
+ ret = knot_ns_process_axfrin(ns, rq);
}
/* Check return code for errors. */
- dbg_xfr_verb("xfr: processed incoming XFR packet (%s)\n",
- knot_strerror(ret));
-
- /* Finished xfers. */
- int xfer_finished = 0;
- if (ret != KNOT_EOK) {
- xfer_finished = 1;
- }
-
+ dbg_xfr_verb("xfr: processed XFR pkt (%s)\n", knot_strerror(ret));
+
/* IXFR refused, try again with AXFR. */
- if (data->type == XFR_TYPE_IIN && ret == KNOT_EXFRREFUSED) {
- log_server_notice("%s Transfer failed, fallback to AXFR.\n",
- data->msgpref);
- size_t bufsize = buflen;
- data->wire_size = buflen; /* Reset maximum bufsize */
- ret = xfrin_create_axfr_query(zone->name, data,
- &bufsize, 1);
- /* Send AXFR/IN query. */
- if (ret == KNOT_EOK) {
- ret = data->send(data->session, &data->addr,
- data->wire, bufsize);
- /* Switch to AIN type XFR and return now. */
- if (ret == bufsize) {
- rcu_read_unlock();
- xfr_xfrin_cleanup(w, data);
- data->type = XFR_TYPE_AIN;
- data->msgpref[XFR_MSG_DLTTR] = 'A';
- return KNOT_EOK;
- }
+ const char *diff_nospace_msg = "Can't fit the differences in the journal.";
+ if (rq->type == XFR_TYPE_IIN) {
+ switch(ret) {
+ case KNOT_ESPACE: /* Fallthrough */
+ return xfr_start_axfr(w, rq, diff_nospace_msg);
+ case KNOT_EXFRREFUSED:
+ return xfr_fallback_axfr(rq);
+ default:
+ break;
}
}
-
- rcu_read_unlock();
/* Handle errors. */
- if (!zone_discarded) {
- if (ret == KNOT_ENOXFR) {
- log_server_warning("%s Finished, %s\n",
- data->msgpref, knot_strerror(ret));
- } else if (ret < 0) {
- log_server_error("%s %s\n",
- data->msgpref, knot_strerror(ret));
- }
+ if (ret == KNOT_ENOXFR) {
+ log_server_warning("%s Finished, %s\n", rq->msg, knot_strerror(ret));
+ } else if (ret < 0) {
+ log_server_error("%s %s\n", rq->msg, knot_strerror(ret));
}
- /* Check finished zone. */
- int result = KNOT_EOK;
- if (xfer_finished) {
-
- /* Close early to free up fd for storing zone. */
- data->session_closed = 1;
- close(data->session);
-
- /* Remove fd-related data. */
- xfrhandler_t *h = w->master;
- pthread_mutex_lock(&h->tasks_mx);
- skip_remove(h->tasks, (void*)((size_t)data->session), 0, 0);
- pthread_mutex_unlock(&h->tasks_mx);
-
- knot_zone_t *zone = (knot_zone_t *)data->zone;
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
-
- /* Only for successful xfers on non-discarded zones. */
- if (ret > 0 && !zone_discarded) {
- ret = xfr_xfrin_finalize(w, data);
-
- /* AXFR bootstrap timeout. */
- if (ret != KNOT_EOK && !knot_zone_contents(zone)) {
- /* Schedule request (60 - 90s random delay). */
- int tmr_s = AXFR_BOOTSTRAP_RETRY;
- tmr_s += (30.0 * 1000) * (tls_rand());
- zd->xfr_in.bootstrap_retry = tmr_s;
- log_zone_info("%s Next attempt to bootstrap "
- "in %d seconds.\n",
- data->msgpref, tmr_s / 1000);
- }
+ /* Only for successful xfers. */
+ if (ret > 0) {
+ ret = xfr_task_finalize(w, rq);
+ if (ret != KNOT_EOK && !knot_zone_contents(rq->zone)) {
- /* Update timers. */
- server_t *server = (server_t *)knot_ns_get_data(w->ns);
- zones_timers_update(zone, zd->conf, server->sched);
+ /* AXFR bootstrap timeout. */
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(rq->zone);
+ int tmr_s = AXFR_BOOTSTRAP_RETRY * tls_rand();
+ zd->xfr_in.bootstrap_retry = tmr_s;
+ log_zone_info("%s Next attempt to bootstrap "
+ "in %d seconds.\n",
+ rq->msg, tmr_s / 1000);
+ } else if (ret == KNOT_EBUSY && rq->type == XFR_TYPE_IIN) {
+ return xfr_start_axfr(w, rq, diff_nospace_msg);
} else {
- /* Cleanup */
- xfr_xfrin_cleanup(w, data);
+
+ /* Passed, schedule NOTIFYs. */
+ zones_schedule_notify(rq->zone);
}
-
- /* Disconnect. */
- result = KNOT_ECONNREFUSED; /* Make it disconnect. */
+
+ /* Update REFRESH/RETRY */
+ zones_schedule_refresh(rq->zone, 0);
+ ret = KNOT_ECONNREFUSED; /* Disconnect */
}
- return result;
+ return ret;
}
-/*!
- * \brief Start incoming transfer (applicable to AXFR/IN or IXFR/IN).
- *
- * \warning xfer descriptor will be registered if successful.
- * \warning data->fd will be duplicated if successful.
- *
- * \param w Given worker.
- * \param data xfer descriptor.
- */
-static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
+/*! \brief Incoming packet handling function. */
+static int xfr_process_event(xfrworker_t *w, knot_ns_xfr_t *rq)
{
- /* Fetch associated zone. */
- knot_zone_t *zone = (knot_zone_t *)data->zone;
- if (!zone) {
- return KNOT_EINVAL;
- }
-
- /* Check if not already processing. */
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- if (!zd) {
- return KNOT_EINVAL;
- }
-
- /* Enqueue to worker that has zone locked for XFR/IN. */
- int ret = pthread_mutex_trylock(&zd->xfr_in.lock);
- rcu_read_lock();
- if (ret != 0) {
- dbg_xfr_verb("xfr: XFR/IN switching to another thread, "
- "zone '%s' is already in transfer\n",
- zd->conf->name);
- xfrworker_t *nextw = (xfrworker_t *)zd->xfr_in.wrkr;
- if (nextw == 0) {
- nextw = w;
- }
-
- /* Free data updated in this processing. */
- ret = evqueue_write(nextw->q, data, sizeof(knot_ns_xfr_t));
- if (ret != sizeof(knot_ns_xfr_t)) {
- char ebuf[256] = {0};
- strerror_r(errno, ebuf, sizeof(ebuf));
- dbg_xfr("xfr: couldn't write request to evqueue: %s\n",
- ebuf);
- rcu_read_unlock();
- return KNOT_ERROR;
- }
-
- rcu_read_unlock();
- return KNOT_EOK;
- } else {
- zd->xfr_in.wrkr = w;
- --zd->xfr_in.scheduled;
+ /* Check if zone is valid. */
+ if (knot_zone_flags(rq->zone) & KNOT_ZONE_DISCARDED) {
+ return KNOT_ECONNREFUSED;
}
- /* Connect to remote. */
- if (data->session <= 0) {
- int fd = socket_create(data->addr.family, SOCK_STREAM);
- if (fd >= 0) {
- /* Bind to specific address - if set. */
- sockaddr_update(&data->saddr);
- if (data->saddr.len > 0) {
- /* Presume port is already preset. */
- ret = bind(fd, data->saddr.ptr, data->saddr.len);
- }
- if (ret < 0) {
- log_server_warning("%s Failed to create socket.\n",
- data->msgpref);
- } else {
- ret = connect(fd, data->addr.ptr, data->addr.len);
- if (ret < 0) {
- dbg_xfr("%s: couldn't connect to "
- "remote host\n", data->msgpref);
- }
- }
- } else {
- ret = -1;
- dbg_xfr("%s: couldn't create socket err=%d\n",
- data->msgpref, errno);
- }
-
- if (ret < 0) {
- rcu_read_unlock();
- pthread_mutex_unlock(&zd->xfr_in.lock);
- if (fd >= 0) {
- close(fd);
- }
- return KNOT_ECONNREFUSED;
- }
-
- /* Store new socket descriptor. */
- data->session = fd;
+ /* Receive msg. */
+ int n = rq->recv(rq->session, &rq->addr, rq->wire, rq->wire_maxlen);
+ if (n < 0) { /* Disconnect */
+ n = knot_map_errno(errno);
+ log_server_error("%s %s\n", rq->msg, knot_strerror(n));
+ return n;
+ } else if (n == 0) {
+ return KNOT_ECONNREFUSED;
} else {
- /* Duplicate existing socket descriptor. */
- data->session = dup(data->session);
- if (data->session < 0) {
- rcu_read_unlock();
- pthread_mutex_unlock(&zd->xfr_in.lock);
- log_server_warning("Not enough memory to duplicate \n"
- "sockets.\n");
- return KNOT_ENOMEM;
- }
+ rq->wire_size = n;
}
- /* Fetch zone contents. */
- const knot_zone_contents_t *contents = knot_zone_contents(zone);
- if (!contents && data->type == XFR_TYPE_IIN) {
- pthread_mutex_unlock(&zd->xfr_in.lock);
- rcu_read_unlock();
- log_server_warning("%s Refusing to start IXFR on zone with no "
- "contents.\n", data->msgpref);
- close(data->session);
- data->session = -1;
- return KNOT_EINVAL;
+ /* Handle SOA/NOTIFY responses. */
+ switch(rq->type) {
+ case XFR_TYPE_NOTIFY:
+ case XFR_TYPE_SOA:
+ case XFR_TYPE_FORWARD:
+ return xfr_task_resp(w, rq);
+ default:
+ return xfr_task_xfer(w, rq);
}
+}
- /* Prepare TSIG key if set. */
- int add_tsig = 0;
- if (data->tsig_key) {
- if (xfr_prepare_tsig(data, data->tsig_key) == KNOT_EOK) {
- size_t data_bufsize = KNOT_NS_TSIG_DATA_MAX_SIZE;
- data->tsig_data = malloc(data_bufsize);
- if (data->tsig_data) {
- dbg_xfr("xfr: using TSIG for XFR/IN\n");
- add_tsig = 1;
- data->tsig_data_size = 0;
- } else {
- dbg_xfr("xfr: failed to allocate TSIG data "
- "buffer (%zu kB)\n",
- data_bufsize / 1024);
- }
- }
+/*! \brief Sweep non-replied connection. */
+static void xfr_sweep(fdset_t *set, int fd, void *data)
+{
+ dbg_xfr("xfr: sweeping fd=%d\n", fd);
+ if (!set || !data) {
+ dbg_xfr("xfr: invalid sweep operation on NULL worker or set\n");
+ return;
+ }
+ xfrworker_t *w = (xfrworker_t *)data;
+ knot_ns_xfr_t *rq = xfr_task_get(w, fd);
+ if (!rq) {
+ dbg_xfr("xfr: NULL data to sweep\n");
+ return;
}
- /* Create XFR query. */
- size_t bufsize = data->wire_size;
- switch(data->type) {
- case XFR_TYPE_AIN:
- ret = xfrin_create_axfr_query(zone->name, data, &bufsize, add_tsig);
- break;
- case XFR_TYPE_IIN:
- ret = xfrin_create_ixfr_query(contents, data, &bufsize, add_tsig);
+ /* Skip non-sweepable types. */
+ int ret = KNOT_ECONNREFUSED;
+ switch(rq->type) {
+ case XFR_TYPE_SOA:
+ case XFR_TYPE_NOTIFY:
+ case XFR_TYPE_FORWARD:
+ ret = xfr_task_expire(set, rq);
break;
default:
- ret = KNOT_EINVAL;
break;
}
- /* Handle errors. */
if (ret != KNOT_EOK) {
- pthread_mutex_unlock(&zd->xfr_in.lock);
- rcu_read_unlock();
- dbg_xfr("xfr: failed to create XFR query type %d: %s\n",
- data->type, knot_strerror(ret));
- close(data->session);
- data->session = -1;
- return KNOT_ERROR;
+ xfr_task_close(w, fd);
+ --w->pending;
}
-
- /* Unlock zone contents. */
- rcu_read_unlock();
-
- /* Start transfer. */
- ret = data->send(data->session, &data->addr, data->wire, bufsize);
- if (ret != bufsize) {
- char ebuf[256] = {0};
- strerror_r(errno, ebuf, sizeof(ebuf));
- log_server_info("%s Failed to send query (%s).\n",
- data->msgpref, ebuf);
- pthread_mutex_unlock(&zd->xfr_in.lock);
- close(data->session);
- data->session = -1;
- return KNOT_ECONNREFUSED;
- }
-
- /* Add to pending transfers. */
- knot_ns_xfr_t *task = xfr_register_task(w, data);
- if (task == NULL) {
- log_server_warning("%s Couldn't start connection.\n",
- data->msgpref);
- close(data->session);
- data->session = -1;
- return KNOT_ERROR;
- }
-
- /* Send XFR query. */
- log_server_info("%s Started.\n", data->msgpref);
- return KNOT_EOK;
}
-/*!
- * \brief Compare file descriptors.
- *
- * \note Return values of {-1,0,1} are required by skip-list structure.
- */
-static int xfr_fd_compare(void *k1, void *k2)
+/*! \brief Check TSIG if exists. */
+static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode, char **tag)
{
- if (k1 > k2) return 1;
- if (k1 < k2) return -1;
- return 0;
-}
+ /* Parse rest of the packet. */
+ int ret = KNOT_EOK;
+ knot_packet_t *qry = xfr->query;
+ knot_tsig_key_t *key = 0;
+ const knot_rrset_t *tsig_rr = 0;
-/*! \brief Return I/A character depending on xfer type. */
-static inline char xfr_strtype(knot_ns_xfr_t *xfr) {
- if (xfr->type == XFR_TYPE_IOUT) {
- return 'I';
- } else {
- return 'A';
- }
-}
+ /* Find TSIG key name from query. */
+ const knot_dname_t* kname = 0;
+ int tsig_pos = knot_packet_additional_rrset_count(qry) - 1;
+ if (tsig_pos >= 0) {
+ tsig_rr = knot_packet_additional_rrset(qry, tsig_pos);
+ if (knot_rrset_type(tsig_rr) == KNOT_RRTYPE_TSIG) {
+ dbg_xfr("xfr: found TSIG in AR\n");
+ kname = knot_rrset_owner(tsig_rr);
+ if (tag) {
+ *tag = knot_dname_to_str(kname);
-/*! \brief Wrapper function for answering AXFR/OUT. */
-static int xfr_answer_axfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
-{
- int ret = knot_ns_answer_axfr(ns, xfr);
- dbg_xfr("xfr: ns_answer_axfr() = %d.\n", ret);
- return ret;
-}
-
-/*! \brief Wrapper function for answering IXFR/OUT. */
-static int xfr_answer_ixfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
-{
- /* Check serial differeces. */
- int ret = KNOT_EOK;
- uint32_t serial_from = 0;
- uint32_t serial_to = 0;
- ret = ns_ixfr_load_serials(xfr, &serial_from, &serial_to);
- dbg_xfr_verb("xfr: loading changesets for IXFR %u-%u\n",
- serial_from, serial_to);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- /* Load changesets from journal. */
- int chsload = zones_xfr_load_changesets(xfr, serial_from, serial_to);
- if (chsload != KNOT_EOK) {
- /* History cannot be reconstructed, fallback to AXFR. */
- if (chsload == KNOT_ERANGE || chsload == KNOT_ENOENT) {
- log_server_info("%s Failed to load data from journal: "
- " Incomplete history. "
- "Fallback to AXFR.\n",
- xfr->msgpref);
- xfr->type = XFR_TYPE_AOUT;
- xfr->msgpref[XFR_MSG_DLTTR] = 'A';
- return xfr_answer_axfr(ns, xfr);
- } else if (chsload == KNOT_EMALF) {
- xfr->rcode = KNOT_RCODE_FORMERR;
+ }
} else {
- xfr->rcode = KNOT_RCODE_SERVFAIL;
+ tsig_rr = 0;
}
-
- /* Mark all as generic error. */
- ret = KNOT_ERROR;
}
-
- /* Finally, answer. */
- if (chsload == KNOT_EOK) {
- ret = knot_ns_answer_ixfr(ns, xfr);
- dbg_xfr("xfr: ns_answer_ixfr() = %s.\n", knot_strerror(ret));
- }
-
- return ret;
-}
+ if (!kname) {
+ dbg_xfr("xfr: TSIG not found in AR\n");
+ char *name = knot_dname_to_str(
+ knot_zone_name(xfr->zone));
+ free(name);
-/*! \brief Build string for logging related to given xfer descriptor. */
-static int xfr_update_msgpref(knot_ns_xfr_t *req, const char *keytag)
-{
- /* Check */
- if (req == NULL) {
- return KNOT_EINVAL;
+ // return REFUSED
+ xfr->tsig_key = 0;
+ *rcode = KNOT_RCODE_REFUSED;
+ return KNOT_EDENIED;
}
-
- rcu_read_lock();
- char *r_key = NULL;
- if (keytag) {
- r_key = xfr_remote_str(&req->addr, keytag);
- } else if (req->tsig_key) {
- char *tag = knot_dname_to_str(req->tsig_key->name);
- r_key = xfr_remote_str(&req->addr, tag);
- free(tag);
+ if (tsig_rr) {
+ knot_tsig_algorithm_t alg = tsig_rdata_alg(tsig_rr);
+ if (knot_tsig_digest_length(alg) == 0) {
+ *rcode = KNOT_RCODE_NOTAUTH;
+ xfr->tsig_key = NULL;
+ xfr->tsig_rcode = KNOT_RCODE_BADKEY;
+ xfr->tsig_prev_time_signed =
+ tsig_rdata_time_signed(tsig_rr);
+ return KNOT_TSIG_EBADKEY;
+ }
+ }
+
+ /* Evaluate configured key for claimed key name.*/
+ key = xfr->tsig_key; /* Expects already set key (check_zone) */
+ xfr->tsig_key = 0;
+ if (key && kname && knot_dname_compare(key->name, kname) == 0) {
+ dbg_xfr("xfr: found claimed TSIG key for comparison\n");
} else {
- r_key = xfr_remote_str(&req->addr, NULL);
+
+ /* TSIG is mandatory if configured for interface. */
+ /* Configured, but doesn't match. */
+ dbg_xfr("xfr: no claimed key configured or not received"
+ ", treating as bad key\n");
+ *rcode = KNOT_RCODE_NOTAUTH;
+ ret = KNOT_TSIG_EBADKEY;
+ xfr->tsig_rcode = KNOT_RCODE_BADKEY;
+ key = NULL; /* Invalidate, ret already set to BADKEY */
}
- /* Prepare log message. */
- const char *zname = req->zname;
- if (zname == NULL && req->zone != NULL) {
- zonedata_t *zd = (zonedata_t *)knot_zone_data(req->zone);
- if (zd == NULL) {
- free(r_key);
- rcu_read_unlock();
- return KNOT_EINVAL;
+ /* Validate with TSIG. */
+ if (key) {
+ /* Prepare variables for TSIG */
+ xfr_task_setsig(xfr, key);
+
+ /* Copy MAC from query. */
+ dbg_xfr("xfr: validating TSIG from query\n");
+ const uint8_t* mac = tsig_rdata_mac(tsig_rr);
+ size_t mac_len = tsig_rdata_mac_length(tsig_rr);
+ if (mac_len > xfr->digest_max_size) {
+ ret = KNOT_EMALF;
+ dbg_xfr("xfr: MAC length %zu exceeds digest "
+ "maximum size %zu\n",
+ mac_len, xfr->digest_max_size);
} else {
- zname = zd->conf->name;
+ memcpy(xfr->digest, mac, mac_len);
+ xfr->digest_size = mac_len;
+
+ /* Check query TSIG. */
+ ret = knot_tsig_server_check(
+ tsig_rr,
+ knot_packet_wireformat(qry),
+ knot_packet_size(qry),
+ key);
+ dbg_xfr("knot_tsig_server_check() returned %s\n",
+ knot_strerror(ret));
}
- }
- const char *pformat = NULL;
- switch (req->type) {
- case XFR_TYPE_AIN:
- pformat = "Incoming AXFR transfer of '%s' with %s:";
- break;
- case XFR_TYPE_IIN:
- pformat = "Incoming IXFR transfer of '%s' with %s:";
- break;
- case XFR_TYPE_AOUT:
- pformat = "Outgoing AXFR transfer of '%s' to %s:";
- break;
- case XFR_TYPE_IOUT:
- pformat = "Outgoing IXFR transfer of '%s' to %s:";
- break;
- case XFR_TYPE_NOTIFY:
- pformat = "NOTIFY query of '%s' to %s:";
- break;
- case XFR_TYPE_SOA:
- pformat = "SOA query of '%s' to %s:";
- break;
- case XFR_TYPE_FORWARD:
- pformat = "UPDATE forwarded query of '%s' to %s:";
- break;
- default:
- pformat = "UNKNOWN query '%s' from %s:";
- break;
- }
- char *msg = sprintf_alloc(pformat, zname, r_key ? r_key : "'unknown'");
- if (msg) {
- req->msgpref = msg;
+ /* Evaluate TSIG check results. */
+ switch(ret) {
+ case KNOT_EOK:
+ *rcode = KNOT_RCODE_NOERROR;
+ break;
+ case KNOT_TSIG_EBADKEY:
+ xfr->tsig_rcode = KNOT_RCODE_BADKEY;
+ xfr->tsig_key = NULL;
+ *rcode = KNOT_RCODE_NOTAUTH;
+ break;
+ case KNOT_TSIG_EBADSIG:
+ xfr->tsig_rcode = KNOT_RCODE_BADSIG;
+ xfr->tsig_key = NULL;
+ *rcode = KNOT_RCODE_NOTAUTH;
+ break;
+ case KNOT_TSIG_EBADTIME:
+ xfr->tsig_rcode = KNOT_RCODE_BADTIME;
+ // store the time signed from the query
+ assert(tsig_rr != NULL);
+ xfr->tsig_prev_time_signed =
+ tsig_rdata_time_signed(tsig_rr);
+ *rcode = KNOT_RCODE_NOTAUTH;
+ break;
+ case KNOT_EMALF:
+ *rcode = KNOT_RCODE_FORMERR;
+ break;
+ default:
+ *rcode = KNOT_RCODE_SERVFAIL;
+ }
}
-
- rcu_read_unlock();
- free(r_key);
- return KNOT_EOK;
+
+
+ return ret;
}
-/*! \brief Create XFR worker. */
-static xfrworker_t* xfr_worker_create(xfrhandler_t *h, knot_nameserver_t *ns)
+int xfr_worker(dthread_t *thread)
{
- xfrworker_t *w = malloc(sizeof(xfrworker_t));
- if(!w) {
- return 0;
+ assert(thread != NULL && thread->data != NULL);
+ xfrworker_t *w = (xfrworker_t *)thread->data;
+ xfrhandler_t *xfr = w->master;
+
+ /* Buffer for answering. */
+ size_t buflen = XFR_BUFFER_SIZE;
+ uint8_t* buf = malloc(buflen);
+ if (buf == NULL) {
+ dbg_xfr("xfr: failed to allocate buffer for XFR worker\n");
+ return KNOT_ENOMEM;
}
-
- /* Set nameserver and master. */
- w->ns = ns;
- w->master = h;
-
- /* Create event queue. */
- w->q = evqueue_new();
- if (!w->q) {
- free(w);
- return 0;
+
+ /* Next sweep time. */
+ timev_t next_sweep;
+ time_now(&next_sweep);
+ next_sweep.tv_sec += XFR_SWEEP_INTERVAL;
+
+ int limit = XFR_CHUNKLEN * 3;
+ if (conf() && conf()->xfers > 0) {
+ limit = conf()->xfers;
}
-
- /* Create fdset. */
- w->fdset = fdset_new();
- if (!w->fdset) {
- evqueue_free(&w->q);
- free(w);
- return 0;
+ unsigned thread_capacity = limit / w->master->unit->size;
+ if (thread_capacity < 1) thread_capacity = 1;
+ w->pool.fds = fdset_new();
+ w->pool.t = ahtable_create();
+ w->pending = 0;
+
+ /* Accept requests. */
+ int ret = 0;
+ dbg_xfr_verb("xfr: worker=%p starting\n", w);
+ for (;;) {
+
+ /* Populate pool with new requests. */
+ if (w->pending <= thread_capacity) {
+ pthread_mutex_lock(&xfr->mx);
+ unsigned was_pending = w->pending;
+ while (!EMPTY_LIST(xfr->queue)) {
+ knot_ns_xfr_t *rq = HEAD(xfr->queue);
+ rem_node(&rq->n);
+
+ /* Unlock queue and process request. */
+ pthread_mutex_unlock(&xfr->mx);
+ ret = xfr_task_process(w, rq, buf, buflen);
+ if (ret == KNOT_EOK) ++w->pending;
+ else xfr_task_free(rq);
+ pthread_mutex_lock(&xfr->mx);
+
+ if (w->pending - was_pending > XFR_CHUNKLEN)
+ break;
+ }
+ pthread_mutex_unlock(&xfr->mx);
+ }
+
+ /* Check pending threads. */
+ if (dt_is_cancelled(thread) || w->pending == 0) {
+ break;
+ }
+
+ /* Poll fdset. */
+ int nfds = fdset_wait(w->pool.fds, (XFR_SWEEP_INTERVAL/2) * 1000);
+ if (nfds < 0) {
+ if (errno == EINTR) continue;
+ break;
+ }
+
+ /* Iterate fdset. */
+ fdset_it_t it;
+ fdset_begin(w->pool.fds, &it);
+ while(nfds > 0) {
+
+ /* Find data. */
+ knot_ns_xfr_t *rq = xfr_task_get(w, it.fd);
+ dbg_xfr_verb("xfr: worker=%p processing event on "
+ "fd=%d data=%p.\n",
+ w, it.fd, rq);
+ if (rq) {
+ ret = xfr_process_event(w, rq);
+ if (ret != KNOT_EOK) {
+ xfr_task_close(w, it.fd);
+ --w->pending;
+ --it.pos; /* Reset iterator */
+ }
+ }
+
+ /* Next fd. */
+ if (fdset_next(w->pool.fds, &it) < 0) {
+ break;
+ }
+ }
+
+ /* Sweep inactive. */
+ timev_t now;
+ if (time_now(&now) == 0) {
+ if (now.tv_sec >= next_sweep.tv_sec) {
+ fdset_sweep(w->pool.fds, &xfr_sweep, w);
+ memcpy(&next_sweep, &now, sizeof(next_sweep));
+ next_sweep.tv_sec += XFR_SWEEP_INTERVAL;
+ }
+ }
}
-
- /* Add evqueue to fdset. */
- fdset_add(w->fdset, evqueue_pollfd(w->q), OS_EV_READ);
-
- return w;
-}
-/*! \brief Free created XFR worker. */
-static void xfr_worker_free(xfrworker_t *w) {
- if (w) {
- evqueue_free(&w->q);
- fdset_destroy(w->fdset);
- free(w);
+ /* Cancel existing connections. */
+ size_t keylen = 0;
+ ahtable_iter_t i;
+ ahtable_iter_begin(w->pool.t, &i, false);
+ while (!ahtable_iter_finished(&i)) {
+ int *key = (int *)ahtable_iter_key(&i, &keylen);
+ xfr_task_close(w, *key);
+ ahtable_iter_next(&i);
}
+ ahtable_iter_free(&i);
+
+ /* Destroy data structures. */
+ fdset_destroy(w->pool.fds);
+ ahtable_free(w->pool.t);
+ free(buf);
+
+ dbg_xfr_verb("xfr: worker=%p finished.\n", w);
+ return KNOT_EOK;
}
/*
@@ -1159,512 +1092,250 @@ static void xfr_worker_free(xfrworker_t *w) {
xfrhandler_t *xfr_create(size_t thrcount, knot_nameserver_t *ns)
{
/* Create XFR handler data. */
- xfrhandler_t *data = malloc(sizeof(xfrhandler_t));
- if (data == NULL) {
+ const size_t total_size = sizeof(xfrhandler_t) + thrcount * sizeof(xfrworker_t);
+ xfrhandler_t *xfr = malloc(total_size);
+ if (xfr == NULL) {
return NULL;
}
- memset(data, 0, sizeof(xfrhandler_t));
-
- /* Create RR mutex. */
- pthread_mutex_init(&data->rr_mx, 0);
+ memset(xfr, 0, total_size);
+ xfr->ns = ns;
- /* Create tasks structure and mutex. */
- pthread_mutex_init(&data->tasks_mx, 0);
- data->tasks = skip_create_list(xfr_fd_compare);
-
- /* Initialize threads. */
- data->workers = malloc(thrcount * sizeof(xfrhandler_t*));
- if(data->workers == NULL) {
- pthread_mutex_destroy(&data->rr_mx);
- free(data);
- return NULL;
- }
-
/* Create threading unit. */
- dt_unit_t *unit = dt_create(thrcount);
- if (unit == NULL) {
- pthread_mutex_destroy(&data->rr_mx);
- free(data->workers);
- free(data);
+ xfr->unit = dt_create(thrcount);
+ if (xfr->unit == NULL) {
+ free(xfr);
return NULL;
}
- data->unit = unit;
-
+
/* Create worker threads. */
- unsigned initialized = 0;
for (unsigned i = 0; i < thrcount; ++i) {
- data->workers[i] = xfr_worker_create(data, ns);
- if(data->workers[i] == 0) {
- break;
- }
- ++initialized;
+ xfrworker_t *w = xfr->workers + i;
+ w->master = xfr;
}
-
- /* Check for initialized. */
- if (initialized != thrcount) {
- for (unsigned i = 0; i < initialized; ++i) {
- xfr_worker_free(data->workers[i]);
- }
- pthread_mutex_destroy(&data->rr_mx);
- free(data->workers);
- free(data->unit);
- free(data);
- return NULL;
- }
-
+
+ /* Create tasks structure and mutex. */
+ pthread_mutex_init(&xfr->mx, 0);
+ init_list(&xfr->queue);
+
/* Assign worker threads. */
+ dthread_t **threads = xfr->unit->threads;
for (unsigned i = 0; i < thrcount; ++i) {
- dt_repurpose(unit->threads[i], xfr_worker, data->workers[i]);
+ dt_repurpose(threads[i], xfr_worker, xfr->workers + i);
}
-
- data->interrupt = xfr_interrupt;
- return data;
+ return xfr;
}
-int xfr_free(xfrhandler_t *handler)
+int xfr_free(xfrhandler_t *xfr)
{
- if (!handler) {
+ if (!xfr) {
return KNOT_EINVAL;
}
-
+
/* Free RR mutex. */
- pthread_mutex_destroy(&handler->rr_mx);
+ pthread_mutex_destroy(&xfr->mx);
- /* Free tasks and mutex. */
- skip_destroy_list(&handler->tasks, 0,
- (void(*)(void*))xfr_free_task);
- pthread_mutex_destroy(&handler->tasks_mx);
-
- /* Free workers. */
- for (unsigned i = 0; i < handler->unit->size; ++i) {
- xfr_worker_free(handler->workers[i]);
+ /* Free pending queue. */
+ knot_ns_xfr_t *n, *nxt;
+ WALK_LIST_DELSAFE(n, nxt, xfr->queue) {
+ xfr_task_free(n);
}
- free(handler->workers);
/* Delete unit. */
- dt_delete(&handler->unit);
- free(handler);
+ dt_delete(&xfr->unit);
+ free(xfr);
return KNOT_EOK;
}
-int xfr_stop(xfrhandler_t *handler)
+int xfr_stop(xfrhandler_t *xfr)
{
- /* Break loop. */
- dt_stop(handler->unit);
- return KNOT_EOK;
-}
+ if (!xfr) {
+ return KNOT_EINVAL;
+ }
-int xfr_join(xfrhandler_t *handler) {
- return dt_join(handler->unit);
+ xfr_enqueue(xfr, NULL);
+ return dt_stop(xfr->unit);
}
-int xfr_request_init(knot_ns_xfr_t *r, int type, int flags, knot_packet_t *pkt)
-{
- if (!r || type < 0 || flags < 0) {
- return KNOT_EINVAL;
- }
-
- /* Blank and init. */
- memset(r, 0, sizeof(knot_ns_xfr_t));
- r->type = type;
- r->flags = flags;
-
- /* Copy packet if applicable. */
- if (pkt != 0) {
- uint8_t *wire_copy = malloc(sizeof(uint8_t) * pkt->size);
- if (!wire_copy) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
- }
- memcpy(wire_copy, pkt->wireformat, pkt->size);
- pkt->wireformat = wire_copy;
- r->query = pkt;
- }
-
- return KNOT_EOK;
+int xfr_join(xfrhandler_t *xfr) {
+ return dt_join(xfr->unit);
}
-int xfr_request(xfrhandler_t *handler, knot_ns_xfr_t *req)
+int xfr_enqueue(xfrhandler_t *xfr, knot_ns_xfr_t *rq)
{
- if (!handler || !req) {
+ if (!xfr) {
return KNOT_EINVAL;
}
-
- /* Assign UDP requests to handler 0. */
- evqueue_t *q = handler->workers[0]->q;
- if (!(req->flags & XFR_FLAG_UDP)) {
- /* Get next worker in RR fashion */
- pthread_mutex_lock(&handler->rr_mx);
- q = handler->workers[handler->rr + 1]->q;
- handler->rr = get_next_rr(handler->rr, handler->unit->size - 1);
- pthread_mutex_unlock(&handler->rr_mx);
+
+ if (rq) {
+ pthread_mutex_lock(&xfr->mx);
+ add_tail(&xfr->queue, &rq->n);
+ pthread_mutex_unlock(&xfr->mx);
}
-
- /* Delegate request. */
- int ret = evqueue_write(q, req, sizeof(knot_ns_xfr_t));
- if (ret < 0) {
- return KNOT_ERROR;
+
+ /* Notify threads. */
+ for (unsigned i = 0; i < xfr->unit->size; ++i) {
+ dt_activate(xfr->unit->threads[i]);
}
return KNOT_EOK;
}
-int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
+int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *rq)
{
- if (ns == NULL || xfr == NULL) {
+ if (!ns || !rq) {
return KNOT_EINVAL;
}
-
- rcu_read_lock();
- int ret = knot_ns_init_xfr(ns, xfr);
- int xfr_failed = (ret != KNOT_EOK);
- const char *errstr = knot_strerror(ret);
+ gettimeofday(&rq->t_start, NULL);
+ rcu_read_lock(); /* About to guess zone from QNAME, so needs RCU. */
+ int ret = knot_ns_init_xfr(ns, rq);
+ rcu_read_unlock(); /* Now, the zone is either refcounted or NULL. */
- // use the QNAME as the zone name to get names also for
- // zones that are not in the server
- const knot_dname_t *qname = knot_packet_qname(xfr->query);
+ /* Use the QNAME as the zone name. */
+ const knot_dname_t *qname = knot_packet_qname(rq->query);
if (qname != NULL) {
- xfr->zname = knot_dname_to_str(qname);
+ rq->zname = knot_dname_to_str(qname);
} else {
- xfr->zname = strdup("(unknown)");
+ rq->zname = strdup("(unknown)");
}
/* Check requested zone. */
- if (!xfr_failed) {
- int zcheck_ret = zones_xfr_check_zone(xfr, &xfr->rcode);
- xfr_failed = (zcheck_ret != KNOT_EOK);
- errstr = knot_strerror(zcheck_ret);
+ if (ret == KNOT_EOK) {
+ ret = zones_xfr_check_zone(rq, &rq->rcode);
}
/* Check TSIG. */
char *keytag = NULL;
- if (!xfr_failed && xfr->tsig_key != NULL) {
- ret = xfr_check_tsig(xfr, &xfr->rcode, &keytag);
- xfr_failed = (ret != KNOT_EOK);
- errstr = knot_strerror(ret);
+ if (ret == KNOT_EOK && rq->tsig_key != NULL) {
+ ret = xfr_check_tsig(rq, &rq->rcode, &keytag);
}
-
- if (xfr_update_msgpref(xfr, keytag) != KNOT_EOK) {
- xfr->msgpref = strdup("XFR:");
+ if (xfr_task_setmsg(rq, keytag) != KNOT_EOK) {
+ rq->msg = strdup("XFR:");
}
free(keytag);
-
+
+ /* Initialize response. */
+ if (ret == KNOT_EOK) {
+ ret = knot_ns_init_xfr_resp(ns, rq);
+ }
+
+ /* Update request. */
+ rq->send = &xfr_send_udp;
+ rq->recv = &xfr_recv_udp;
+ if (rq->flags & XFR_FLAG_TCP) {
+ rq->send = &xfr_send_tcp;
+ rq->recv = &xfr_recv_tcp;
+ }
+
/* Announce. */
- log_server_info("%s Started.\n", xfr->msgpref);
switch (ret) {
- case KNOT_EXFRDENIED:
+ case KNOT_EDENIED:
log_server_info("%s TSIG required, but not found in query.\n",
- xfr->msgpref);
- break;
- case KNOT_TSIG_EBADKEY:
- log_server_info("%s Unsupported digest "
- "algorithm requested, "
- "treating as bad key.\n",
- xfr->msgpref);
+ rq->msg);
break;
default:
break;
}
-
- /* Prepare place for TSIG data */
- xfr->tsig_data = malloc(KNOT_NS_TSIG_DATA_MAX_SIZE);
- if (xfr->tsig_data) {
- dbg_xfr("xfr: TSIG data allocated: %zu.\n",
- KNOT_NS_TSIG_DATA_MAX_SIZE);
- xfr->tsig_data_size = 0;
- } else {
- dbg_xfr("xfr: failed to allocate TSIG data "
- "buffer (%zu kB)\n",
- KNOT_NS_TSIG_DATA_MAX_SIZE / 1024);
- }
-
+
/* Finally, answer AXFR/IXFR. */
- if (!xfr_failed) {
- switch(xfr->type) {
+ const knot_zone_contents_t *cont = knot_zone_contents(rq->zone);
+ if (ret == KNOT_EOK) {
+ switch(rq->type) {
case XFR_TYPE_AOUT:
- ret = xfr_answer_axfr(ns, xfr);
+ log_server_info("%s Started (serial %u).\n", rq->msg,
+ knot_zone_serial(cont));
+ ret = xfr_answer_axfr(ns, rq);
break;
case XFR_TYPE_IOUT:
- ret = xfr_answer_ixfr(ns, xfr);
+ ret = xfr_answer_ixfr(ns, rq);
break;
default:
ret = KNOT_ENOTSUP;
break;
}
-
- xfr_failed = (ret != KNOT_EOK);
- errstr = knot_strerror(ret);
} else {
- knot_ns_error_response_from_query(ns, xfr->query, xfr->rcode,
- xfr->wire, &xfr->wire_size);
/*! \todo Sign with TSIG for some errors. */
- ret = xfr->send(xfr->session, &xfr->addr, xfr->wire, xfr->wire_size);
+ knot_ns_error_response_from_query(ns, rq->query, rq->rcode,
+ rq->wire, &rq->wire_size);
+ rq->send(rq->session, &rq->addr, rq->wire, rq->wire_size);
}
-
+
/* Check results. */
- if (xfr_failed) {
- log_server_notice("%s %s\n", xfr->msgpref, errstr);
+ gettimeofday(&rq->t_end, NULL);
+ if (ret != KNOT_EOK) {
+ log_server_notice("%s %s\n", rq->msg, knot_strerror(ret));
} else {
- log_server_info("%s Finished.\n", xfr->msgpref);
- }
-
- /* Free allocated data. */
- free(xfr->tsig_data);
- xfr->tsig_data = NULL;
- xfr_request_deinit(xfr);
- rcu_read_unlock();
-
- /* Cleanup. */
- free(xfr->digest);
- free(xfr->query->wireformat); /* Free wireformat. */
- knot_packet_free(&xfr->query); /* Free query. */
- knot_packet_free(&xfr->response); /* Free response. */
- knot_free_changesets((knot_changesets_t **)(&xfr->data));
- free(xfr->zname);
- if (xfr_failed) {
- return KNOT_ERROR;
- }
-
- return KNOT_EOK;
-}
-
-static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
-{
- /* Read single request. */
- knot_ns_xfr_t xfr = {};
- int ret = evqueue_read(w->q, &xfr, sizeof(knot_ns_xfr_t));
- if (ret != sizeof(knot_ns_xfr_t)) {
- dbg_xfr_verb("xfr: evqueue_read() returned %d.\n", ret);
- return KNOT_ENOTRUNNING;
- }
-
- rcu_read_lock();
-
- /* Update request. */
- xfr.wire = buf;
- xfr.wire_size = buflen;
-
- /* Update XFR message prefix. */
- xfr_update_msgpref(&xfr, NULL);
-
- /* Check if not already processing. */
- zonedata_t *zd = (zonedata_t *)knot_zone_data(xfr.zone);
-
- /* Check if the zone is not discarded. */
- if (knot_zone_flags(xfr.zone) & KNOT_ZONE_DISCARDED) {
- xfr_request_deinit(&xfr);
- knot_zone_release(xfr.zone);
- rcu_read_unlock();
- return KNOT_EOK;
+ log_server_info("%s Finished in %.02fs.\n",
+ rq->msg,
+ time_diff(&rq->t_start, &rq->t_end) / 1000.0);
}
- /* Handle request. */
- knot_ns_xfr_t *task = NULL;
- dbg_xfr("%s processing request type '%d'\n", xfr.msgpref, xfr.type);
- dbg_xfr_verb("%s query ptr: %p\n", xfr.msgpref, xfr.query);
- switch(xfr.type) {
- case XFR_TYPE_AIN:
- case XFR_TYPE_IIN:
- ret = xfr_client_start(w, &xfr);
-
- /* Report. */
- if (ret != KNOT_EOK && ret != KNOT_EACCES) {
- if (zd != NULL && !knot_zone_contents(xfr.zone)) {
- /* Reschedule request delay. */
- int tmr_s = AXFR_BOOTSTRAP_RETRY;
- tmr_s += (int)((tmr_s) * tls_rand());
- event_t *ev = zd->xfr_in.timer;
- if (ev) {
- evsched_cancel(ev->parent, ev);
- evsched_schedule(ev->parent, ev, tmr_s);
- }
- log_zone_notice("%s Bootstrap failed, next "
- "attempt in %d seconds.\n",
- xfr.msgpref, tmr_s / 1000);
- } else {
- log_server_error("%s %s\n",
- xfr.msgpref, knot_strerror(ret));
- }
- knot_zone_release(xfr.zone); /* No further access to zone. */
- }
-
- break;
- case XFR_TYPE_SOA:
- case XFR_TYPE_NOTIFY:
- case XFR_TYPE_FORWARD:
- /* Register task. */
- task = xfr_register_task(w, &xfr);
- if (!task) {
- knot_zone_release(xfr.zone); /* No further access to zone. */
- ret = KNOT_ENOMEM;
- } else {
- /* Add timeout. */
- rcu_read_lock();
- fdset_set_watchdog(w->fdset, task->session,
- conf()->max_conn_reply);
- rcu_read_unlock();
- if (xfr.type == XFR_TYPE_FORWARD) {
- log_server_info("%s Forwarded query.\n",
- xfr.msgpref);
- } else {
- log_server_info("%s Query issued.\n",
- xfr.msgpref);
- }
- ret = KNOT_EOK;
- }
- break;
- default:
- log_server_error("Unknown XFR request type (%d).\n", xfr.type);
- break;
- }
+ /* Cleanup. */
+ knot_packet_free(&rq->response); /* Free response. */
+ knot_free_changesets((knot_changesets_t **)(&rq->data));
+ free(rq->zname);
- rcu_read_unlock();
-
- /* Deinitialize (it is already registered, or discarded).
- * Right now, this only frees temporary msgpref.
- */
- xfr_request_deinit(&xfr);
-
+ /* Free request. */
+ xfr_task_free(rq);
return ret;
}
-int xfr_worker(dthread_t *thread)
+knot_ns_xfr_t *xfr_task_create(knot_zone_t *z, int type, int flags)
{
- xfrworker_t *w = (xfrworker_t *)thread->data;
+ knot_ns_xfr_t *rq = malloc(sizeof(knot_ns_xfr_t));
+ if (rq == NULL) return NULL;
+ memset(rq, 0, sizeof(knot_ns_xfr_t));
+
+ /* Initialize. */
+ rq->type = type;
+ rq->flags = flags;
+ if (z) {
+ rq->zone = z;
+ knot_zone_retain(rq->zone);
+ }
+ return rq;
+}
- /* Check data. */
- if (w < 0) {
- dbg_xfr("xfr: NULL worker data, worker cancelled\n");
+int xfr_task_free(knot_ns_xfr_t *rq)
+{
+ if (!rq) {
return KNOT_EINVAL;
}
- /* Buffer for answering. */
- size_t buflen = XFR_BUFFER_SIZE;
- uint8_t* buf = malloc(buflen);
- if (buf == NULL) {
- dbg_xfr("xfr: failed to allocate buffer for XFR worker\n");
- return KNOT_ENOMEM;
- }
-
- /* Next sweep time. */
- timev_t next_sweep;
- time_now(&next_sweep);
- next_sweep.tv_sec += XFR_SWEEP_INTERVAL;
+ /* Free DNAME trie. */
+ hattrie_free(rq->lookup_tree);
+ rq->lookup_tree = NULL;
- /* Accept requests. */
- int ret = 0;
- dbg_xfr_verb("xfr: worker=%p starting\n", w);
- for (;;) {
-
- /* Check for cancellation. */
- if (dt_is_cancelled(thread)) {
- break;
- }
-
- /* Poll fdset. */
- int nfds = fdset_wait(w->fdset, (XFR_SWEEP_INTERVAL * 1000)/2);
- if (nfds < 0) {
- continue;
- }
-
- /* Check for cancellation. */
- if (dt_is_cancelled(thread)) {
- break;
- }
-
- /* Iterate fdset. */
- knot_ns_xfr_t *data = 0;
- int rfd = evqueue_pollfd(w->q);
- fdset_it_t it = {0};
- fdset_begin(w->fdset, &it);
- int rfd_event = 0;
- while(nfds > 0) {
- /* Check if it request. */
- if (it.fd == rfd) {
- rfd_event = 1; /* Delay new tasks after processing. */
- } else {
- /* Find data. */
- data = xfr_handler_task(w, it.fd);
- if (data == NULL) {
- /* Next fd. */
- if (fdset_next(w->fdset, &it) < 0) {
- break;
- } else {
- continue;
- }
- }
- dbg_xfr_verb("xfr: worker=%p processing event on "
- "fd=%d data=%p.\n",
- w, it.fd, data);
- ret = xfr_process_event(w, it.fd, data, buf, buflen);
- if (ret != KNOT_EOK) {
- xfr_free_task(data);
- /*! \todo Refactor to allow erase on iterator.*/
- break;
- }
- }
-
- /* Next fd. */
- if (fdset_next(w->fdset, &it) < 0) {
- break;
- }
- }
-
- /* Lazily process new tasks. */
- if (rfd_event) {
- dbg_xfr_verb("xfr: worker=%p processing request\n", w);
- ret = xfr_process_request(w, buf, buflen);
- }
-
- /* Sweep inactive. */
- timev_t now;
- if (time_now(&now) == 0) {
- if (now.tv_sec >= next_sweep.tv_sec) {
- fdset_sweep(w->fdset, &xfr_sweep, w);
- memcpy(&next_sweep, &now, sizeof(next_sweep));
- next_sweep.tv_sec += XFR_SWEEP_INTERVAL;
- }
- }
-
- /* Check for interrupt request. */
- if (ret == KNOT_ENOTRUNNING) {
- break;
- }
- }
+ /* Free TSIG buffers. */
+ free(rq->digest);
+ rq->digest = NULL;
+ rq->digest_size = 0;
+ free(rq->tsig_data);
+ rq->tsig_data = NULL;
+ rq->tsig_data_size = 0;
- /* Stop whole unit. */
- free(buf);
- dbg_xfr_verb("xfr: worker=%p finished.\n", w);
- thread->data = 0;
+ /* Cleanup transfer-specifics. */
+ xfr_task_cleanup(rq);
+
+ /* No further access to zone. */
+ knot_zone_release(rq->zone);
+ free(rq->msg);
+ rq->msg = NULL;
+ free(rq);
return KNOT_EOK;
}
-int xfr_prepare_tsig(knot_ns_xfr_t *xfr, knot_key_t *key)
+int xfr_task_setaddr(knot_ns_xfr_t *rq, sockaddr_t *to, sockaddr_t *from)
{
- if (xfr == NULL || key == NULL) {
+ if (!rq) {
return KNOT_EINVAL;
}
-
- int ret = KNOT_EOK;
- xfr->tsig_key = key;
- xfr->tsig_size = tsig_wire_maxsize(key);
- xfr->digest_max_size = tsig_alg_digest_length(
- key->algorithm);
- xfr->digest = malloc(xfr->digest_max_size);
- if (xfr->digest == NULL) {
- xfr->tsig_key = NULL;
- xfr->tsig_size = 0;
- xfr->digest_max_size = 0;
- return KNOT_ENOMEM;
- }
- memset(xfr->digest, 0 , xfr->digest_max_size);
- dbg_xfr("xfr: found TSIG key (MAC len=%zu), adding to transfer\n",
- xfr->digest_max_size);
-
- return ret;
+
+ memcpy(&rq->addr, to, sizeof(sockaddr_t));
+ if (from) memcpy(&rq->saddr, from, sizeof(sockaddr_t));
+ return KNOT_EOK;
}
char *xfr_remote_str(const sockaddr_t *addr, const char *key)
@@ -1672,12 +1343,12 @@ char *xfr_remote_str(const sockaddr_t *addr, const char *key)
if (!addr) {
return NULL;
}
-
+
/* Prepare address strings. */
char r_addr[SOCKADDR_STRLEN];
int r_port = sockaddr_portnum(addr);
sockaddr_tostr(addr, r_addr, sizeof(r_addr));
-
+
/* Prepare key strings. */
char *tag = "";
char *q = "'";
@@ -1687,6 +1358,6 @@ char *xfr_remote_str(const sockaddr_t *addr, const char *key)
key = tag; /* Both empty. */
q = tag;
}
-
+
return sprintf_alloc("'%s@%d'%s%s%s%s", r_addr, r_port, tag, q, key, q);
}
diff --git a/src/knot/server/xfr-handler.h b/src/knot/server/xfr-handler.h
index 9f52752..2042605 100644
--- a/src/knot/server/xfr-handler.h
+++ b/src/knot/server/xfr-handler.h
@@ -32,17 +32,27 @@
#include "common/evqueue.h"
#include "common/fdset.h"
#include "common/skip-list.h"
+#include "common/hattrie/ahtable.h"
struct xfrhandler_t;
+/*! \brief Transfer state. */
+enum xfrstate_t {
+ XFR_IDLE = 0,
+ XFR_SCHED,
+ XFR_PENDING,
+};
+
/*!
* \brief XFR worker structure.
*/
typedef struct xfrworker_t
{
- knot_nameserver_t *ns; /*!< \brief Pointer to nameserver.*/
- evqueue_t *q; /*!< \brief Shared XFR requests queue.*/
- fdset_t *fdset; /*!< \brief File descriptor set. */
+ struct {
+ ahtable_t *t;
+ fdset_t *fds;
+ } pool;
+ unsigned pending;
struct xfrhandler_t *master; /*! \brief Worker master. */
} xfrworker_t;
@@ -51,13 +61,11 @@ typedef struct xfrworker_t
*/
typedef struct xfrhandler_t
{
+ list queue;
+ pthread_mutex_t mx; /*!< \brief Tasks synchronisation. */
+ knot_nameserver_t *ns;
dt_unit_t *unit; /*!< \brief Threading unit. */
- xfrworker_t **workers; /*!< \brief Workers. */
- skip_list_t *tasks; /*!< \brief Pending tasks. */
- pthread_mutex_t tasks_mx; /*!< \brief Tasks synchronisation. */
- void (*interrupt)(struct xfrhandler_t *h); /*!< Interrupt handler. */
- unsigned rr; /*!< \brief Round-Robin counter. */
- pthread_mutex_t rr_mx; /*!< \brief RR mutex. */
+ xfrworker_t workers[]; /*!< \brief Workers. */
} xfrhandler_t;
/*!
@@ -79,71 +87,57 @@ xfrhandler_t *xfr_create(size_t thrcount, knot_nameserver_t *ns);
*
* \warning Threading unit must be stopped and joined.
*
- * \param handler XFR handler.
+ * \param xfr XFR handler.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EINVAL on NULL handler.
* \retval KNOT_ERROR on error.
*/
-int xfr_free(xfrhandler_t *handler);
+int xfr_free(xfrhandler_t *xfr);
/*!
* \brief Start XFR handler.
*
- * \param handler XFR handler.
+ * \param xfr XFR handler.
*
* \retval KNOT_EOK on success.
* \retval KNOT_ERROR on error.
*/
-static inline int xfr_start(xfrhandler_t *handler) {
- return dt_start(handler->unit);
+static inline int xfr_start(xfrhandler_t *xfr) {
+ return dt_start(xfr->unit);
}
/*!
* \brief Stop XFR handler.
*
- * \param handler XFR handler.
+ * \param xfr XFR handler.
*
* \retval KNOT_EOK on success.
* \retval KNOT_ERROR on error.
*/
-int xfr_stop(xfrhandler_t *handler);
+int xfr_stop(xfrhandler_t *xfr);
/*!
* \brief Wait for XFR handler to finish.
*
- * \param handler XFR handler.
+ * \param xfr XFR handler.
*
* \retval KNOT_EOK on success.
* \retval KNOT_ERROR on error.
*/
-int xfr_join(xfrhandler_t *handler);
-
-/*!
- * \brief Prepare XFR request.
- *
- * \param r XFR request.
- * \param type Request type.
- * \param flags Request flags.
- * \param pkt Query packet or NULL.
- *
- * \retval KNOT_EOK
- * \retval KNOT_ENOMEM
- * \retval KNOT_EINVAL
- */
-int xfr_request_init(knot_ns_xfr_t *r, int type, int flags, knot_packet_t *pkt);
+int xfr_join(xfrhandler_t *xfr);
/*!
* \brief Enqueue XFR request.
*
- * \param handler XFR handler instance.
+ * \param xfr XFR handler instance.
* \param req XFR request.
*
* \retval KNOT_EOK on success.
* \retval KNOT_EINVAL on NULL handler or request.
* \retval KNOT_ERROR on error.
*/
-int xfr_request(xfrhandler_t *handler, knot_ns_xfr_t *req);
+int xfr_enqueue(xfrhandler_t *xfr, knot_ns_xfr_t *rq);
/*!
* \brief Answer XFR query.
@@ -155,34 +149,38 @@ int xfr_request(xfrhandler_t *handler, knot_ns_xfr_t *req);
* \retval KNOT_EINVAL on NULL handler or request.
* \retval KNOT_ERROR on error.
*/
-int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *req);
+int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *rq);
/*!
- * \brief XFR master runnable.
- *
- * Processes incoming AXFR/IXFR requests asynchonously.
- * When no thread is available at the moment, request is enqueued.
+ * \brief Prepare XFR request.
*
- * \param thread Associated thread from DThreads unit.
+ * \param z Related zone.
+ * \param type Request type.
+ * \param flags Request flags.
*
- * \retval KNOT_EOK on success.
- * \retval KNOT_EINVAL invalid parameters.
+ * \return new request
*/
-int xfr_worker(dthread_t *thread);
+knot_ns_xfr_t *xfr_task_create(knot_zone_t *z, int type, int flags);
/*!
- * \brief Prepare TSIG for XFR.
- * \param xfr XFR request.
- * \param key Used TSIG key.
+ * \brief Free XFR request.
+ * \param rq Request.
+ * \return KNOT_EOK or KNOT_EINVAL
+ */
+int xfr_task_free(knot_ns_xfr_t *rq);
+
+/*!
+ * \brief Set XFR request destination/source address.
*
- * \retval KNOT_EOK on success.
- * \retval KNOT_EINVAL on NULL parameters.
- * \retval KNOT_ENOMEM when out of memory.
+ * \param rq XFR request,
+ * \param to Destination address.
+ * \param from Source address.
+ * \return
*/
-int xfr_prepare_tsig(knot_ns_xfr_t *xfr, knot_key_t *key);
+int xfr_task_setaddr(knot_ns_xfr_t *rq, sockaddr_t *to, sockaddr_t *from);
/*!
- * \brief Return formatted string of the remote as 'ip@port key $key'.
+ * \brief Return formatted string of the remote as 'ip\@port key $key'.
*
* \param addr Remote address.
* \param keytag Used TSIG key name (or NULL).
diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c
index a06484d..d1a3bf6 100644
--- a/src/knot/server/zones.c
+++ b/src/knot/server/zones.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -21,7 +22,7 @@
#include "common/prng.h"
#include "libknot/dname.h"
#include "libknot/util/wire.h"
-#include "knot/zone/zone-dump-text.h"
+#include "knot/zone/zone-dump.h"
#include "knot/zone/zone-load.h"
#include "libknot/zone/zone.h"
#include "libknot/zone/zonedb.h"
@@ -30,42 +31,24 @@
#include "common/log.h"
#include "knot/server/notify.h"
#include "knot/server/server.h"
+#include "knot/server/xfr-handler.h"
#include "libknot/updates/xfr-in.h"
#include "knot/server/zones.h"
-#include "knot/zone/zone-dump.h"
#include "libknot/nameserver/name-server.h"
+#include "libknot/nameserver/chaos.h"
#include "libknot/updates/changesets.h"
#include "libknot/tsig-op.h"
+#include "common/descriptor.h"
#include "libknot/packet/response.h"
#include "libknot/zone/zone-diff.h"
#include "libknot/updates/ddns.h"
static const size_t XFRIN_CHANGESET_BINARY_SIZE = 100;
static const size_t XFRIN_CHANGESET_BINARY_STEP = 100;
-static const size_t XFRIN_BOOTSTRAP_DELAY = 60; /*!< AXFR bootstrap avg. delay */
+static const size_t XFRIN_BOOTSTRAP_DELAY = 2000; /*!< AXFR bootstrap avg. delay */
/* Forward declarations. */
static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *zf);
-static int zones_dump_zone_binary(knot_zone_contents_t *zone,
- const char *zonedb,
- const char *zonefile);
-/*----------------------------------------------------------------------------*/
-
-/*!
- * \brief Wrapper for TCP send.
- */
-#include "knot/server/tcp-handler.h"
-static int zones_send_cb(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
-{
- return tcp_send(fd, msg, msglen);
-}
-
-static int zones_send_udp(int fd, sockaddr_t *addr, uint8_t *msg, size_t msglen)
-{
- return sendto(fd, msg, msglen, 0, addr->ptr, addr->len);
-}
-
-/*----------------------------------------------------------------------------*/
/*! \brief Zone data destructor function. */
static int zonedata_destroy(knot_zone_t *zone)
@@ -73,9 +56,9 @@ static int zonedata_destroy(knot_zone_t *zone)
if (zone == NULL) {
return KNOT_EINVAL;
}
-
+
dbg_zones_verb("zones: zonedata_destroy(%p) called\n", zone);
-
+
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
if (!zd) {
return KNOT_EINVAL;
@@ -96,14 +79,6 @@ static int zonedata_destroy(knot_zone_t *zone)
evsched_event_free(sch, zd->xfr_in.expire);
zd->xfr_in.expire = 0;
}
-
- /* Remove list of pending NOTIFYs. */
- pthread_mutex_lock(&zd->lock);
- notify_ev_t *ev = 0, *evn = 0;
- WALK_LIST_DELSAFE(ev, evn, zd->notify_pending) {
- zones_cancel_notify(zd, ev);
- }
- pthread_mutex_unlock(&zd->lock);
/* Cancel IXFR DB sync timer. */
if (zd->ixfr_dbsync) {
@@ -113,27 +88,21 @@ static int zonedata_destroy(knot_zone_t *zone)
zd->ixfr_dbsync = 0;
}
- /* Destroy mutex. */
- pthread_mutex_destroy(&zd->lock);
- pthread_mutex_destroy(&zd->xfr_in.lock);
-
acl_delete(&zd->xfr_in.acl);
acl_delete(&zd->xfr_out);
acl_delete(&zd->notify_in);
acl_delete(&zd->notify_out);
acl_delete(&zd->update_in);
+ pthread_mutex_destroy(&zd->lock);
/* Close IXFR db. */
journal_release(zd->ixfr_db);
-
+
/* Free assigned config. */
conf_free_zone(zd->conf);
free(zd);
-
- /* Invalidate. */
zone->data = 0;
-
return KNOT_EOK;
}
@@ -166,25 +135,20 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
sockaddr_init(&zd->xfr_in.master, -1);
zd->xfr_in.timer = 0;
zd->xfr_in.expire = 0;
- zd->xfr_in.next_id = -1;
zd->xfr_in.acl = 0;
- zd->xfr_in.wrkr = 0;
- zd->xfr_in.bootstrap_retry = (XFRIN_BOOTSTRAP_DELAY * tls_rand() + 5)
- * 1000;
- pthread_mutex_init(&zd->xfr_in.lock, 0);
-
- /* Initialize NOTIFY. */
- init_list(&zd->notify_pending);
+ zd->xfr_in.bootstrap_retry = (XFRIN_BOOTSTRAP_DELAY * tls_rand());
/* Initialize IXFR database. */
zd->ixfr_db = journal_open(cfg->ixfr_db, cfg->ixfr_fslimit,
JOURNAL_LAZY, JOURNAL_DIRTY);
-
+
if (zd->ixfr_db == NULL) {
char ebuf[256] = {0};
- strerror_r(errno, ebuf, sizeof(ebuf));
- log_server_warning("Couldn't open journal file for zone '%s', "
- "disabling incoming IXFR. (%s)\n", cfg->name, ebuf);
+ if (strerror_r(errno, ebuf, sizeof(ebuf)) == 0) {
+ log_server_warning("Couldn't open journal file for "
+ "zone '%s', disabling incoming "
+ "IXFR. (%s)\n", cfg->name, ebuf);
+ }
}
/* Initialize IXFR database syncing event. */
@@ -196,7 +160,6 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
/* Set zonefile SOA serial. */
const knot_rrset_t *soa_rrs = 0;
- const knot_rdata_t *soa_rr = 0;
/* Load serial. */
zd->zonefile_serial = 0;
@@ -205,8 +168,7 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
soa_rrs = knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
assert(soa_rrs != NULL);
- soa_rr = knot_rrset_rdata(soa_rrs);
- int64_t serial = knot_rdata_soa_serial(soa_rr);
+ int64_t serial = knot_rrset_rdata_soa_serial(soa_rrs);
zd->zonefile_serial = (uint32_t)serial;
if (serial < 0) {
return KNOT_EINVAL;
@@ -226,7 +188,7 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
*/
static uint32_t zones_jitter(uint32_t interval)
{
- return (interval * (100 - (tls_rand() * ZONES_JITTER_PCT))) / 100;
+ return (interval * (100 - (tls_rand() * ZONES_JITTER_PCT))) / 100;
}
/*!
@@ -237,7 +199,7 @@ static uint32_t zones_jitter(uint32_t interval)
* \return Timer in miliseconds.
*/
static uint32_t zones_soa_timer(knot_zone_t *zone,
- uint32_t (*rr_func)(const knot_rdata_t*))
+ uint32_t (*rr_func)(const knot_rrset_t*))
{
if (!zone) {
dbg_zones_verb("zones: zones_soa_timer() called "
@@ -248,7 +210,6 @@ static uint32_t zones_soa_timer(knot_zone_t *zone,
/* Retrieve SOA RDATA. */
const knot_rrset_t *soa_rrs = 0;
- const knot_rdata_t *soa_rr = 0;
rcu_read_lock();
@@ -261,8 +222,7 @@ static uint32_t zones_soa_timer(knot_zone_t *zone,
soa_rrs = knot_node_rrset(knot_zone_contents_apex(zc),
KNOT_RRTYPE_SOA);
assert(soa_rrs != NULL);
- soa_rr = knot_rrset_rdata(soa_rrs);
- ret = rr_func(soa_rr);
+ ret = rr_func(soa_rrs);
rcu_read_unlock();
@@ -278,7 +238,7 @@ static uint32_t zones_soa_timer(knot_zone_t *zone,
*/
static uint32_t zones_soa_refresh(knot_zone_t *zone)
{
- return zones_soa_timer(zone, knot_rdata_soa_refresh);
+ return zones_soa_timer(zone, knot_rrset_rdata_soa_refresh);
}
/*!
@@ -289,7 +249,7 @@ static uint32_t zones_soa_refresh(knot_zone_t *zone)
*/
static uint32_t zones_soa_retry(knot_zone_t *zone)
{
- return zones_soa_timer(zone, knot_rdata_soa_retry);
+ return zones_soa_timer(zone, knot_rrset_rdata_soa_retry);
}
/*!
@@ -300,7 +260,7 @@ static uint32_t zones_soa_retry(knot_zone_t *zone)
*/
static uint32_t zones_soa_expire(knot_zone_t *zone)
{
- return zones_soa_timer(zone, knot_rdata_soa_expire);
+ return zones_soa_timer(zone, knot_rrset_rdata_soa_expire);
}
/*!
@@ -309,68 +269,39 @@ static uint32_t zones_soa_expire(knot_zone_t *zone)
static int zones_expire_ev(event_t *e)
{
dbg_zones("zones: EXPIRE timer event\n");
- knot_zone_t *zone = (knot_zone_t *)e->data;
- if (zone == NULL || zone->data == NULL) {
+ if (e->data == NULL) {
return KNOT_EINVAL;
}
-
- zonedata_t *zd = (zonedata_t *)zone->data;
+
rcu_read_lock();
-
+ knot_zone_t *zone = (knot_zone_t *)e->data;
+ zonedata_t *zd = (zonedata_t *)zone->data;
+
/* Check if zone is not discarded. */
if (knot_zone_flags(zone) & KNOT_ZONE_DISCARDED) {
rcu_read_unlock();
return KNOT_EOK;
}
-
- /* Do not issue SOA query if transfer is pending. */
- int locked = pthread_mutex_trylock(&zd->xfr_in.lock);
- if (locked != 0) {
- dbg_zones("zones: zone '%s' is being transferred, "
- "deferring EXPIRE\n",
- zd->conf->name);
-
- /* Reschedule as EXPIRE timer. */
- uint32_t exp_tmr = zones_soa_expire(zone);
- evsched_schedule(e->parent, e, exp_tmr);
- dbg_zones("zones: EXPIRE of '%s' after %u seconds\n",
- zd->conf->name, exp_tmr / 1000);
-
- /* Unlock RCU. */
- rcu_read_unlock();
- return KNOT_EOK;
- }
- dbg_zones_verb("zones: zone %s locked, no xfers are running\n",
- zd->conf->name);
-
- /* Won't accept any pending SOA responses. */
- zd->xfr_in.next_id = -1;
+ knot_zone_retain(zone); /* Keep a reference. */
+ rcu_read_unlock();
+
/* Mark the zone as expired. This will remove the zone contents. */
knot_zone_contents_t *contents = knot_zonedb_expire_zone(
zd->server->nameserver->zone_db, zone->name);
- if (contents == NULL) {
- pthread_mutex_unlock(&zd->xfr_in.lock);
- log_server_warning("Non-existent zone expired. Ignoring.\n");
- rcu_read_unlock();
- return KNOT_EOK;
- }
-
- /* Publish expired zone. */
- /* Need to keep a reference in case zone get's deleted in meantime. */
- knot_zone_retain(zone);
- rcu_read_unlock();
- synchronize_rcu();
- rcu_read_lock();
-
- /* Log event. */
- log_server_info("Zone '%s' expired.\n", zd->conf->name);
-
/* Early finish this event to prevent lockup during cancellation. */
dbg_zones("zones: zone expired, removing from database\n");
evsched_event_finished(e->parent);
+ /* Publish expired zone, must be after evsched_event_finished.
+ * This is because some other thread may hold rcu_read_lock and
+ * wait for event cancellation. */
+ synchronize_rcu();
+
+ /* Log event. */
+ log_server_info("Zone '%s' expired.\n", zd->conf->name);
+
/* Cancel REFRESH timer. */
if (zd->xfr_in.timer) {
evsched_cancel(e->parent, zd->xfr_in.timer);
@@ -383,14 +314,11 @@ static int zones_expire_ev(event_t *e)
evsched_event_free(e->parent, zd->xfr_in.expire);
zd->xfr_in.expire = 0;
}
-
- knot_zone_contents_deep_free(&contents, 0);
- pthread_mutex_unlock(&zd->xfr_in.lock);
- rcu_read_unlock();
-
+
+ knot_zone_contents_deep_free(&contents);
+
/* Release holding reference. */
knot_zone_release(zone);
-
return KNOT_EOK;
}
@@ -407,94 +335,54 @@ static int zones_refresh_ev(event_t *e)
return KNOT_EINVAL;
}
- /* Cancel pending timers. */
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
-
/* Check if zone is not discarded. */
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
if (knot_zone_flags(zone) & KNOT_ZONE_DISCARDED) {
rcu_read_unlock();
return KNOT_EOK;
}
+ /* Create XFR request. */
+ knot_ns_xfr_t *rq = xfr_task_create(zone, XFR_TYPE_SOA, XFR_FLAG_UDP);
+ rcu_read_unlock(); /* rq now holds a reference to zone */
+ if (!rq) {
+ return KNOT_EINVAL;
+ }
+ xfr_task_setaddr(rq, &zd->xfr_in.master, &zd->xfr_in.via);
+ if (zd->xfr_in.tsig_key.name) {
+ rq->tsig_key = &zd->xfr_in.tsig_key;
+ }
+
/* Check for contents. */
+ int ret = KNOT_EOK;
if (!knot_zone_contents(zone)) {
- /* Bootstrap from XFR master. */
- knot_ns_xfr_t xfr_req;
- memset(&xfr_req, 0, sizeof(knot_ns_xfr_t));
- memcpy(&xfr_req.addr, &zd->xfr_in.master, sizeof(sockaddr_t));
- memcpy(&xfr_req.saddr, &zd->xfr_in.via, sizeof(sockaddr_t));
- xfr_req.data = (void *)zone;
- xfr_req.send = zones_send_cb;
-
- /* Select transfer method. */
- xfr_req.type = XFR_TYPE_AIN;
- xfr_req.zone = zone;
-
- /* Select TSIG key. */
- if (zd->xfr_in.tsig_key.name) {
- xfr_req.tsig_key = &zd->xfr_in.tsig_key;
- }
+ /* Bootstrap over TCP. */
+ rq->type = XFR_TYPE_AIN;
+ rq->flags = XFR_FLAG_TCP;
+ evsched_event_finished(e->parent);
- /* Enqueue XFR request. */
- int locked = pthread_mutex_trylock(&zd->xfr_in.lock);
- if (locked != 0) {
- dbg_zones("zones: already bootstrapping '%s'\n",
- zd->conf->name);
- rcu_read_unlock();
+ /* Check transfer state. */
+ pthread_mutex_lock(&zd->lock);
+ if (zd->xfr_in.state == XFR_PENDING) {
+ pthread_mutex_unlock(&zd->lock);
+ xfr_task_free(rq);
return KNOT_EOK;
+ } else {
+ zd->xfr_in.state = XFR_PENDING;
}
- if (zd->xfr_in.scheduled > 0) {
- /* Already pending bootstrap (unprocessed). */
- pthread_mutex_unlock(&zd->xfr_in.lock);
- dbg_zones("zones: already bootstrapping '%s' (q'd)\n",
- zd->conf->name);
- rcu_read_unlock();
- return KNOT_EOK;
- }
-
-// log_zone_info("Attempting to bootstrap zone %s from master\n",
-// zd->conf->name);
- ++zd->xfr_in.scheduled;
- pthread_mutex_unlock(&zd->xfr_in.lock);
-
- /* Retain pointer to zone for processing. */
- knot_zone_retain(xfr_req.zone);
-
- /* Unlock zone contents. */
- rcu_read_unlock();
-
- /* Mark as finished to prevent stalling. */
- evsched_event_finished(e->parent);
- int ret = xfr_request(zd->server->xfr_h, &xfr_req);
+ /* Issue request. */
+ ret = xfr_enqueue(zd->server->xfr, rq);
if (ret != KNOT_EOK) {
- knot_zone_release(xfr_req.zone); /* Discard */
+ xfr_task_free(rq);
+ zd->xfr_in.state = XFR_SCHED; /* Revert state. */
}
+ pthread_mutex_unlock(&zd->lock);
return ret;
-
- }
-
- /* Do not issue SOA query if transfer is pending. */
- int locked = pthread_mutex_trylock(&zd->xfr_in.lock);
- if (locked != 0) {
- dbg_zones("zones: zone '%s' is being transferred, "
- "deferring SOA query\n",
- zd->conf->name);
-
- /* Reschedule as RETRY timer. */
- uint32_t retry_tmr = zones_jitter(zones_soa_retry(zone));
- evsched_schedule(e->parent, e, retry_tmr);
- dbg_zones("zones: RETRY of '%s' after %u seconds\n",
- zd->conf->name, retry_tmr / 1000);
-
- /* Unlock RCU. */
- rcu_read_unlock();
- return KNOT_EOK;
- } else {
- pthread_mutex_unlock(&zd->xfr_in.lock);
+
}
-
+
/* Schedule EXPIRE timer on first attempt. */
if (!zd->xfr_in.expire) {
uint32_t expire_tmr = zones_jitter(zones_soa_expire(zone));
@@ -505,240 +393,23 @@ static int zones_refresh_ev(event_t *e)
dbg_zones("zones: EXPIRE of '%s' after %u seconds\n",
zd->conf->name, expire_tmr / 1000);
}
-
+
/* Reschedule as RETRY timer. */
uint32_t retry_tmr = zones_jitter(zones_soa_retry(zone));
evsched_schedule(e->parent, e, retry_tmr);
dbg_zones("zones: RETRY of '%s' after %u seconds\n",
zd->conf->name, retry_tmr / 1000);
-
- /* Prepare buffer for query. */
- uint8_t *qbuf = malloc(SOCKET_MTU_SZ);
- if (qbuf == NULL) {
- log_zone_error("Not enough memory to allocate SOA query.\n");
- rcu_read_unlock();
- return KNOT_ENOMEM;
- }
-
- size_t buflen = SOCKET_MTU_SZ;
-
- knot_ns_xfr_t req;
- memset(&req, 0, sizeof(knot_ns_xfr_t));
- req.wire = qbuf;
-
- /* Select TSIG key. */
- if (zd->xfr_in.tsig_key.name) {
- xfr_prepare_tsig(&req, &zd->xfr_in.tsig_key);
- }
-
- /* Create query. */
- int sock = -1;
- char strbuf[256] = "Generic error.";
- const char *errstr = strbuf;
- sockaddr_t *master = &zd->xfr_in.master;
- int ret = xfrin_create_soa_query(zone->name, &req, &buflen);
- if (ret == KNOT_EOK) {
- /* Create socket on random port. */
- sock = socket_create(master->family, SOCK_DGRAM);
-
- /* Check requested source. */
- sockaddr_t *via = &zd->xfr_in.via;
- if (via->len > 0) {
- if (bind(sock, via->ptr, via->len) < 0) {
- socket_close(sock);
- sock = -1;
- char r_addr[SOCKADDR_STRLEN];
- sockaddr_tostr(via, r_addr, sizeof(r_addr));
- snprintf(strbuf, sizeof(strbuf),
- "Couldn't bind to \'%s\'", r_addr);
- }
- }
- /* Send query. */
- ret = KNOT_ERROR;
- if (sock > -1) {
- int sent = sendto(sock, qbuf, buflen, 0,
- master->ptr, master->len);
-
- /* Store ID of the awaited response. */
- if (sent == buflen) {
- ret = KNOT_EOK;
- } else {
- strbuf[0] = '\0';
- strerror_r(errno, strbuf, sizeof(strbuf));
- socket_close(sock);
- sock = -1;
- }
- }
-
- /* Check result. */
- if (ret == KNOT_EOK) {
- zd->xfr_in.next_id = knot_wire_get_id(qbuf);
- dbg_zones("zones: expecting SOA response "
- "ID=%d for '%s'\n",
- zd->xfr_in.next_id, zd->conf->name);
- }
- } else {
- ret = KNOT_ERROR;
- errstr = "Couldn't create SOA query";
- }
-
-
- /* Mark as finished to prevent stalling. */
+ /* Issue request. */
evsched_event_finished(e->parent);
-
- /* Watch socket. */
- req.session = sock;
- req.type = XFR_TYPE_SOA;
- req.flags |= XFR_FLAG_UDP;
- req.zone = zone;
- req.wire = NULL;
- memcpy(&req.addr, master, sizeof(sockaddr_t));
- memcpy(&req.saddr, &zd->xfr_in.via, sizeof(sockaddr_t));
- sockaddr_update(&req.addr);
- sockaddr_update(&req.saddr);
-
- /* Retain pointer to zone and issue. */
- knot_zone_retain(req.zone);
- if (ret == KNOT_EOK) {
- ret = xfr_request(zd->server->xfr_h, &req);
- }
+ ret = xfr_enqueue(zd->server->xfr, rq);
if (ret != KNOT_EOK) {
- free(req.digest);
- knot_zone_release(req.zone); /* Discard */
- log_server_warning("Failed to issue SOA query for zone '%s' (%s).\n",
- zd->conf->name, errstr);
+ xfr_task_free(rq);
}
-
- free(qbuf);
-
- /* Unlock RCU. */
- rcu_read_unlock();
- return ret;
-}
-
-/*!
- * \brief Send NOTIFY to slave server.
- */
-static int zones_notify_send(event_t *e)
-{
- dbg_notify("notify: NOTIFY timer event\n");
- rcu_read_lock();
- notify_ev_t *ev = (notify_ev_t *)e->data;
- if (ev == NULL) {
- rcu_read_unlock();
- log_zone_error("NOTIFY invalid event received\n");
- return KNOT_EINVAL;
- }
-
- knot_zone_t *zone = ev->zone;
- if (zone == NULL || zone->data == NULL) {
- rcu_read_unlock();
- log_zone_error("NOTIFY invalid event data received\n");
- evsched_event_free(e->parent, e);
- free(ev);
- return KNOT_EINVAL;
- }
-
- /* Check if zone is not discarded. */
- if (knot_zone_flags(zone) & KNOT_ZONE_DISCARDED) {
- rcu_read_unlock(); /* Event will be freed on zonedata_destroy.*/
- return KNOT_EOK;
- }
-
- /* Check for answered/cancelled query. */
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- knot_zone_contents_t *contents = knot_zone_get_contents(zone);
-
- /* Reduce number of available retries. */
- --ev->retries;
-
- /* Check number of retries. */
- if (ev->retries < 0) {
- log_server_notice("NOTIFY query maximum number of retries "
- "for zone '%s' exceeded.\n",
- zd->conf->name);
- rcu_read_unlock();
- pthread_mutex_lock(&zd->lock);
- rem_node(&ev->n);
- evsched_event_free(e->parent, e);
- free(ev);
- pthread_mutex_unlock(&zd->lock);
- return KNOT_EMALF;
- }
-
- /* RFC suggests 60s, but it is configurable. */
- int retry_tmr = ev->timeout * 1000;
-
- /* Reschedule. */
- evsched_schedule(e->parent, e, retry_tmr);
- dbg_notify("notify: Query RETRY after %u secs (zone '%s')\n",
- retry_tmr / 1000, zd->conf->name);
-
- /* Prepare buffer for query. */
- uint8_t *qbuf = malloc(SOCKET_MTU_SZ);
- if (qbuf == NULL) {
- log_zone_error("Not enough memory to allocate NOTIFY query.\n");
- rcu_read_unlock();
- return KNOT_ENOMEM;
- }
-
- size_t buflen = SOCKET_MTU_SZ;
-
- /* Create query. */
- int ret = notify_create_request(contents, qbuf, &buflen);
- if (ret == KNOT_EOK && zd->server) {
-
- /* Create socket on random port. */
- int sock = socket_create(ev->addr.family, SOCK_DGRAM);
-
- /* Check requested source. */
- if (ev->saddr.len > 0) {
- if (bind(sock, ev->saddr.ptr, ev->saddr.len) < 0) {
- socket_close(sock);
- sock = -1;
- }
- }
-
- /* Send query. */
- ret = -1;
- if (sock > -1) {
- ret = sendto(sock, qbuf, buflen, 0,
- ev->addr.ptr, ev->addr.len);
- }
-
- /* Store ID of the awaited response. */
- if (ret == buflen) {
- ev->msgid = knot_wire_get_id(qbuf);
-
- }
-
- /* Mark as finished to prevent stalling. */
- evsched_event_finished(e->parent);
- /* Watch socket. */
- knot_ns_xfr_t req;
- memset(&req, 0, sizeof(req));
- req.session = sock;
- req.type = XFR_TYPE_NOTIFY;
- req.flags |= XFR_FLAG_UDP;
- req.zone = zone;
- memcpy(&req.addr, &ev->addr, sizeof(sockaddr_t));
- memcpy(&req.saddr, &ev->saddr, sizeof(sockaddr_t));
-
- /* Retain pointer to zone and issue request. */
- knot_zone_retain(req.zone);
- ret = xfr_request(zd->server->xfr_h, &req);
- if (ret != KNOT_EOK) {
- knot_zone_release(req.zone); /* Discard */
- }
- }
-
- free(qbuf);
- rcu_read_unlock();
return ret;
}
@@ -792,10 +463,8 @@ static int zones_zonefile_sync_ev(event_t *e)
"to zonefile.\n",
zd->conf->name);
}
- rcu_read_unlock();
/* Reschedule. */
- rcu_read_lock();
evsched_schedule(e->parent, e, zd->conf->dbsync_timeout * 1000);
dbg_zones("zones: next IXFR database SYNC of '%s' in %d seconds\n",
zd->conf->name, zd->conf->dbsync_timeout);
@@ -865,124 +534,67 @@ static int zones_set_acl(acl_t **acl, list* acl_list)
* \param dst Loaded zone will be returned in this parameter.
* \param zone_name Zone name (owner of the apex node).
* \param source Path to zone file source.
- * \param filename Path to requested compiled zone file.
*
* \retval KNOT_EOK
* \retval KNOT_EINVAL
* \retval KNOT_EZONEINVAL
*/
static int zones_load_zone(knot_zone_t **dst, const char *zone_name,
- const char *source, const char *filename)
+ const char *source, int enable_checks)
{
if (dst == NULL || zone_name == NULL || source == NULL) {
return KNOT_EINVAL;
}
- *dst = NULL;
-
- /* Duplicate zone name. */
- size_t zlen = strlen(zone_name);
- char *zname = NULL;
- if (zlen > 0) {
- if ((zname = strdup(zone_name)) == NULL) {
- return KNOT_ENOMEM;
- }
- } else {
- return KNOT_EINVAL;
- }
- zname[zlen - 1] = '\0'; /* Trim last dot */
- if (filename == NULL) {
- log_server_error("No file name for zone '%s'.\n", zname);
- free(zname);
- return KNOT_EINVAL;
- }
-
-
- /* Check if the compiled file still exists. */
- struct stat st;
- if (stat(source, &st) != 0) {
- char reason[256] = {0};
- strerror_r(errno, reason, sizeof(reason));
- log_server_warning("Failed to open zone file '%s' (%s).\n",
- zname, reason);
- free(zname);
- return KNOT_EZONEINVAL;
- }
- /* Attempt to open compiled zone for loading. */
+
int ret = KNOT_EOK;
zloader_t *zl = NULL;
- dbg_zones("zones: parsing zone database '%s'\n", filename);
- switch(knot_zload_open(&zl, filename)) {
- case KNOT_EOK:
- /* OK */
- break;
+ *dst = NULL;
+
+ /* Open zone file for parsing. */
+ switch(knot_zload_open(&zl, source, zone_name, enable_checks)) {
+ case KNOT_EOK: /* OK */ break;
case KNOT_EACCES:
- log_server_error("Failed to open compiled zone '%s' "
- "(Permission denied).\n", filename);
- free(zname);
+ log_server_error("Failed to open zone file '%s' "
+ "(Permission denied).\n", source);
+ knot_zload_close(zl);
return KNOT_EZONEINVAL;
case KNOT_ENOENT:
- log_server_error("Couldn't find compiled zone. "
- "Please recompile '%s'.\n", zname);
- free(zname);
- return KNOT_EZONEINVAL;
- case KNOT_ECRC:
- log_server_error("Compiled zone db CRC mismatch, "
- "db is corrupted or .crc file is "
- "deleted. Please recompile '%s'.\n",
- zname);
- free(zname);
- return KNOT_EZONEINVAL;
- case KNOT_EMALF:
- log_server_error("Compiled db '%s' is too old. "
- "Please recompile '%s'.\n",
- filename, zname);
- free(zname);
+ log_server_error("Couldn't find zone file '%s'\n", source);
+ knot_zload_close(zl);
return KNOT_EZONEINVAL;
- case KNOT_EFEWDATA:
- case KNOT_ERROR:
- case KNOT_ENOMEM:
default:
- log_server_error("Failed to load compiled zone file "
- "'%s'.\n", filename);
- free(zname);
+ log_server_error("Failed to load zone file '%s'\n", source);
+ knot_zload_close(zl);
return KNOT_EZONEINVAL;
}
-
+
/* Check the source file */
assert(zl != NULL);
- int src_changed = strcmp(source, zl->source) != 0;
- if (src_changed || knot_zload_needs_update(zl)) {
- log_server_warning("Database for zone '%s' is not "
- "up-to-date. Please recompile.\n",
- zname);
- }
-
*dst = knot_zload_load(zl);
if (*dst == NULL) {
- log_server_error("Failed to load db '%s' for zone '%s'.\n",
- filename, zname);
+ log_zone_error("Zone %s could not be loaded.\n", zone_name);
knot_zload_close(zl);
- free(zname);
- return KNOT_EZONEINVAL;
+ return KNOT_ERROR;
}
-
+
/* Check if loaded origin matches. */
const knot_dname_t *dname = knot_zone_name(*dst);
knot_dname_t *dname_req = NULL;
- dname_req = knot_dname_new_from_str(zone_name, zlen, 0);
+ dname_req = knot_dname_new_from_str(zone_name, strlen(zone_name), 0);
if (knot_dname_compare(dname, dname_req) != 0) {
log_server_error("Origin of the zone db file is "
"different than '%s'\n",
zone_name);
- knot_zone_deep_free(dst, 0);
+ knot_zone_deep_free(dst);
ret = KNOT_EZONEINVAL;
} else {
/* Save the timestamp from the zone db file. */
- if (stat(filename, &st) < 0) {
+ struct stat st;
+ if (stat(source, &st) < 0) {
dbg_zones("zones: failed to stat() zone db, "
"something is seriously wrong\n");
- knot_zone_deep_free(dst, 0);
+ knot_zone_deep_free(dst);
ret = KNOT_EZONEINVAL;
} else {
knot_zone_set_version(*dst, st.st_mtime);
@@ -990,7 +602,6 @@ static int zones_load_zone(knot_zone_t **dst, const char *zone_name,
}
knot_dname_free(&dname_req);
knot_zload_close(zl);
- free(zname);
return ret;
}
@@ -1058,7 +669,7 @@ static inline uint64_t ixfrdb_key_make(uint32_t from, uint32_t to)
int zones_changesets_from_binary(knot_changesets_t *chgsets)
{
/*! \todo #1291 Why doesn't this just increment stream ptr? */
-
+
assert(chgsets != NULL);
assert(chgsets->allocated >= chgsets->count);
/*
@@ -1069,16 +680,16 @@ int zones_changesets_from_binary(knot_changesets_t *chgsets)
int ret = 0;
for (int i = 0; i < chgsets->count; ++i) {
-
+
/* Read changeset flags. */
knot_changeset_t* chs = chgsets->sets + i;
size_t remaining = chs->size;
memcpy(&chs->flags, chs->data, sizeof(uint32_t));
remaining -= sizeof(uint32_t);
-
+
/* Read initial changeset RRSet - SOA. */
uint8_t *stream = chs->data + (chs->size - remaining);
- ret = knot_zload_rrset_deserialize(&rrset, stream, &remaining);
+ ret = rrset_deserialize(stream, &remaining, &rrset);
if (ret != KNOT_EOK) {
dbg_xfr("xfr: SOA: failed to deserialize data "
"from changeset, %s\n", knot_strerror(ret));
@@ -1093,7 +704,7 @@ int zones_changesets_from_binary(knot_changesets_t *chgsets)
knot_rrset_type(rrset));
assert(knot_rrset_type(rrset) == KNOT_RRTYPE_SOA);
assert(chs->serial_from ==
- knot_rdata_soa_serial(knot_rrset_rdata(rrset)));
+ knot_rrset_rdata_soa_serial(rrset));
knot_changeset_store_soa(&chs->soa_from, &chs->serial_from,
rrset);
@@ -1104,7 +715,7 @@ int zones_changesets_from_binary(knot_changesets_t *chgsets)
/* Parse next RRSet. */
rrset = 0;
stream = chs->data + (chs->size - remaining);
- ret = knot_zload_rrset_deserialize(&rrset, stream, &remaining);
+ ret = rrset_deserialize(stream, &remaining, &rrset);
if (ret != KNOT_EOK) {
dbg_xfr("xfr: failed to deserialize data "
"from changeset, %s\n",
@@ -1127,7 +738,7 @@ int zones_changesets_from_binary(knot_changesets_t *chgsets)
} else {
/* Final SOA. */
dbg_xfr_verb("xfr: extra SOA\n");
- knot_rrset_free(&rrset);
+ knot_rrset_deep_free(&rrset, 1, 1);
break;
}
} else {
@@ -1157,7 +768,7 @@ int zones_changesets_from_binary(knot_changesets_t *chgsets)
}
}
}
-
+
dbg_xfr_verb("xfr: read all RRSets in changeset\n");
}
@@ -1166,7 +777,7 @@ int zones_changesets_from_binary(knot_changesets_t *chgsets)
/*----------------------------------------------------------------------------*/
-static int zones_load_changesets(const knot_zone_t *zone,
+static int zones_load_changesets(const knot_zone_t *zone,
knot_changesets_t *dst,
uint32_t from, uint32_t to)
{
@@ -1178,7 +789,7 @@ static int zones_load_changesets(const knot_zone_t *zone,
dbg_zones_detail("Bad arguments: zone->data=%p\n", zone->data);
return KNOT_EINVAL;
}
-
+
/* Fetch zone-specific data. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
if (!zd->ixfr_db) {
@@ -1187,10 +798,16 @@ static int zones_load_changesets(const knot_zone_t *zone,
}
rcu_read_lock();
+ /* Check journal file existence. */
+ struct stat st;
+ if (stat(zd->conf->ixfr_db, &st) == -1) {
+ rcu_read_unlock();
+ return KNOT_ERANGE; /* Not existent, no changesets available. */
+ }
dbg_xfr("xfr: loading changesets for zone '%s' from serial %u to %u\n",
zd->conf->name, from, to);
rcu_read_unlock();
-
+
/* Retain journal for changeset loading. */
journal_t *j = journal_retain(zd->ixfr_db);
if (j == NULL) {
@@ -1207,7 +824,7 @@ static int zones_load_changesets(const knot_zone_t *zone,
journal_release(j);
return ret;
}
-
+
while (n != 0 && n != journal_end(j)) {
/* Check for history end. */
@@ -1228,7 +845,7 @@ static int zones_load_changesets(const knot_zone_t *zone,
journal_release(j);
return KNOT_ERROR;
}
-
+
/* Skip wrong changesets. */
if (!(n->flags & JOURNAL_VALID) || n->flags & JOURNAL_TRANS) {
++n;
@@ -1266,7 +883,7 @@ static int zones_load_changesets(const knot_zone_t *zone,
/*! \todo Check consistency. */
}
-
+
dbg_xfr_detail("xfr: finished reading journal entries\n");
journal_release(j);
@@ -1319,12 +936,10 @@ static int zones_journal_apply(knot_zone_t *zone)
/* Fetch SOA serial. */
const knot_rrset_t *soa_rrs = 0;
- const knot_rdata_t *soa_rr = 0;
soa_rrs = knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
assert(soa_rrs != NULL);
- soa_rr = knot_rrset_rdata(soa_rrs);
- int64_t serial_ret = knot_rdata_soa_serial(soa_rr);
+ int64_t serial_ret = knot_rrset_rdata_soa_serial(soa_rrs);
if (serial_ret < 0) {
rcu_read_unlock();
return KNOT_EINVAL;
@@ -1360,6 +975,9 @@ static int zones_journal_apply(knot_zone_t *zone)
&chsets->changes);
} else {
/* Switch zone immediately. */
+ log_server_info("Zone '%s' serial %u -> %u.\n",
+ zd->conf->name,
+ serial, knot_zone_serial(contents));
rcu_read_unlock();
apply_ret = xfrin_switch_zone(zone, contents,
XFR_TYPE_IIN);
@@ -1392,8 +1010,6 @@ static int zones_journal_apply(knot_zone_t *zone)
return ret;
}
-/*----------------------------------------------------------------------------*/
-
/*!
* \brief Insert new zone to the database.
*
@@ -1416,7 +1032,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
if (z == NULL || dst == NULL || ns == NULL) {
return KNOT_EINVAL;
}
-
+
/* Convert the zone name into a domain name. */
/* Local allocation, will be discarded. */
knot_dname_t *dname = knot_dname_new_from_str(z->name, strlen(z->name),
@@ -1427,20 +1043,16 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
return KNOT_EINVAL;
}
- /* Try to find the zone in the current zone db. */
- rcu_read_lock();
+ /* Try to find the zone in the current zone db, doesn't need RCU. */
knot_zone_t *zone = knot_zonedb_find_zone(ns->zone_db, dname);
- rcu_read_unlock();
/* Attempt to bootstrap if db or source does not exist. */
+ int ret = KNOT_ERROR;
int zone_changed = 0;
- struct stat s = {};
- int stat_ret = stat(z->file, &s);
+ struct stat st_zone;
+ int stat_ret = stat(z->file, &st_zone);
if (zone != NULL) {
- /* if found, check timestamp of the file against the
- * loaded zone
- */
- if (stat_ret == 0 && knot_zone_version(zone) < s.st_mtime) {
+ if (stat_ret == 0 && knot_zone_version(zone) < st_zone.st_mtime) {
zone_changed = 1;
}
} else {
@@ -1448,9 +1060,6 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
}
/* Reload zone file. */
- int is_new = 0;
- int is_bootstrapped = 0;
- int ret = KNOT_ERROR;
if (zone_changed) {
/* Zone file not exists and has master set. */
if (stat_ret < 0 && !EMPTY_LIST(z->acl.xfr_in)) {
@@ -1463,16 +1072,15 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
zone = knot_zone_new_empty(owner);
if (zone != NULL) {
ret = KNOT_EOK;
- is_bootstrapped = 1;
} else {
dbg_zones("zones: failed to create "
"stub zone '%s'.\n", z->name);
ret = KNOT_ERROR;
}
} else {
- dbg_zones_verb("zones: loading zone '%s' from '%s'\n",
- z->name, z->db);
- ret = zones_load_zone(&zone, z->name, z->file, z->db);
+ dbg_zones_verb("zones: loading zone '%s'\n", z->name);
+ ret = zones_load_zone(&zone, z->name, z->file,
+ z->enable_checks);
const knot_node_t *apex = NULL;
const knot_rrset_t *soa = NULL;
if (ret == KNOT_EOK) {
@@ -1482,13 +1090,11 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
KNOT_RRTYPE_SOA);
int64_t sn = 0;
if (apex && soa) {
- sn = knot_rdata_soa_serial(
- knot_rrset_rdata(soa));
+ sn = knot_rrset_rdata_soa_serial(soa);
if (sn < 0) sn = 0;
}
log_server_info("Loaded zone '%s' serial %u\n",
z->name, (uint32_t)sn);
- is_new = 1;
}
}
@@ -1517,14 +1123,6 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
if (zone != NULL) {
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
assert(zd != NULL);
-
- /* Log bootstrapped zone. */
- if (is_bootstrapped) {
- log_server_info("Will attempt to bootstrap zone"
- " %s from AXFR master in %us.\n",
- z->name,
- zd->xfr_in.bootstrap_retry / 1000);
- }
/* Update refs. */
if (zd->conf != z) {
@@ -1545,7 +1143,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
/* Update master server address. */
zd->xfr_in.has_master = 0;
- memset(&zd->xfr_in.tsig_key, 0, sizeof(knot_key_t));
+ memset(&zd->xfr_in.tsig_key, 0, sizeof(knot_tsig_key_t));
sockaddr_init(&zd->xfr_in.master, -1);
sockaddr_init(&zd->xfr_in.via, -1);
if (!EMPTY_LIST(z->acl.xfr_in)) {
@@ -1564,7 +1162,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
if (cfg_if->key) {
memcpy(&zd->xfr_in.tsig_key,
cfg_if->key,
- sizeof(knot_key_t));
+ sizeof(knot_tsig_key_t));
}
dbg_zones("zones: using '%s@%d' as XFR master "
@@ -1581,24 +1179,13 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
"for zone '%s': %s\n",
z->name, knot_strerror(ar));
}
-
- /* Update events scheduled for zone. */
- evsched_t *sch = ((server_t *)knot_ns_get_data(ns))->sched;
- zones_timers_update(zone, z, sch);
-
- /* Refresh new slave zones (almost) immediately. */
- if(is_new && zd->xfr_in.timer) {
- evsched_cancel(sch, zd->xfr_in.timer);
- evsched_schedule(sch, zd->xfr_in.timer,
- zd->xfr_in.bootstrap_retry / 2);
- }
-
/* Schedule IXFR database syncing. */
/*! \note This has to remain separate as it must not be
* triggered by a zone update or SOA response.
*/
/* Fetch zone data. */
+ evsched_t *sch = ((server_t *)knot_ns_get_data(ns))->sched;
int sync_tmr = z->dbsync_timeout * 1000; /* s -> ms. */
if (zd->ixfr_dbsync != NULL) {
evsched_cancel(sch, zd->ixfr_dbsync);
@@ -1628,7 +1215,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
rcu_read_unlock();
}
-
+
/* Calculate differences. */
rcu_read_lock();
knot_zone_t *z_old = knot_zonedb_find_zone(ns->zone_db,
@@ -1669,7 +1256,7 @@ struct zonewalk_t {
unsigned qhead;
unsigned qtail;
conf_zone_t *q[];
-
+
};
/*! Thread entrypoint for loading zones. */
@@ -1678,7 +1265,7 @@ static int zonewalker(dthread_t *thread)
if (thread == NULL) {
return KNOT_ERROR;
}
-
+
struct zonewalk_t *zw = (struct zonewalk_t *)thread->data;
if (zw == NULL) {
return KNOT_ERROR;
@@ -1696,20 +1283,20 @@ static int zonewalker(dthread_t *thread)
if (i >= zw->qtail) {
break;
}
-
+
if (mreserve((char **)&zones, sizeof(knot_zone_t*),
inserted + 1, 32, &allocd) < 0) {
dbg_zones("zones: failed to reserve space for "
"loading zones\n");
continue;
}
-
+
int ret = zones_insert_zone(zw->q[i], zones + inserted, zw->ns);
if (ret == KNOT_EOK) {
++inserted;
}
}
-
+
/* Collect results. */
pthread_mutex_lock(&zw->lock);
zw->inserted += inserted;
@@ -1718,7 +1305,9 @@ static int zonewalker(dthread_t *thread)
if (knot_zonedb_add_zone(zw->db_new, zones[i]) != KNOT_EOK) {
log_server_error("Failed to insert zone '%s' "
"into database.\n", zd->conf->name);
- knot_zone_deep_free(zones + i, 0);
+ /* Not doing this here would result in memory errors. */
+ rem_node(&zd->conf->n);
+ knot_zone_deep_free(zones + i);
} else {
/* Unlink zone config from conf(),
* transferring ownership to zonedata. */
@@ -1727,7 +1316,7 @@ static int zonewalker(dthread_t *thread)
}
pthread_mutex_unlock(&zw->lock);
free(zones);
-
+
return KNOT_EOK;
}
@@ -1744,61 +1333,58 @@ static int zonewalker(dthread_t *thread)
* \return Number of inserted zones.
*/
static int zones_insert_zones(knot_nameserver_t *ns,
- const list *zone_conf,
+ const list *zone_conf,
knot_zonedb_t *db_new)
{
- int inserted = 0;
+ int ret = 0;
size_t zcount = 0;
conf_zone_t *z = NULL;
WALK_LIST(z, *zone_conf) {
++zcount;
}
-
+ if (zcount == 0)
+ return 0;
+
/* Initialize zonewalker. */
size_t zwlen = sizeof(struct zonewalk_t) + zcount * sizeof(conf_zone_t*);
struct zonewalk_t *zw = malloc(zwlen);
- if (zw != NULL) {
- memset(zw, 0, zwlen);
- zw->ns = ns;
- zw->db_new = db_new;
- zw->inserted = 0;
- if (pthread_mutex_init(&zw->lock, NULL) < 0) {
- free(zw);
- zw = NULL;
- } else {
- unsigned i = 0;
- WALK_LIST(z, *zone_conf) {
- zw->q[i++] = z;
- }
- zw->qhead = 0;
- zw->qtail = zcount;
- }
+ if (zw == NULL) {
+ return KNOT_ENOMEM;
}
-
+ memset(zw, 0, zwlen);
+ zw->ns = ns;
+ zw->db_new = db_new;
+ zw->inserted = 0;
+ if (pthread_mutex_init(&zw->lock, NULL) < 0) {
+ free(zw);
+ return KNOT_ENOMEM;
+ }
+ unsigned i = 0;
+ WALK_LIST(z, *zone_conf) {
+ zw->q[i++] = z;
+ }
+ zw->qhead = 0;
+ zw->qtail = zcount;
+
/* Initialize threads. */
- dt_unit_t *unit = NULL;
- if (zw != NULL) {
- unit = dt_create_coherent(dt_optimal_size(), &zonewalker, zw);
- }
- /* Single-thread fallback. */
- if (unit == NULL) {
- log_server_error("Couldn't initialize zone loading - %s\n",
- knot_strerror(KNOT_ENOMEM));
- return 0;
+ size_t thrs = dt_optimal_size();
+ if (thrs > zcount) thrs = zcount;
+ dt_unit_t *unit = dt_create_coherent(thrs, &zonewalker, zw);
+ if (unit != NULL) {
+ /* Start loading. */
+ dt_start(unit);
+ dt_join(unit);
+ dt_delete(&unit);
+
+ /* Collect counts. */
+ ret = zw->inserted;
+ } else {
+ ret = KNOT_ENOMEM;
}
-
- /* Start loading. */
- dt_start(unit);
-
- /* Wait for finish. */
- dt_join(unit);
- dt_delete(&unit);
-
- /* Collect counts. */
- inserted = zw->inserted;
+
pthread_mutex_destroy(&zw->lock);
free(zw);
- return inserted;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -1817,19 +1403,17 @@ static int zones_insert_zones(knot_nameserver_t *ns,
static int zones_remove_zones(const knot_zonedb_t *db_new,
knot_zonedb_t *db_old)
{
- const knot_zone_t **new_zones = knot_zonedb_zones(db_new);
- if (new_zones == NULL) {
- return KNOT_ENOMEM;
- }
+ hattrie_iter_t *i = hattrie_iter_begin(db_new->zone_tree, 0);
+ while(!hattrie_iter_finished(i)) {
- for (int i = 0; i < knot_zonedb_zone_count(db_new); ++i) {
/* try to find the new zone in the old DB
* if the pointers match, remove the zone from old DB
*/
/*! \todo Find better way of removing zone with given pointer.*/
+ knot_zone_t *new_zone = (knot_zone_t *)(*hattrie_iter_val(i));
knot_zone_t *old_zone = knot_zonedb_find_zone(
- db_old, knot_zone_name(new_zones[i]));
- if (old_zone == new_zones[i]) {
+ db_old, knot_zone_name(new_zone));
+ if (old_zone == new_zone) {
dbg_zones_exec(
char *name = knot_dname_to_str(knot_zone_name(old_zone));
dbg_zones_verb("zones: zone pointers match, removing zone %s "
@@ -1847,15 +1431,16 @@ dbg_zones_exec(
WALK_LIST_FREE(zconf->acl.notify_in);
WALK_LIST_FREE(zconf->acl.notify_out);
WALK_LIST_FREE(zconf->acl.update_in);
-
+
/* Remove from zone db. */
knot_zone_t * rm = knot_zonedb_remove_zone(db_old,
knot_zone_name(old_zone));
assert(rm == old_zone);
}
+ hattrie_iter_next(i);
}
- free(new_zones);
+ hattrie_iter_free(i);
return KNOT_EOK;
}
@@ -1867,7 +1452,7 @@ static int zones_check_tsig_query(const knot_zone_t *zone,
const sockaddr_t *addr,
knot_rcode_t *rcode,
uint16_t *tsig_rcode,
- knot_key_t **tsig_key_zone,
+ knot_tsig_key_t **tsig_key_zone,
uint64_t *tsig_prev_time_signed)
{
assert(zone != NULL);
@@ -1881,7 +1466,7 @@ static int zones_check_tsig_query(const knot_zone_t *zone,
int ret = zones_query_check_zone(zone, knot_packet_opcode(query),
addr, tsig_key_zone, rcode);
-
+
/* Accept found OR unknown key results. */
if (ret == KNOT_EOK || ret == KNOT_EACCES) {
if (*tsig_key_zone != NULL) {
@@ -1896,7 +1481,7 @@ static int zones_check_tsig_query(const knot_zone_t *zone,
// no key configured for zone, return BADKEY
dbg_zones_verb("TSIG used, but not configured "
"for this zone, ret=BADKEY.\n");
- *tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
+ *tsig_rcode = KNOT_RCODE_BADKEY;
*rcode = KNOT_RCODE_NOTAUTH;
ret = KNOT_TSIG_EBADKEY;
}
@@ -1913,110 +1498,53 @@ static int zones_update_forward(int fd, knot_ns_transport_t ttype,
knot_zone_t *zone, const sockaddr_t *from,
knot_packet_t *query, size_t qsize)
{
- /*! \todo #1291 #1999 This is really the same as for NOTIFY+SOA, should
- * use common API. */
-
- int ret = KNOT_EOK;
- int orig_id = (int)knot_packet_id(query);
rcu_read_lock();
-
+
+ /* Check transport type. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
-
- /* Create socket on random port. */
- sockaddr_t *master = &zd->xfr_in.master;
- int stype = SOCK_DGRAM;
- if (ttype == NS_TRANSPORT_TCP) {
- stype = SOCK_STREAM;
- }
- int nfd = socket_create(master->family, stype);
-
- /* Check requested source. */
- char strbuf[256] = "Generic error.";
- sockaddr_t *via = &zd->xfr_in.via;
- if (via->len > 0) {
- if (bind(nfd, via->ptr, via->len) < 0) {
- socket_close(nfd);
- nfd = -1;
- char r_addr[SOCKADDR_STRLEN];
- sockaddr_tostr(via, r_addr, sizeof(r_addr));
- snprintf(strbuf, sizeof(strbuf),
- "Couldn't bind to \'%s\'", r_addr);
- }
- }
-
- /* Store query as pending. */
- knot_ns_xfr_t req;
- memset(&req, 0, sizeof(knot_ns_xfr_t));
- req.session = nfd;
- req.fwd_src_fd = fd;
- req.type = XFR_TYPE_FORWARD;
+ unsigned flags = XFR_FLAG_UDP;
if (ttype == NS_TRANSPORT_TCP) {
- req.flags |= XFR_FLAG_TCP;
- req.send = zones_send_cb;
- } else {
- req.flags |= XFR_FLAG_UDP;
- req.send = zones_send_udp;
+ flags = XFR_FLAG_TCP;
}
- req.zone = zone;
-
- /* Create FORWARD query and send to primary. */
- uint8_t *rwire = malloc(qsize);
- if (rwire) {
- ret = knot_ns_create_forward_query(query, rwire, &qsize);
- } else {
- ret = KNOT_ENOMEM;
+
+ /* Prepare task. */
+ knot_ns_xfr_t *rq = xfr_task_create(zone, XFR_TYPE_FORWARD, flags);
+ if (!rq) {
+ rcu_read_unlock();
+ return KNOT_ENOMEM;
}
- if (nfd > -1) {
- /* Connect on TCP. */
- if (ttype == NS_TRANSPORT_TCP) {
- if (connect(nfd, master->ptr, master->len) < 0) {
- ret = KNOT_ECONNREFUSED;
- }
- }
+ xfr_task_setaddr(rq, &zd->xfr_in.master, &zd->xfr_in.via);
- int sent = 0;
- if (ret == KNOT_EOK) {
- sent = req.send(nfd, master, rwire, qsize);
- }
-
- /* Store ID of the awaited response. */
- if (sent == qsize) {
- ret = KNOT_EOK;
- } else {
- strbuf[0] = '\0';
- ret = KNOT_ECONNREFUSED;
- }
+ /* Copy query originator data. */
+ rq->fwd_src_fd = fd;
+ memcpy(&rq->fwd_addr, from, sizeof(sockaddr_t));
+ rq->packet_nr = (int)knot_packet_id(query);
+
+ /* Duplicate query to keep it in memory during forwarding. */
+ rq->query = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
+ if (!rq->query) {
+ xfr_task_free(rq);
+ rcu_read_unlock();
+ return KNOT_ENOMEM;
}
- if (ret != KNOT_EOK) {
- if (nfd > -1) {
- socket_close(nfd);
- }
- dbg_zones("update: failed to create FORWARD qry '%s'\n",
- knot_strerror(ret));
+ rq->query->size = knot_packet_size(query);
+ rq->query->wireformat = malloc(rq->query->size);
+ if (!rq->query->wireformat) {
+ knot_packet_free(&rq->query);
+ xfr_task_free(rq);
rcu_read_unlock();
- free(rwire);
return KNOT_ENOMEM;
}
- free(rwire);
+ rq->query->free_wireformat = 1;
+ memcpy(rq->query->wireformat, query->wireformat, knot_packet_size(query));
- req.packet_nr = orig_id;
- memcpy(&req.addr, master, sizeof(sockaddr_t));
- memcpy(&req.saddr, from, sizeof(sockaddr_t));
- sockaddr_update(&req.addr);
- sockaddr_update(&req.saddr);
-
/* Retain pointer to zone and issue. */
- knot_zone_retain(req.zone);
- if (ret == KNOT_EOK) {
- ret = xfr_request(zd->server->xfr_h, &req);
- }
+ rcu_read_unlock();
+ int ret = xfr_enqueue(zd->server->xfr, rq);
if (ret != KNOT_EOK) {
- knot_zone_release(req.zone); /* Discard */
- log_server_warning("Failed to forward UPDATE query for zone '%s' (%s).\n",
- zd->conf->name, strbuf);
+ xfr_task_free(rq);
}
-
- rcu_read_unlock();
+
return KNOT_EOK;
}
@@ -2033,26 +1561,26 @@ static int zones_store_changesets_to_disk(knot_zone_t *zone,
"Could not start journal operation.\n");
return KNOT_ERROR;
}
-
+
int ret = zones_store_changesets(zone, chgsets);
if (ret != KNOT_EOK) {
zones_store_changesets_rollback(journal);
dbg_zones("zones: create_changesets: "
"Could not store in the journal. Reason: %s.\n",
knot_strerror(ret));
-
+
return ret;
}
-
+
ret = zones_store_changesets_commit(journal);
if (ret != KNOT_EOK) {
dbg_zones("zones: create_changesets: "
"Could not commit to journal. Reason: %s.\n",
knot_strerror(ret));
-
+
return ret;
}
-
+
return KNOT_EOK;
}
@@ -2072,11 +1600,11 @@ static int zones_process_update_auth(knot_zone_t *zone,
uint8_t *resp_wire, size_t *rsize,
knot_rcode_t *rcode,
const sockaddr_t *addr,
- knot_key_t *tsig_key)
+ knot_tsig_key_t *tsig_key)
{
int ret = KNOT_EOK;
dbg_zones_verb("TSIG check successful. Answering query.\n");
-
+
/* Create log message prefix. */
char *keytag = NULL;
if (tsig_key) {
@@ -2084,19 +1612,19 @@ static int zones_process_update_auth(knot_zone_t *zone,
}
char *r_str = xfr_remote_str(addr, keytag);
const char *zone_name = ((zonedata_t*)knot_zone_data(zone))->conf->name;
- char *msg = sprintf_alloc("UPDATE of '%s' from %s:",
+ char *msg = sprintf_alloc("UPDATE of '%s' from %s",
zone_name, r_str ? r_str : "'unknown'");
free(r_str);
free(keytag);
log_zone_info("%s Started.\n", msg);
-
-
+
+
/* Reserve place for the TSIG */
if (tsig_key != NULL) {
size_t tsig_max_size = tsig_wire_maxsize(tsig_key);
knot_packet_set_tsig_size(resp, tsig_max_size);
}
-
+
/* We must prepare a changesets_t structure even if
* there is only one changeset - because of the API. */
knot_changesets_t *chgsets = NULL;
@@ -2107,17 +1635,17 @@ static int zones_process_update_auth(knot_zone_t *zone,
free(msg);
return ret;
}
-
+
assert(chgsets->allocated >= 1);
-
+
/*
* NEW DDNS PROCESSING -------------------------------------------------
*/
/* 1) Process the UPDATE packet, apply to zone, create changesets. */
-
+
dbg_zones_verb("Processing UPDATE packet.\n");
chgsets->count = 1; /* DU is represented by a single chset. */
-
+
knot_zone_contents_t *new_contents = NULL;
ret = knot_ns_process_update2(knot_packet_query(resp),
knot_zone_get_contents(zone),
@@ -2128,13 +1656,12 @@ static int zones_process_update_auth(knot_zone_t *zone,
if (ret < 0) {
log_zone_error("%s %s\n", msg, knot_strerror(ret));
} else {
- log_zone_notice("%s: No change to zone made.\n", msg);
+ log_zone_notice("%s No change to zone made.\n", msg);
knot_response_set_rcode(resp, KNOT_RCODE_NOERROR);
uint8_t *tmp_wire = NULL;
ret = knot_packet_to_wire(resp, &tmp_wire, rsize);
if (ret != KNOT_EOK) {
*rcode = KNOT_RCODE_SERVFAIL;
- return ret;
} else {
memcpy(resp_wire, tmp_wire, *rsize);
*rcode = KNOT_RCODE_NOERROR;
@@ -2145,7 +1672,7 @@ static int zones_process_update_auth(knot_zone_t *zone,
free(msg);
return (ret < 0) ? ret : KNOT_EOK;
}
-
+
/* 2) Store changesets, (TODO: but do not commit???). */
ret = zones_store_changesets_to_disk(zone, chgsets);
if (ret != KNOT_EOK) {
@@ -2156,7 +1683,7 @@ static int zones_process_update_auth(knot_zone_t *zone,
free(msg);
return ret;
}
-
+
/* 3) Switch zone contents. */
knot_zone_retain(zone); /* Retain pointer for safe RCU unlock. */
rcu_read_unlock(); /* Unlock for switch. */
@@ -2165,7 +1692,7 @@ static int zones_process_update_auth(knot_zone_t *zone,
knot_zone_release(zone);/* Release held pointer. */
if (ret != KNOT_EOK) {
- log_zone_error("%s: Failed to replace current zone - %s\n",
+ log_zone_error("%s Failed to replace current zone - %s\n",
msg, knot_strerror(ret));
// Cleanup old and new contents
xfrin_rollback_update(zone->contents, &new_contents,
@@ -2177,23 +1704,23 @@ static int zones_process_update_auth(knot_zone_t *zone,
}
/* 4) Cleanup. */
-
+
xfrin_cleanup_successful_update(&chgsets->changes);
-
+
/* Free changesets, but not the data. */
knot_free_changesets(&chgsets);
assert(ret == KNOT_EOK);
- log_zone_info("%s: Finished.\n", msg);
-
+ log_zone_info("%s Finished.\n", msg);
+
free(msg);
msg = NULL;
-
+
/*
* \NEW DDNS PROCESSING ------------------------------------------------
*/
-
-
-// /* 1) Process the incoming packet, prepare
+
+
+// /* 1) Process the incoming packet, prepare
// * prerequisities and changeset.
// */
// dbg_zones_verb("Processing UPDATE packet.\n");
@@ -2201,14 +1728,14 @@ static int zones_process_update_auth(knot_zone_t *zone,
// ret = knot_ns_process_update(knot_packet_query(resp),
// knot_zone_contents(zone),
// &chgsets->sets[0], rcode);
-
+
// if (ret != KNOT_EOK) {
// log_zone_error("%s %s\n", msg, knot_strerror(ret));
// knot_free_changesets(&chgsets);
// free(msg);
// return ret;
// }
-
+
// /* 2) Save changeset to journal.
// * Apply changeset to zone.
// * Commit changeset to journal.
@@ -2218,13 +1745,13 @@ static int zones_process_update_auth(knot_zone_t *zone,
// knot_zone_retain(zone); /* Retain pointer for safe RCU unlock. */
// rcu_read_unlock(); /* Unlock for switch. */
// dbg_zones_verb("Storing and applying changesets.\n");
-// ret = zones_store_and_apply_chgsets(chgsets, zone, &contents_new, msg,
+// ret = zones_store_and_apply_chgsets(chgsets, zone, &contents_new, msg,
// XFR_TYPE_UPDATE);
// rcu_read_lock(); /* Relock */
// knot_zone_release(zone);/* Release held pointer. */
// free(msg);
// msg = NULL;
-
+
// /* Changesets should be freed by now. */
// if (ret != KNOT_EOK) {
// dbg_zones_verb("Storing and applying changesets failed: %s.\n",
@@ -2251,10 +1778,10 @@ static int zones_process_update_auth(knot_zone_t *zone,
* to already existing buffer. */
memcpy(resp_wire, tmp_wire, *rsize);
}
-
+
dbg_zones("DDNS reply rsize = %zu\n", *rsize);
-
-
+
+
return ret;
}
@@ -2272,7 +1799,7 @@ int zones_update_db_from_config(const conf_t *conf, knot_nameserver_t *ns,
/* Lock RCU to ensure none will deallocate any data under our hands. */
rcu_read_lock();
-
+
/* Grab a pointer to the old database */
if (ns->zone_db == NULL) {
rcu_read_unlock();
@@ -2288,20 +1815,24 @@ int zones_update_db_from_config(const conf_t *conf, knot_nameserver_t *ns,
return KNOT_ERROR;
}
- log_server_info("Loading %d compiled zones...\n", conf->zones_count);
+ log_server_info("Loading %d zones...\n", conf->zones_count);
/* Insert all required zones to the new zone DB. */
- /*! \warning RCU must not be locked as some contents switching will
+ /*! \warning RCU must not be locked as some contents switching will
be required. */
int inserted = zones_insert_zones(ns, &conf->zones, db_new);
-
+ if (inserted < 0) {
+ log_server_warning("Failed to load zones - %s\n",
+ knot_strerror(inserted));
+ inserted = 0;
+ }
log_server_info("Loaded %d out of %d zones.\n", inserted,
conf->zones_count);
if (inserted != conf->zones_count) {
log_server_warning("Not all the zones were loaded.\n");
}
-
+
/* Lock RCU to ensure none will deallocate any data under our hands. */
rcu_read_lock();
*db_old = ns->zone_db;
@@ -2310,7 +1841,7 @@ int zones_update_db_from_config(const conf_t *conf, knot_nameserver_t *ns,
"new db: %p\n", ns->zone_db, *db_old, db_new);
/* Switch the databases. */
- (void)rcu_xchg_pointer(&ns->zone_db, db_new);
+ UNUSED(rcu_xchg_pointer(&ns->zone_db, db_new));
dbg_zones_detail("db in nameserver: %p, old db stored: %p, new db: %p\n",
ns->zone_db, *db_old, db_new);
@@ -2324,10 +1855,13 @@ int zones_update_db_from_config(const conf_t *conf, knot_nameserver_t *ns,
* All other have been loaded again so that the old must be destroyed.
*/
int ret = zones_remove_zones(db_new, *db_old);
-
+
+ /* Heal zonedb index. */
+ hattrie_build_index(db_new->zone_tree);
+
/* Unlock RCU, messing with any data will not affect us now */
rcu_read_unlock();
-
+
if (ret != KNOT_EOK) {
return ret;
}
@@ -2359,23 +1893,21 @@ int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal)
knot_zone_contents_t *contents = knot_zone_get_contents(zone);
if (!contents) {
- pthread_mutex_unlock(&zd->lock);
rcu_read_unlock();
+ pthread_mutex_unlock(&zd->lock);
return KNOT_EINVAL;
}
/* Latest zone serial. */
const knot_rrset_t *soa_rrs = 0;
- const knot_rdata_t *soa_rr = 0;
soa_rrs = knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
assert(soa_rrs != NULL);
- soa_rr = knot_rrset_rdata(soa_rrs);
- int64_t serial_ret = knot_rdata_soa_serial(soa_rr);
+ int64_t serial_ret = knot_rrset_rdata_soa_serial(soa_rrs);
if (serial_ret < 0) {
- pthread_mutex_unlock(&zd->lock);
rcu_read_unlock();
+ pthread_mutex_unlock(&zd->lock);
return KNOT_EINVAL;
}
uint32_t serial_to = (uint32_t)serial_ret;
@@ -2392,20 +1924,9 @@ int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal)
log_zone_warning("Failed to apply differences "
"'%s' to '%s'\n",
zd->conf->name, zd->conf->file);
- pthread_mutex_unlock(&zd->lock);
rcu_read_unlock();
- return ret;
- }
-
- /* Save zone to binary db file. */
- ret = zones_dump_zone_binary(contents, zd->conf->db, zd->conf->file);
- if (ret != KNOT_EOK) {
- log_zone_warning("Failed to apply differences "
- "'%s' to '%s'\n",
- zd->conf->name, zd->conf->db);
pthread_mutex_unlock(&zd->lock);
- rcu_read_unlock();
- return KNOT_ERROR;
+ return ret;
}
/* Update journal entries. */
@@ -2424,19 +1945,19 @@ int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal)
ret = KNOT_ERANGE;
}
- /* Unlock zone data. */
- pthread_mutex_unlock(&zd->lock);
-
/* Unlock RCU. */
rcu_read_unlock();
+ /* Unlock zone data. */
+ pthread_mutex_unlock(&zd->lock);
+
return ret;
}
/*----------------------------------------------------------------------------*/
int zones_query_check_zone(const knot_zone_t *zone, uint8_t q_opcode,
- const sockaddr_t *addr, knot_key_t **tsig_key,
+ const sockaddr_t *addr, knot_tsig_key_t **tsig_key,
knot_rcode_t *rcode)
{
if (addr == NULL || tsig_key == NULL || rcode == NULL) {
@@ -2520,8 +2041,10 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
{
rcu_read_lock();
+ knot_rcode_t rcode = 0;
knot_packet_t *resp = NULL;
const knot_zone_t *zone = NULL;
+ const uint16_t qclass = knot_packet_qclass(query);
dbg_zones_verb("Preparing response structure.\n");
int ret = knot_ns_prep_normal_response(nameserver, query, &resp, &zone,
@@ -2529,20 +2052,6 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
? *rsize : 0);
query->zone = zone;
- // check for TSIG in the query
- // not required, TSIG is already found if it is there
-// if (knot_packet_additional_rrset_count(query) > 0) {
-// /*! \todo warning */
-// const knot_rrset_t *tsig = knot_packet_additional_rrset(query,
-// knot_packet_additional_rrset_count(query) - 1);
-// if (knot_rrset_type(tsig) == KNOT_RRTYPE_TSIG) {
-// dbg_zones_verb("found TSIG in normal query\n");
-// knot_packet_set_tsig(query, tsig);
-// }
-// }
-
- knot_rcode_t rcode = 0;
-
switch (ret) {
case KNOT_EOK:
rcode = KNOT_RCODE_NOERROR;
@@ -2557,14 +2066,15 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
break;
}
- if (rcode == KNOT_RCODE_NOERROR
- && ((zone == NULL && knot_packet_tsig(query) == NULL)
- || (knot_packet_qclass(query) != KNOT_CLASS_IN
- && knot_packet_qclass(query) != KNOT_CLASS_ANY))) {
- /*! \todo If there is TSIG, this should be probably handled
- * as a key error.
- */
- rcode = KNOT_RCODE_REFUSED;
+ if (rcode == KNOT_RCODE_NOERROR) {
+ switch (qclass) {
+ case KNOT_CLASS_IN:
+ case KNOT_CLASS_CH:
+ case KNOT_CLASS_ANY:
+ break;
+ default:
+ rcode = KNOT_RCODE_REFUSED;
+ }
}
if (rcode != KNOT_RCODE_NOERROR) {
@@ -2586,32 +2096,26 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
assert(resp != NULL);
assert(rcode == KNOT_RCODE_NOERROR);
uint16_t tsig_rcode = 0;
- knot_key_t *tsig_key_zone = NULL;
+ knot_tsig_key_t *tsig_key_zone = NULL;
uint64_t tsig_prev_time_signed = 0;
/*! \todo Verify, as it was uninitialized! */
size_t answer_size = *rsize;
int ret = KNOT_EOK;
- if (zone == NULL) {
- assert(knot_packet_tsig(query) != NULL);
- // treat as BADKEY error
- /*! \todo Is this OK?? */
- rcode = KNOT_RCODE_NOTAUTH;
- tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
- ret = KNOT_TSIG_EBADKEY;
- } else {
+ const knot_rrset_t *tsig = knot_packet_tsig(query);
+ if (tsig != NULL) {
dbg_zones_verb("Checking TSIG in query.\n");
- const knot_rrset_t *tsig = knot_packet_tsig(query);
- if (tsig == NULL) {
- // no TSIG, this is completely valid
- tsig_rcode = 0;
- ret = KNOT_EOK;
+ if (zone == NULL) {
+ // treat as BADKEY error
+ /*! \todo Is this OK?? */
+ rcode = KNOT_RCODE_NOTAUTH;
+ tsig_rcode = KNOT_RCODE_BADKEY;
+ ret = KNOT_TSIG_EBADKEY;
} else {
ret = zones_check_tsig_query(zone, query, addr,
- &rcode, &tsig_rcode,
- &tsig_key_zone,
- &tsig_prev_time_signed);
+ &rcode, &tsig_rcode, &tsig_key_zone,
+ &tsig_prev_time_signed);
}
}
@@ -2634,11 +2138,14 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
resp, resp_wire,
&answer_size);
} else {
- ret = knot_ns_answer_normal(nameserver, zone,
- resp, resp_wire,
- &answer_size,
- transport ==
- NS_TRANSPORT_UDP);
+ if (qclass == KNOT_CLASS_CH) {
+ ret = knot_ns_answer_chaos(nameserver,
+ resp, resp_wire, &answer_size);
+ } else {
+ ret = knot_ns_answer_normal(nameserver,
+ zone, resp, resp_wire, &answer_size,
+ transport == NS_TRANSPORT_UDP);
+ }
query->flags = resp->flags; /* Copy markers. */
}
@@ -2657,7 +2164,7 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
knot_packet_tsig(knot_packet_query(resp));
size_t digest_max_size =
- tsig_alg_digest_length(
+ knot_tsig_digest_length(
tsig_key_zone->algorithm);
uint8_t *digest = (uint8_t *)malloc(
digest_max_size);
@@ -2674,7 +2181,7 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
digest, &digest_size,
tsig_key_zone, tsig_rcode,
tsig_prev_time_signed);
-
+
free(digest);
dbg_zones_detail("answer_size = %zu\n",
@@ -2708,7 +2215,7 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
// then add the TSIG to the wire format
if (ret == KNOT_EOK &&
- tsig_rcode != KNOT_TSIG_RCODE_BADTIME) {
+ tsig_rcode != KNOT_RCODE_BADTIME) {
dbg_zones_verb("Adding TSIG.\n");
ret = knot_tsig_add(resp_wire,
&answer_size,
@@ -2719,7 +2226,7 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
*rsize = answer_size;
} else if (tsig_rcode
- == KNOT_TSIG_RCODE_BADTIME) {
+ == KNOT_RCODE_BADTIME) {
dbg_zones_verb("Signing error resp.\n");
//*rsize = answer_size;
@@ -2728,7 +2235,7 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
knot_packet_query(resp));
size_t digest_max_size =
- tsig_alg_digest_length(
+ knot_tsig_digest_length(
tsig_key_zone->algorithm);
uint8_t *digest = (uint8_t *)malloc(
digest_max_size);
@@ -2745,7 +2252,7 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
tsig_rdata_mac_length(tsig),
digest, &digest_size, tsig_key_zone,
tsig_rcode, tsig_prev_time_signed);
-
+
// no need to keep the digest
free(digest);
@@ -2785,10 +2292,10 @@ int zones_process_update(knot_nameserver_t *nameserver,
knot_zone_t *zone = NULL;
knot_rcode_t rcode = KNOT_RCODE_NOERROR;
size_t rsize_max = *rsize;
- knot_key_t *tsig_key_zone = NULL;
+ knot_tsig_key_t *tsig_key_zone = NULL;
uint16_t tsig_rcode = 0;
uint64_t tsig_prev_time_signed = 0;
- const knot_rrset_t *tsig_rr = NULL;
+ const knot_rrset_t *tsig_rr = NULL;
// Parse rest of the query, prepare response, find zone
int ret = knot_ns_prep_update_response(nameserver, query, &resp, &zone,
@@ -2809,11 +2316,11 @@ int zones_process_update(knot_nameserver_t *nameserver,
const knot_zone_contents_t *contents = knot_zone_contents(zone);
if (zone && (knot_zone_flags(zone) & KNOT_ZONE_DISCARDED)) {
rcode = KNOT_RCODE_SERVFAIL; /* It's ok, temporarily. */
- tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
+ tsig_rcode = KNOT_RCODE_BADKEY;
ret = KNOT_ENOZONE;
} else if (!zone || !contents) { /* Treat as BADKEY. */
rcode = KNOT_RCODE_NOTAUTH;
- tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
+ tsig_rcode = KNOT_RCODE_BADKEY;
ret = KNOT_TSIG_EBADKEY;
dbg_zones_verb("No zone or empty, refusing UPDATE.\n");
}
@@ -2844,7 +2351,7 @@ int zones_process_update(knot_nameserver_t *nameserver,
return ret;
}
}
-
+
/*
* 1) DDNS Zone Section check (RFC2136, Section 3.1).
*/
@@ -2873,17 +2380,12 @@ int zones_process_update(knot_nameserver_t *nameserver,
/*
* 3) Process query.
- */
+ */
if (ret == KNOT_EOK) {
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- pthread_mutex_lock(&zd->xfr_in.lock);
-
/*! \note This function expects RCU locked. */
ret = zones_process_update_auth(zone, resp, resp_wire, rsize,
&rcode, addr, tsig_key_zone);
dbg_zones_verb("Auth, update_proc = %s\n", knot_strerror(ret));
-
- pthread_mutex_unlock(&zd->xfr_in.lock);
}
/* Create error query if processing failed. */
@@ -2892,22 +2394,22 @@ int zones_process_update(knot_nameserver_t *nameserver,
query, rcode,
resp_wire, rsize);
}
-
+
/* No response, no signing required or FORMERR. */
if (*rsize == 0 || !tsig_rr || rcode == KNOT_RCODE_FORMERR) {
knot_packet_free(&resp);
rcu_read_unlock();
return ret;
}
-
+
/* Just add TSIG RR on most errors. */
- if (tsig_rcode != 0 && tsig_rcode != KNOT_TSIG_RCODE_BADTIME) {
+ if (tsig_rcode != 0 && tsig_rcode != KNOT_RCODE_BADTIME) {
ret = knot_tsig_add(resp_wire, rsize, rsize_max,
tsig_rcode, tsig_rr);
dbg_zones_verb("Adding TSIG = %s\n", knot_strerror(ret));
} else if (tsig_key_zone) {
dbg_zones_verb("Signing message with TSIG.\n");
- size_t digest_len = tsig_alg_digest_length(tsig_key_zone->algorithm);
+ size_t digest_len = knot_tsig_digest_length(tsig_key_zone->algorithm);
uint8_t *digest = (uint8_t *)malloc(digest_len);
if (digest == NULL) {
knot_packet_free(&resp);
@@ -2931,7 +2433,8 @@ int zones_process_update(knot_nameserver_t *nameserver,
/*----------------------------------------------------------------------------*/
-int zones_process_response(knot_nameserver_t *nameserver,
+int zones_process_response(knot_nameserver_t *nameserver,
+ int exp_msgid,
sockaddr_t *from,
knot_packet_t *packet, uint8_t *response_wire,
size_t *rsize)
@@ -2940,7 +2443,7 @@ int zones_process_response(knot_nameserver_t *nameserver,
response_wire == NULL) {
return KNOT_EINVAL;
}
-
+
/* Declare no response. */
*rsize = 0;
@@ -2949,7 +2452,7 @@ int zones_process_response(knot_nameserver_t *nameserver,
* Reset REFRESH timer on finish.
*/
if (knot_packet_qtype(packet) == KNOT_RRTYPE_SOA) {
-
+
if (knot_packet_rcode(packet) != KNOT_RCODE_NOERROR) {
/*! \todo Handle error response. */
return KNOT_ERROR;
@@ -2975,7 +2478,7 @@ int zones_process_response(knot_nameserver_t *nameserver,
/* Match ID against awaited. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
uint16_t pkt_id = knot_packet_id(packet);
- if ((int)pkt_id != zd->xfr_in.next_id) {
+ if ((int)pkt_id != exp_msgid) {
rcu_read_unlock();
return KNOT_ERROR;
}
@@ -2989,59 +2492,47 @@ int zones_process_response(knot_nameserver_t *nameserver,
rcu_read_unlock();
return KNOT_ERROR;
}
-
+
/* No updates available. */
- evsched_t *sched =
- ((server_t *)knot_ns_get_data(nameserver))->sched;
if (ret == 0) {
- /* Reinstall timers. */
- zones_timers_update(zone, zd->conf, sched);
+ zones_schedule_refresh(zone, 0);
rcu_read_unlock();
return KNOT_EUPTODATE;
}
-
+
assert(ret > 0);
-
- /* Already transferring. */
- int xfrtype = zones_transfer_to_use(zd);
- if (pthread_mutex_trylock(&zd->xfr_in.lock) != 0) {
- /* Unlock zone contents. */
- dbg_zones("zones: SOA response received, but zone is "
- "being transferred, refusing to start another "
- "transfer\n");
+
+ /* Check zone transfer state. */
+ pthread_mutex_lock(&zd->lock);
+ if (zd->xfr_in.state == XFR_PENDING) {
+ pthread_mutex_unlock(&zd->lock);
rcu_read_unlock();
- return KNOT_EOK;
+ return KNOT_EOK; /* Already pending. */
} else {
- ++zd->xfr_in.scheduled;
- pthread_mutex_unlock(&zd->xfr_in.lock);
+ zd->xfr_in.state = XFR_PENDING;
}
/* Prepare XFR client transfer. */
- knot_ns_xfr_t xfr_req;
- memset(&xfr_req, 0, sizeof(knot_ns_xfr_t));
- memcpy(&xfr_req.addr, &zd->xfr_in.master, sizeof(sockaddr_t));
- memcpy(&xfr_req.saddr, &zd->xfr_in.via, sizeof(sockaddr_t));
- xfr_req.zone = (void *)zone;
- xfr_req.send = zones_send_cb;
-
- /* Select transfer method. */
- xfr_req.type = xfrtype;
-
- /* Select TSIG key. */
+ server_t *srv = (server_t *)knot_ns_get_data(nameserver);
+ int rqtype = zones_transfer_to_use(zd);
+ knot_ns_xfr_t *rq = xfr_task_create(zone, rqtype, XFR_FLAG_TCP);
+ if (!rq) {
+ pthread_mutex_unlock(&zd->lock);
+ rcu_read_unlock();
+ return KNOT_ENOMEM;
+ }
+ xfr_task_setaddr(rq, &zd->xfr_in.master, &zd->xfr_in.via);
if (zd->xfr_in.tsig_key.name) {
- xfr_req.tsig_key = &zd->xfr_in.tsig_key;
+ rq->tsig_key = &zd->xfr_in.tsig_key;
}
- /* Unlock zone contents. */
rcu_read_unlock();
-
- /* Retain pointer to zone for processing. */
- knot_zone_retain(xfr_req.zone);
- ret = xfr_request(((server_t *)knot_ns_get_data(
- nameserver))->xfr_h, &xfr_req);
+ ret = xfr_enqueue(srv->xfr, rq);
if (ret != KNOT_EOK) {
- knot_zone_release(xfr_req.zone); /* Discard */
+ xfr_task_free(rq);
+ zd->xfr_in.state = XFR_SCHED; /* Revert state */
}
+ pthread_mutex_unlock(&zd->lock);
}
return KNOT_EOK;
@@ -3054,7 +2545,7 @@ knot_ns_xfr_type_t zones_transfer_to_use(zonedata_t *data)
if (data == NULL || data->ixfr_db == NULL) {
return XFR_TYPE_AIN;
}
-
+
return XFR_TYPE_IIN;
}
@@ -3073,13 +2564,13 @@ static int zones_open_free_filename(const char *old_name, char **new_name)
dbg_zones_verb("zones: creating temporary zone file\n");
mode_t old_mode = umask(077);
int fd = mkstemp(*new_name);
- (void) umask(old_mode);
+ UNUSED(umask(old_mode));
if (fd < 0) {
dbg_zones_verb("zones: couldn't create temporary zone file\n");
free(*new_name);
*new_name = NULL;
}
-
+
return fd;
}
@@ -3092,11 +2583,9 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
char *new_fname = NULL;
int fd = zones_open_free_filename(fname, &new_fname);
if (fd < 0) {
- log_zone_warning("Failed to find filename for temporary "
- "storage of the transferred zone.\n");
- return KNOT_ERROR;
+ return FLOADER_EWRITABLE;
}
-
+
FILE *f = fdopen(fd, "w");
if (f == NULL) {
log_zone_warning("Failed to open file descriptor for text zone.\n");
@@ -3104,7 +2593,7 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
free(new_fname);
return KNOT_ERROR;
}
-
+
if (zone_dump_text(zone, f) != KNOT_EOK) {
log_zone_warning("Failed to save the transferred zone to '%s'.\n",
new_fname);
@@ -3113,143 +2602,43 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
free(new_fname);
return KNOT_ERROR;
}
-
+
/* Set zone file rights to 0640. */
fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
/* Swap temporary zonefile and new zonefile. */
fclose(f);
+
int ret = rename(new_fname, fname);
if (ret < 0 && ret != EEXIST) {
- log_zone_warning("Failed to replace old zone file '%s'' with a new"
- " zone file '%s'.\n", fname, new_fname);
+ log_zone_warning("Failed to replace old zone file '%s'' with a "
+ "new zone file '%s'.\n", fname, new_fname);
unlink(new_fname);
free(new_fname);
return KNOT_ERROR;
}
-
+
free(new_fname);
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int zones_dump_zone_binary(knot_zone_contents_t *zone,
- const char *zonedb,
- const char *zonefile)
-{
- assert(zone != NULL && zonedb != NULL);
-
- char *new_zonedb = NULL;
- int fd = zones_open_free_filename(zonedb, &new_zonedb);
- if (fd < 0) {
- dbg_zones("zones: failed to find free filename for temporary "
- "storage of the zone binary file '%s'\n",
- zonedb);
- return KNOT_ERROR;
- }
-
- crc_t crc_value = 0;
- if (knot_zdump_dump(zone, fd, zonefile, &crc_value) != KNOT_EOK) {
- close(fd);
- unlink(new_zonedb);
- free(new_zonedb);
- return KNOT_ERROR;
- }
-
- /* Set compiled zone rights to 0640. */
- fchmod(fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
-
- /* Close compiled zone. */
- close(fd);
-
- /* Delete old CRC file. */
- char *zonedb_crc = knot_zdump_crc_file(zonedb);
- if (zonedb_crc == NULL) {
- unlink(new_zonedb);
- free(new_zonedb);
- return KNOT_ENOMEM;
- }
- remove(zonedb_crc);
-
- /* New CRC file. */
- char *new_zonedb_crc = knot_zdump_crc_file(new_zonedb);
- if (new_zonedb_crc == NULL) {
- dbg_zdump("Failed to create CRC file path from %s.\n",
- new_zonedb);
- free(zonedb_crc);
- unlink(new_zonedb);
- free(new_zonedb);
- return KNOT_ENOMEM;
- }
-
- /* Write CRC value to CRC file. */
- FILE *f_crc = fopen(new_zonedb_crc, "w");
- if (f_crc == NULL) {
- dbg_zdump("Cannot open CRC file %s!\n",
- zonedb_crc);
- free(zonedb_crc);
- unlink(new_zonedb);
- free(new_zonedb);
- return KNOT_ERROR;
- } else {
- fprintf(f_crc, "%lu\n",
- (unsigned long)crc_value);
- fclose(f_crc);
- }
-
- /* Set CRC file rights to 0640. */
- chmod(new_zonedb_crc, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
-
- /* Swap CRC files. */
- int ret = KNOT_EOK;
- if (rename(new_zonedb_crc, zonedb_crc) < 0) {
- dbg_zdump("Failed to replace old zonedb CRC %s "
- "with new CRC zone file %s.\n",
- zonedb_crc,
- new_zonedb_crc);
- unlink(new_zonedb);
- unlink(new_zonedb_crc);
- ret = KNOT_ERROR;
- } else {
- /* Swap zone databases. */
- int swap_res = rename(new_zonedb, zonedb);
- if (swap_res < 0 && swap_res != EEXIST) {
- dbg_zdump("Failed to replace old zonedb %s "
- "with new zone file %s.\n",
- new_zonedb,
- zonedb);
- ret = KNOT_ERROR;
- unlink(new_zonedb);
- } else {
-
- }
- }
-
- free(new_zonedb_crc);
- free(zonedb_crc);
- free(new_zonedb);
-
-
- return ret;
-}
-
-/*----------------------------------------------------------------------------*/
-
int zones_save_zone(const knot_ns_xfr_t *xfr)
{
+ /* Zone is already referenced, no need for RCU locking. */
+
if (xfr == NULL || xfr->new_contents == NULL || xfr->zone == NULL) {
return KNOT_EINVAL;
}
-
- rcu_read_lock();
-
+
+ dbg_xfr("xfr: %s Saving new zone file.\n", xfr->msg);
+
zonedata_t *zd = (zonedata_t *)knot_zone_data(xfr->zone);
knot_zone_contents_t *new_zone = xfr->new_contents;
-
+
const char *zonefile = zd->conf->file;
- const char *zonedb = zd->conf->db;
-
+
/* Check if the new zone apex dname matches zone name. */
knot_dname_t *cur_name = knot_dname_new_from_str(zd->conf->name,
strlen(zd->conf->name),
@@ -3259,28 +2648,14 @@ int zones_save_zone(const knot_ns_xfr_t *xfr)
int r = knot_dname_compare(cur_name, new_name);
knot_dname_free(&cur_name);
if (r != 0) {
- rcu_read_unlock();
return KNOT_EINVAL;
}
-
- assert(zonefile != NULL && zonedb != NULL);
-
+
+ assert(zonefile != NULL);
+
/* dump the zone into text zone file */
int ret = zones_dump_zone_text(new_zone, zonefile);
- if (ret != KNOT_EOK) {
- rcu_read_unlock();
- return KNOT_ERROR;
- }
- /* dump the zone into binary db file */
- ret = zones_dump_zone_binary(new_zone, zonedb, zonefile);
- if (ret != KNOT_EOK) {
- rcu_read_unlock();
- return KNOT_ERROR;
- }
-
- rcu_read_unlock();
-
- return KNOT_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -3289,10 +2664,15 @@ int zones_ns_conf_hook(const struct conf_t *conf, void *data)
{
knot_nameserver_t *ns = (knot_nameserver_t *)data;
dbg_zones_verb("zones: reconfiguring name server.\n");
-
+
/* Set NSID. */
knot_ns_set_nsid(ns, conf->nsid, conf->nsid_len);
+ /* Server identification, RFC 4892. */
+ ns->identity = conf->identity;
+ ns->version = conf->version;
+ ns->hostname = conf->hostname;
+
knot_zonedb_t *old_db = 0;
int ret = zones_update_db_from_config(conf, ns, &old_db);
@@ -3308,82 +2688,30 @@ int zones_ns_conf_hook(const struct conf_t *conf, void *data)
/* Delete all deprecated zones and delete the old database. */
knot_zonedb_deep_free(&old_db);
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/* Counting size of changeset in serialized form. */
-/*----------------------------------------------------------------------------*/
-
-static inline size_t zones_dname_binary_size(const knot_dname_t *dname)
-{
- if (dname == NULL) {
- return 0;
+ /* Update events scheduled for zone. */
+ rcu_read_lock();
+ knot_zone_t **zones = (knot_zone_t **)knot_zonedb_zones(ns->zone_db);
+ if (zones == NULL) {
+ rcu_read_unlock();
+ return KNOT_ENOMEM;
}
- size_t size = 10; // 4B ID, 4B size, 2B label count
-
- // dname size in wire format
- size += knot_dname_size(dname);
- // label array size
- size += knot_dname_label_count(dname);
-
- return size;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static size_t zones_rdata_binary_size(const knot_rdata_t *rdata,
- knot_rrtype_descriptor_t *desc)
-{
- if (rdata == NULL) {
- return 0;
+ /* REFRESH zones. */
+ for (unsigned i = 0; i < knot_zonedb_zone_count(ns->zone_db); ++i) {
+ /* Refresh new slave zones (almost) immediately. */
+ zones_schedule_refresh(zones[i], tls_rand() * 500 + i/2);
+ zones_schedule_notify(zones[i]);
}
- assert(desc != NULL);
-
- size_t size = sizeof(unsigned int); // RDATA item count
-
- for (int i = 0; i < rdata->count; ++i) {
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME
- || desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME) {
- size += zones_dname_binary_size(rdata->items[i].dname);
- size += 2; // flags
- } else {
- if (rdata->items[i].raw_data != NULL) {
- size += rdata->items[i].raw_data[0] + 2;
- }
- }
- }
+ /* Unlock RCU. */
+ rcu_read_unlock();
+ free(zones);
- return size;
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-
-static size_t zones_rrset_binary_size(const knot_rrset_t *rrset)
-{
- assert(rrset != NULL);
-
- size_t size = 0;
-
- size += 13; // 2B type, 2B class, 4B TTL, 4B RDATA count, 1B flags
- size += zones_dname_binary_size(rrset->owner);
-
- knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(
- knot_rrset_type(rrset));
- assert(desc != NULL);
-
- const knot_rdata_t *rdata = knot_rrset_rdata(rrset);
- while (rdata != NULL) {
- size += zones_rdata_binary_size(rdata, desc);
- rdata = knot_rrset_rdata_next(rrset, rdata);
- }
-
- return size;
-}
-
+/* Counting size of changeset in serialized form. */
/*----------------------------------------------------------------------------*/
int zones_changeset_binary_size(const knot_changeset_t *chgset, size_t *size)
@@ -3392,19 +2720,19 @@ int zones_changeset_binary_size(const knot_changeset_t *chgset, size_t *size)
return KNOT_EINVAL;
}
- size_t soa_from_size = zones_rrset_binary_size(chgset->soa_from);
- size_t soa_to_size = zones_rrset_binary_size(chgset->soa_to);
+ size_t soa_from_size = rrset_binary_size(chgset->soa_from);
+ size_t soa_to_size = rrset_binary_size(chgset->soa_to);
size_t remove_size = 0;
for (int i = 0; i < chgset->remove_count; ++i)
{
- remove_size += zones_rrset_binary_size(chgset->remove[i]);
+ remove_size += rrset_binary_size(chgset->remove[i]);
}
size_t add_size = 0;
for (int i = 0; i < chgset->add_count; ++i)
{
- add_size += zones_rrset_binary_size(chgset->add[i]);
+ add_size += rrset_binary_size(chgset->add[i]);
}
/*! \todo How is the changeset serialized? Any other parts? */
@@ -3422,14 +2750,14 @@ int zones_changeset_binary_size(const knot_changeset_t *chgset, size_t *size)
static int zones_rrset_write_to_mem(const knot_rrset_t *rr, char **entry,
size_t *remaining) {
size_t written = 0;
- int ret = knot_zdump_rrset_serialize(rr, *((uint8_t **)entry),
- *remaining, &written);
+ int ret = rrset_serialize(rr, *((uint8_t **)entry),
+ &written);
if (ret == KNOT_EOK) {
assert(written <= *remaining);
*remaining -= written;
*entry += written;
}
-
+
return ret;
}
@@ -3440,7 +2768,7 @@ static int zones_serialize_and_store_chgset(const knot_changeset_t *chs,
memcpy(entry, (char*)&chs->flags, sizeof(uint32_t));
entry += sizeof(uint32_t);
max_size -= sizeof(uint32_t);
-
+
/* Serialize SOA 'from'. */
int ret = zones_rrset_write_to_mem(chs->soa_from, &entry, &max_size);
if (ret != KNOT_EOK) {
@@ -3506,48 +2834,6 @@ static int zones_store_changeset(const knot_changeset_t *chs, journal_t *j,
/* Reserve space for the journal entry. */
char *journal_entry = NULL;
ret = journal_map(j, k, &journal_entry, entry_size);
-
- /* Sync to zonefile may be needed. */
- while (ret == KNOT_EAGAIN) {
- /* Cancel sync timer. */
- event_t *tmr = zd->ixfr_dbsync;
- if (tmr) {
- dbg_xfr_verb("xfr: cancelling zonefile "
- "SYNC timer of '%s'\n",
- zd->conf->name);
- evsched_cancel(tmr->parent, tmr);
- }
-
- /* Synchronize. */
- dbg_xfr_verb("xfr: forcing zonefile SYNC "
- "of '%s'\n",
- zd->conf->name);
- ret = zones_zonefile_sync(zone, j);
- if (ret != KNOT_EOK && ret != KNOT_ERANGE) {
- continue;
- }
-
- /* Reschedule sync timer. */
- if (tmr) {
- /* Fetch sync timeout. */
- rcu_read_lock();
- int timeout = zd->conf->dbsync_timeout;
- timeout *= 1000; /* Convert to ms. */
- rcu_read_unlock();
-
- /* Reschedule. */
- dbg_xfr_verb("xfr: resuming SYNC "
- "of '%s'\n",
- zd->conf->name);
- evsched_schedule(tmr->parent, tmr,
- timeout);
-
- }
-
- /* Attempt to map again. */
- ret = journal_map(j, k, &journal_entry, entry_size);
- }
-
if (ret != KNOT_EOK) {
dbg_xfr("Failed to map space for journal entry: %s.\n",
knot_strerror(ret));
@@ -3592,7 +2878,7 @@ journal_t *zones_store_changesets_begin(knot_zone_t *zone)
journal_release(j);
j = NULL;
}
-
+
return j;
}
@@ -3603,7 +2889,7 @@ int zones_store_changesets_commit(journal_t *j)
if (j == NULL) {
return KNOT_EINVAL;
}
-
+
int ret = journal_trans_commit(j);
journal_release(j);
return ret;
@@ -3616,7 +2902,7 @@ int zones_store_changesets_rollback(journal_t *j)
if (j == NULL) {
return KNOT_EINVAL;
}
-
+
int ret = journal_trans_rollback(j);
journal_release(j);
return ret;
@@ -3630,8 +2916,7 @@ int zones_store_changesets(knot_zone_t *zone, knot_changesets_t *src)
return KNOT_EINVAL;
}
-// knot_zone_t *zone = xfr->zone;
-// knot_changesets_t *src = (knot_changesets_t *)xfr->data;
+ int ret = KNOT_EOK;
/* Fetch zone-specific data. */
zonedata_t *zd = (zonedata_t *)zone->data;
@@ -3644,7 +2929,6 @@ int zones_store_changesets(knot_zone_t *zone, knot_changesets_t *src)
if (j == NULL) {
return KNOT_EBUSY;
}
- int ret = 0;
/* Begin writing to journal. */
for (unsigned i = 0; i < src->count; ++i) {
@@ -3652,43 +2936,48 @@ int zones_store_changesets(knot_zone_t *zone, knot_changesets_t *src)
knot_changeset_t* chs = src->sets + i;
ret = zones_store_changeset(chs, j, zone, zd);
- if (ret != KNOT_EOK) {
- journal_release(j);
- return ret;
- }
+ if (ret != KNOT_EOK)
+ break;
}
/* Release journal. */
journal_release(j);
+ /* Flush if the journal is full. */
+ event_t *tmr = zd->ixfr_dbsync;
+ if (ret == KNOT_EBUSY && tmr) {
+ log_server_notice("Journal for '%s' is full, flushing.\n",
+ zd->conf->name);
+ evsched_cancel(tmr->parent, tmr);
+ evsched_schedule(tmr->parent, tmr, 0);
+ }
+
/* Written changesets to journal. */
- return KNOT_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
int zones_xfr_load_changesets(knot_ns_xfr_t *xfr, uint32_t serial_from,
- uint32_t serial_to)
+ uint32_t serial_to)
{
if (!xfr || !xfr->zone || !knot_zone_contents(xfr->zone)) {
- dbg_zones_detail("Wrong parameters: xfr=%p,"
- " xfr->zone = %p\n", xfr, xfr->zone);
return KNOT_EINVAL;
}
-
+
knot_changesets_t *chgsets = (knot_changesets_t *)
calloc(1, sizeof(knot_changesets_t));
CHECK_ALLOC_LOG(chgsets, KNOT_ENOMEM);
-
+
int ret = ns_serial_compare(serial_to, serial_from);
dbg_zones_verb("Compared serials, result: %d\n", ret);
-
+
/* if serial_to is not larger than serial_from, do not load anything */
if (ret <= 0) {
xfr->data = chgsets;
return KNOT_EOK;
}
-
+
dbg_xfr_verb("xfr: loading changesets\n");
ret = zones_load_changesets(xfr->zone, chgsets,
serial_from, serial_to);
@@ -3698,7 +2987,7 @@ int zones_xfr_load_changesets(knot_ns_xfr_t *xfr, uint32_t serial_from,
knot_free_changesets(&chgsets);
return ret;
}
-
+
xfr->data = chgsets;
return KNOT_EOK;
}
@@ -3714,7 +3003,7 @@ int zones_create_and_save_changesets(const knot_zone_t *old_zone,
"NULL arguments.\n");
return KNOT_EINVAL;
}
-
+
knot_ns_xfr_t xfr;
memset(&xfr, 0, sizeof(xfr));
xfr.zone = (knot_zone_t *)old_zone;
@@ -3743,7 +3032,7 @@ int zones_create_and_save_changesets(const knot_zone_t *old_zone,
return KNOT_ERROR;
}
}
-
+
xfr.data = changesets;
journal_t *journal = zones_store_changesets_begin(xfr.zone);
if (journal == NULL) {
@@ -3751,28 +3040,28 @@ int zones_create_and_save_changesets(const knot_zone_t *old_zone,
"Could not start journal operation.\n");
return KNOT_ERROR;
}
-
+
ret = zones_store_changesets(xfr.zone, (knot_changesets_t *)xfr.data);
if (ret != KNOT_EOK) {
zones_store_changesets_rollback(journal);
dbg_zones("zones: create_changesets: "
"Could not store in the journal. Reason: %s.\n",
knot_strerror(ret));
-
+
return ret;
}
-
+
ret = zones_store_changesets_commit(journal);
if (ret != KNOT_EOK) {
dbg_zones("zones: create_changesets: "
"Could not commit to journal. Reason: %s.\n",
knot_strerror(ret));
-
+
return ret;
}
-
+
knot_free_changesets(&changesets);
-
+
return KNOT_EOK;
}
@@ -3797,9 +3086,9 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs,
}
if (ret != KNOT_EOK) {
log_zone_error("%s Failed to serialize and store "
- "changesets - %s\n", msgpref,
- knot_strerror(ret));
+ "changesets.\n", msgpref);
/* Free changesets, but not the data. */
+ zones_store_changesets_rollback(transaction);
knot_free_changesets(&chs);
return ret;
}
@@ -3808,11 +3097,10 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs,
apply_ret = xfrin_apply_changesets(zone, chs, new_contents);
if (apply_ret != KNOT_EOK) {
- zones_store_changesets_rollback(transaction);
- log_zone_error("%s Failed to apply changesets - %s\n",
- msgpref, knot_strerror(apply_ret));
+ log_zone_error("%s Failed to apply changesets.\n", msgpref);
/* Free changesets, but not the data. */
+ zones_store_changesets_rollback(transaction);
knot_free_changesets(&chs);
return apply_ret; // propagate the error above
}
@@ -3821,8 +3109,7 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs,
ret = zones_store_changesets_commit(transaction);
if (ret != KNOT_EOK) {
/*! \todo THIS WILL LEAK!! xfrin_rollback_update() needed. */
- log_zone_error("%s Failed to commit stored changesets "
- "- %s\n", msgpref, knot_strerror(apply_ret));
+ log_zone_error("%s Failed to commit stored changesets.\n", msgpref);
knot_free_changesets(&chs);
return ret;
}
@@ -3831,8 +3118,7 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs,
switch_ret = xfrin_switch_zone(zone, *new_contents, type);
if (switch_ret != KNOT_EOK) {
- log_zone_error("%s Failed to replace current zone - %s\n",
- msgpref, knot_strerror(switch_ret));
+ log_zone_error("%s Failed to replace current zone.\n", msgpref);
// Cleanup old and new contents
xfrin_rollback_update(zone->contents, new_contents,
&chs->changes);
@@ -3847,172 +3133,96 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs,
/* Free changesets, but not the data. */
knot_free_changesets(&chs);
assert(ret == KNOT_EOK);
- log_zone_info("%s Finished.\n", msgpref);
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
+int zones_schedule_notify(knot_zone_t *zone)
{
- if (!sch || !zone) {
- return KNOT_EINVAL;
- }
-
- /* Fetch zone data. */
- zonedata_t *zd = (zonedata_t *)zone->data;
- if (!zd) {
- return KNOT_EINVAL;
- }
-
- /* Cancel REFRESH timer. */
- if (zd->xfr_in.timer) {
- evsched_cancel(sch, zd->xfr_in.timer);
- evsched_event_free(sch, zd->xfr_in.timer);
- zd->xfr_in.timer = 0;
- }
-
- /* Cancel EXPIRE timer. */
- if (zd->xfr_in.expire) {
- evsched_cancel(sch, zd->xfr_in.expire);
- evsched_event_free(sch, zd->xfr_in.expire);
- zd->xfr_in.expire = 0;
- }
-
- /* Remove list of pending NOTIFYs. */
- pthread_mutex_lock(&zd->lock);
- notify_ev_t *ev = 0, *evn = 0;
- WALK_LIST_DELSAFE(ev, evn, zd->notify_pending) {
- zones_cancel_notify(zd, ev);
- }
- pthread_mutex_unlock(&zd->lock);
-
- /* Check XFR/IN master server. */
- rcu_read_lock();
- if (zd->xfr_in.has_master) {
-
- /* Schedule REFRESH timer. */
- uint32_t refresh_tmr = 0;
- if (knot_zone_contents(zone)) {
- refresh_tmr = zones_jitter(zones_soa_refresh(zone));
- } else {
- refresh_tmr = zd->xfr_in.bootstrap_retry;
- }
- zd->xfr_in.timer = evsched_schedule_cb(sch, zones_refresh_ev,
- zone, refresh_tmr);
- dbg_zones("zone: REFRESH '%s' set to %u\n",
- cfzone->name, refresh_tmr);
- }
-
/* Do not issue NOTIFY queries if stub. */
if (!knot_zone_contents(zone)) {
- rcu_read_unlock();
return KNOT_EOK;
}
/* Schedule NOTIFY to slaves. */
+ zonedata_t *zd = (zonedata_t *)zone->data;
+ conf_zone_t *cfg = zd->conf;
conf_remote_t *r = 0;
- WALK_LIST(r, cfzone->acl.notify_out) {
+ WALK_LIST(r, cfg->acl.notify_out) {
/* Fetch remote. */
conf_iface_t *cfg_if = r->remote;
/* Create request. */
- notify_ev_t *ev = malloc(sizeof(notify_ev_t));
- if (!ev) {
- free(ev);
- dbg_zones("notify: out of memory to create "
- "NOTIFY query for %s\n", cfg_if->name);
+ knot_ns_xfr_t *rq = xfr_task_create(zone, XFR_TYPE_NOTIFY, XFR_FLAG_UDP);
+ if (!rq) {
+ log_server_error("Failed to create NOTIFY for '%s', "
+ "not enough memory.\n", cfg->name);
continue;
}
/* Parse server address. */
- sockaddr_init(&ev->saddr, -1);
- int ret = sockaddr_set(&ev->addr, cfg_if->family,
- cfg_if->address,
- cfg_if->port);
- sockaddr_t *via = &cfg_if->via;
- if (ret > 0) {
- if (sockaddr_isvalid(via)) {
- sockaddr_copy(&ev->saddr, via);
- }
- } else {
- free(ev);
- log_server_warning("NOTIFY slave '%s' has invalid "
- "address '%s@%d', couldn't create"
- "query.\n", cfg_if->name,
- cfg_if->address, cfg_if->port);
+ sockaddr_t addr;
+ sockaddr_set(&addr, cfg_if->family, cfg_if->address, cfg_if->port);
+ xfr_task_setaddr(rq, &addr, &cfg_if->via);
+ rq->data = (void *)((long)cfg->notify_retries + 1);
+ if (xfr_enqueue(zd->server->xfr, rq) != KNOT_EOK) {
+ log_server_error("Failed to enqueue NOTIFY for '%s'.",
+ cfg->name);
continue;
}
-
- /* Prepare request. */
- ev->retries = cfzone->notify_retries + 1; /* first + N retries*/
- ev->msgid = 0;
- ev->zone = zone;
- ev->timeout = cfzone->notify_timeout;
-
- /* Schedule request (30 - 60s random delay). */
- int tmr_s = 30 + (int)(30.0 * tls_rand());
- pthread_mutex_lock(&zd->lock);
- ev->timer = evsched_schedule_cb(sch, zones_notify_send, ev,
- tmr_s * 1000);
- add_tail(&zd->notify_pending, &ev->n);
- pthread_mutex_unlock(&zd->lock);
-
- log_server_info("Scheduled '%s' NOTIFY query "
- "after %d s to '%s@%d'.\n", zd->conf->name,
- tmr_s, cfg_if->address, cfg_if->port);
}
- rcu_read_unlock();
-
return KNOT_EOK;
}
-int zones_cancel_notify(zonedata_t *zd, notify_ev_t *ev)
+int zones_schedule_refresh(knot_zone_t *zone, unsigned time)
{
- if (!zd || !ev || !ev->timer) {
+ if (!zone || !zone->data) {
return KNOT_EINVAL;
}
- /* Wait for event to finish running. */
-#ifdef KNOTD_NOTIFY_DEBUG
- int pkt_id = ev->msgid; /*< Do not optimize! */
-#endif
- event_t *tmr = ev->timer;
- ev->timer = 0;
- pthread_mutex_unlock(&zd->lock);
- if (evsched_cancel(tmr->parent, tmr) == 0) {
- dbg_notify("notify: NOTIFY event %p designated for cancellation "
- "not found\n", tmr);
+ /* Cancel REFRESH timer. */
+ zonedata_t *zd = (zonedata_t *)zone->data;
+ evsched_t *sch = zd->server->sched;
+ if (zd->xfr_in.timer) {
+ evsched_cancel(sch, zd->xfr_in.timer);
+ evsched_event_free(sch, zd->xfr_in.timer);
+ zd->xfr_in.timer = 0;
}
- /* Re-lock and find again (if not deleted). */
- pthread_mutex_lock(&zd->lock);
- int match_exists = 0;
- notify_ev_t *tmpev = 0;
- WALK_LIST(tmpev, zd->notify_pending) {
- if (tmpev == ev) {
- match_exists = 1;
- break;
- }
+ /* Cancel EXPIRE timer. */
+ if (zd->xfr_in.expire) {
+ evsched_cancel(sch, zd->xfr_in.expire);
+ evsched_event_free(sch, zd->xfr_in.expire);
+ zd->xfr_in.expire = 0;
}
- /* Event deleted before cancelled. */
- if (!match_exists) {
- dbg_notify("notify: NOTIFY event for query ID=%u was "
- "deleted before cancellation.\n",
- pkt_id);
- return KNOT_EOK;
+ /* Check XFR/IN master server. */
+ pthread_mutex_lock(&zd->lock);
+ rcu_read_lock();
+ zd->xfr_in.state = XFR_IDLE;
+ if (zd->xfr_in.has_master) {
+ /* Schedule REFRESH timer. */
+ uint32_t refresh_tmr = time;
+ if (refresh_tmr == 0) {
+ if (knot_zone_contents(zone)) {
+ refresh_tmr = zones_jitter(zones_soa_refresh(zone));
+ } else {
+ refresh_tmr = zd->xfr_in.bootstrap_retry;
+ }
+ }
+ zd->xfr_in.timer = evsched_schedule_cb(sch, zones_refresh_ev,
+ zone, refresh_tmr);
+ dbg_zones("zone: REFRESH '%s' set to %u\n",
+ zd->conf->name, refresh_tmr);
+ zd->xfr_in.state = XFR_SCHED;
}
+ rcu_read_unlock();
+ pthread_mutex_unlock(&zd->lock);
- /* Free event (won't be scheduled again). */
- dbg_notify("notify: NOTIFY query ID=%u event cancelled.\n",
- pkt_id);
- rem_node(&ev->n);
- evsched_event_free(tmr->parent, tmr);
- free(ev);
return KNOT_EOK;
}
@@ -4025,13 +3235,13 @@ int zones_process_update_response(knot_ns_xfr_t *data, uint8_t *rwire, size_t *r
knot_wire_set_id(rwire, (uint16_t)data->packet_nr);
/* Forward the response. */
- ret = data->send(data->fwd_src_fd, &data->saddr, rwire, *rsize);
+ ret = data->send(data->fwd_src_fd, &data->fwd_addr, rwire, *rsize);
if (ret != *rsize) {
ret = KNOT_ECONN;
} else {
ret = KNOT_EOK;
}
-
+
/* As it is a response, do not reply back. */
*rsize = 0;
return ret;
@@ -4039,14 +3249,14 @@ int zones_process_update_response(knot_ns_xfr_t *data, uint8_t *rwire, size_t *r
int zones_verify_tsig_query(const knot_packet_t *query,
- const knot_key_t *key,
+ const knot_tsig_key_t *key,
knot_rcode_t *rcode, uint16_t *tsig_rcode,
uint64_t *tsig_prev_time_signed)
{
assert(key != NULL);
assert(rcode != NULL);
assert(tsig_rcode != NULL);
-
+
const knot_rrset_t *tsig_rr = knot_packet_tsig(query);
if (tsig_rr == NULL) {
dbg_zones("TSIG key required, but not in query - REFUSED.\n");
@@ -4057,8 +3267,8 @@ int zones_verify_tsig_query(const knot_packet_t *query,
/*
* 1) Check if we support the requested algorithm.
*/
- tsig_algorithm_t alg = tsig_rdata_alg(tsig_rr);
- if (tsig_alg_digest_length(alg) == 0) {
+ knot_tsig_algorithm_t alg = tsig_rdata_alg(tsig_rr);
+ if (knot_tsig_digest_length(alg) == 0) {
log_answer_info("Unsupported digest algorithm "
"requested, treating as bad key\n");
/*! \todo [TSIG] It is unclear from RFC if I
@@ -4066,7 +3276,7 @@ int zones_verify_tsig_query(const knot_packet_t *query,
* or some other error.
*/
*rcode = KNOT_RCODE_NOTAUTH;
- *tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
+ *tsig_rcode = KNOT_RCODE_BADKEY;
return KNOT_TSIG_EBADKEY;
}
@@ -4082,7 +3292,7 @@ int zones_verify_tsig_query(const knot_packet_t *query,
dbg_zones_verb("Found claimed TSIG key for comparison\n");
} else {
*rcode = KNOT_RCODE_NOTAUTH;
- *tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
+ *tsig_rcode = KNOT_RCODE_BADKEY;
return KNOT_TSIG_EBADKEY;
}
@@ -4092,7 +3302,7 @@ int zones_verify_tsig_query(const knot_packet_t *query,
/* Prepare variables for TSIG */
/*! \todo These need to be saved to the response somehow. */
//size_t tsig_size = tsig_wire_maxsize(key);
- size_t digest_max_size = tsig_alg_digest_length(key->algorithm);
+ size_t digest_max_size = knot_tsig_digest_length(key->algorithm);
//size_t digest_size = 0;
//uint64_t tsig_prev_time_signed = 0;
//uint8_t *digest = (uint8_t *)malloc(digest_max_size);
@@ -4128,15 +3338,15 @@ int zones_verify_tsig_query(const knot_packet_t *query,
*rcode = KNOT_RCODE_NOERROR;
break;
case KNOT_TSIG_EBADKEY:
- *tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
+ *tsig_rcode = KNOT_RCODE_BADKEY;
*rcode = KNOT_RCODE_NOTAUTH;
break;
case KNOT_TSIG_EBADSIG:
- *tsig_rcode = KNOT_TSIG_RCODE_BADSIG;
+ *tsig_rcode = KNOT_RCODE_BADSIG;
*rcode = KNOT_RCODE_NOTAUTH;
break;
case KNOT_TSIG_EBADTIME:
- *tsig_rcode = KNOT_TSIG_RCODE_BADTIME;
+ *tsig_rcode = KNOT_RCODE_BADTIME;
// store the time signed from the query
*tsig_prev_time_signed = tsig_rdata_time_signed(tsig_rr);
*rcode = KNOT_RCODE_NOTAUTH;
diff --git a/src/knot/server/zones.h b/src/knot/server/zones.h
index 89834a6..5045d50 100644
--- a/src/knot/server/zones.h
+++ b/src/knot/server/zones.h
@@ -44,7 +44,7 @@
/* Constants. */
#define ZONES_JITTER_PCT 10 /*!< +-N% jitter to timers. */
#define IXFR_DBSYNC_TIMEOUT (60*1000) /*!< Database sync timeout = 60s. */
-#define AXFR_BOOTSTRAP_RETRY (60*1000) /*!< Interval between AXFR BS retries. */
+#define AXFR_BOOTSTRAP_RETRY (30*1000) /*!< Interval between AXFR BS retries. */
/*!
* \brief Zone-related data.
@@ -59,7 +59,7 @@ typedef struct zonedata_t
/*! \brief Zone data lock for exclusive access. */
pthread_mutex_t lock;
-
+
/*! \brief Access control lists. */
acl_t *xfr_out; /*!< ACL for xfr-out.*/
acl_t *notify_in; /*!< ACL for notify-in.*/
@@ -68,23 +68,17 @@ typedef struct zonedata_t
/*! \brief XFR-IN scheduler. */
struct {
- acl_t *acl; /*!< ACL for xfr-in.*/
- sockaddr_t master; /*!< Master server for xfr-in.*/
- sockaddr_t via; /*!< Master server transit interface.*/
- knot_key_t tsig_key; /*!< Master TSIG key. */
- struct event_t *timer; /*!< Timer for REFRESH/RETRY. */
- struct event_t *expire; /*!< Timer for REFRESH. */
- pthread_mutex_t lock; /*!< Pending XFR/IN lock. */
- void *wrkr; /*!< Pending XFR/IN worker. */
- int next_id; /*!< ID of the next awaited SOA resp.*/
- uint32_t bootstrap_retry;/*!< AXFR/IN bootstrap retry. */
- unsigned scheduled;/*!< Scheduled operations. */
- int has_master; /*!< True if it has master set. */
+ acl_t *acl; /*!< ACL for xfr-in.*/
+ sockaddr_t master; /*!< Master server for xfr-in.*/
+ sockaddr_t via; /*!< Master server transit interface.*/
+ knot_tsig_key_t tsig_key; /*!< Master TSIG key. */
+ struct event_t *timer; /*!< Timer for REFRESH/RETRY. */
+ struct event_t *expire; /*!< Timer for REFRESH. */
+ uint32_t bootstrap_retry; /*!< AXFR/IN bootstrap retry. */
+ int has_master; /*!< True if it has master set. */
+ unsigned state;
} xfr_in;
- /*! \brief List of pending NOTIFY events. */
- list notify_pending;
-
/*! \brief Zone IXFR history. */
journal_t *ixfr_db;
struct event_t *ixfr_dbsync; /*!< Syncing IXFR db to zonefile. */
@@ -138,7 +132,7 @@ int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal);
* \todo Document me.
*/
int zones_query_check_zone(const knot_zone_t *zone, uint8_t q_opcode,
- const sockaddr_t *addr, knot_key_t **tsig_key,
+ const sockaddr_t *addr, knot_tsig_key_t **tsig_key,
knot_rcode_t *rcode);
/*!
@@ -176,7 +170,8 @@ int zones_process_update(knot_nameserver_t *nameserver,
* \retval KNOT_EINVAL on invalid parameters or packet.
* \retval KNOT_EMALF if an error occured and the response is not valid.
*/
-int zones_process_response(knot_nameserver_t *nameserver,
+int zones_process_response(knot_nameserver_t *nameserver,
+ int exp_msgid,
sockaddr_t *from,
knot_packet_t *packet, uint8_t *response_wire,
size_t *rsize);
@@ -306,31 +301,23 @@ int zones_store_and_apply_chgsets(knot_changesets_t *chs,
*
* REFRESH/RETRY/EXPIRE timers are updated according to SOA.
*
- * \param sched Event scheduler.
* \param zone Related zone.
- * \param cfzone Related zone contents. If NULL, configuration is
- * reused.
+ * \param time Specific time or 0 for default.
*
* \retval KNOT_EOK
* \retval KNOT_EINVAL
* \retval KNOT_ERROR
*/
-int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch);
+int zones_schedule_refresh(knot_zone_t *zone, unsigned time);
/*!
- * \brief Cancel pending NOTIFY timer.
- *
- * \warning Expects locked zonedata lock.
- *
- * \param zd Zone data.
- * \param ev NOTIFY event.
+ * \brief Schedule NOTIFY after zone update.
+ * \param zone Related zone.
*
* \retval KNOT_EOK
* \retval KNOT_ERROR
- * \retval KNOT_EINVAL
*/
-int zones_cancel_notify(zonedata_t *zd, notify_ev_t *ev);
-
+int zones_schedule_notify(knot_zone_t *zone);
/*!
* \brief Processes forwarded UPDATE response packet.
@@ -350,9 +337,10 @@ int zones_process_update_response(knot_ns_xfr_t *data, uint8_t *rwire, size_t *r
* \return KNOT_EOK if verified or error if not.
*/
int zones_verify_tsig_query(const knot_packet_t *query,
- const knot_key_t *key,
+ const knot_tsig_key_t *key,
knot_rcode_t *rcode, uint16_t *tsig_rcode,
uint64_t *tsig_prev_time_signed);
+
#endif // _KNOTD_ZONES_H_
/*! @} */
diff --git a/src/knot/stat/gatherer.h b/src/knot/stat/gatherer.h
index 62b3939..0bb6829 100644
--- a/src/knot/stat/gatherer.h
+++ b/src/knot/stat/gatherer.h
@@ -19,7 +19,7 @@
* \author Jan Kadlec <jan.kadlec@nic.cz>
*
* \brief Contains gatherer structure and its API.
- *
+ *
* \addtogroup statistics
* @{
*/
@@ -55,7 +55,7 @@ struct flow_data {
typedef struct flow_data flow_data_t;
/*!
- * \brief Gatherer structure, used for gathering statistics from
+ * \brief Gatherer structure, used for gathering statistics from
* multiple threads.
*/
struct gatherer {
diff --git a/src/knot/stat/stat.c b/src/knot/stat/stat.c
index 01bbbc4..10947ba 100644
--- a/src/knot/stat/stat.c
+++ b/src/knot/stat/stat.c
@@ -21,8 +21,8 @@
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
-#include <arpa/inet.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
diff --git a/src/knot/zone/estimator.c b/src/knot/zone/estimator.c
new file mode 100644
index 0000000..a939851
--- /dev/null
+++ b/src/knot/zone/estimator.c
@@ -0,0 +1,262 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <assert.h>
+
+#include "estimator.h"
+#include "dname.h"
+#include "common/lists.h"
+#include "libknot/zone/node.h"
+#include "common/hattrie/ahtable.h"
+#include "zscanner/scanner.h"
+#include "common/descriptor.h"
+
+// Constants used for tweaking, mostly malloc overhead
+enum estim_consts {
+ MALLOC_OVER = sizeof(size_t), // according to malloc.c, this is minimum
+ DNAME_MULT = 1,
+ DNAME_ADD = MALLOC_OVER * 3, // dname itself, labels, name
+ RDATA_MULT = 1,
+ RDATA_ADD = MALLOC_OVER, // just raw rdata, but allocation is there
+ RRSET_MULT = 1,
+ RRSET_ADD = MALLOC_OVER * 3, // rrset itself, rdata array, indices
+ NODE_MULT = 1,
+ NODE_ADD = MALLOC_OVER * 2, // node itself, rrset array
+ AHTABLE_ADD = MALLOC_OVER * 3, // table, slots, slot sizes
+ MALLOC_MIN = 3 * MALLOC_OVER // minimun size of malloc'd chunk, -overhead
+};
+
+typedef struct type_list_item {
+ node n;
+ uint16_t type;
+} type_list_item_t;
+
+typedef struct dummy_node {
+ // For now only contains list of RR types
+ list node_list;
+} dummy_node_t;
+
+// return: 0 not present, 1 - present
+static int find_in_list(list *node_list, uint16_t type)
+{
+ node *n = NULL;
+ WALK_LIST(n, *node_list) {
+ type_list_item_t *l_entr = (type_list_item_t *)n;
+ assert(l_entr);
+ if (l_entr->type == type) {
+ return 1;
+ }
+ }
+
+ type_list_item_t *new_entry = xmalloc(sizeof(type_list_item_t));
+ new_entry->type = type;
+
+ add_head(node_list, (node *)new_entry);
+ return 0;
+}
+
+// return: 0 not present (added), 1 - present
+static int dummy_node_add_type(dummy_node_t *n, uint16_t t)
+{
+ return find_in_list(&n->node_list, t);
+}
+
+static size_t dname_memsize(const knot_dname_t *d)
+{
+ size_t d_size = d->size;
+ size_t l_size = d->label_count;
+ if (d->size < MALLOC_MIN) {
+ d_size = MALLOC_MIN;
+ }
+ if (d->label_count < MALLOC_MIN) {
+ l_size = MALLOC_MIN;
+ }
+
+ return (sizeof(knot_dname_t) + d_size + l_size)
+ * DNAME_MULT + DNAME_ADD;
+}
+
+// return: 0 - unique, 1 - duplicate
+static int insert_dname_into_table(hattrie_t *table, knot_dname_t *d,
+ dummy_node_t **n)
+{
+ value_t *val = hattrie_tryget(table, (char *)d->name, d->size);
+ if (val == NULL) {
+ // Create new dummy node to use for this dname
+ *n = xmalloc(sizeof(dummy_node_t));
+ init_list(&(*n)->node_list);
+ *hattrie_get(table, (char *)d->name, d->size) = *n;
+ return 0;
+ } else {
+ // Return previously found dummy node
+ *n = (dummy_node_t *)(*val);
+ return 1;
+ }
+}
+
+// return: RDATA memsize, minus size of dnames inside
+static size_t rdata_memsize(zone_estim_t *est, const scanner_t *scanner)
+{
+ const rdata_descriptor_t *desc = get_rdata_descriptor(scanner->r_type);
+ size_t size = 0;
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; ++i) {
+ // DNAME - pointer in memory
+ int item = desc->block_types[i];
+ if (descriptor_item_is_dname(item)) {
+ size += sizeof(knot_dname_t *);
+ knot_dname_t *dname =
+ knot_dname_new_from_wire(scanner->r_data +
+ scanner->r_data_blocks[i],
+ scanner->r_data_blocks[i + 1] -
+ scanner->r_data_blocks[i],
+ NULL);
+ if (dname == NULL) {
+ return KNOT_ERROR;
+ }
+
+ knot_dname_to_lower(dname);
+ dummy_node_t *n = NULL;
+ if (insert_dname_into_table(est->dname_table,
+ dname, &n) == 0) {
+ // First time we see this dname, add size
+ est->dname_size += dname_memsize(dname);
+ }
+ knot_dname_free(&dname);
+ } else if (descriptor_item_is_fixed(item)) {
+ // Fixed length
+ size += item;
+ } else {
+ // Variable length
+ size += scanner->r_data_blocks[i + 1] -
+ scanner->r_data_blocks[i];
+ }
+ }
+
+ return size * RDATA_MULT + RDATA_ADD;
+}
+
+static void rrset_memsize(zone_estim_t *est, const scanner_t *scanner)
+{
+ // Handle RRSet's owner
+ knot_dname_t *owner = knot_dname_new_from_wire(scanner->r_owner,
+ scanner->r_owner_length,
+ NULL);
+ if (owner == NULL) {
+ return;
+ }
+
+ dummy_node_t *n;
+ if (insert_dname_into_table(est->node_table, owner, &n) == 0) {
+ // First time we see this name == new node
+ est->node_size += sizeof(knot_node_t) * NODE_MULT + NODE_ADD;
+ // Also, RRSet's owner will now contain full dname
+ est->dname_size += dname_memsize(owner);
+ // Trie's nodes handled at the end of computation
+ }
+ knot_dname_free(&owner);
+ assert(n);
+
+ // We will always add RDATA
+ size_t rdlen = rdata_memsize(est, scanner);
+ if (rdlen < MALLOC_MIN) {
+ rdlen = MALLOC_MIN;
+ }
+ // DNAME's size not included (handled inside rdata_memsize())
+ est->rdata_size += rdlen;
+
+ est->record_count++;
+
+ /*
+ * RDATA size done, now add static part of RRSet to size.
+ * Do not add for RRs that would be merged.
+ * All possible duplicates will be added to total size.
+ */
+
+ if (dummy_node_add_type(n, scanner->r_type) == 0) {
+ /*
+ * New RR type, add actual RRSet struct's size:
+ * MALLOC_MIN is added because of index array - usually not many RRs
+ * are in the RRSet and values in the array are type uint32, so
+ * 3 would be needed on 32bit system and 6 on 32bit system in order to
+ * be larger than MALLOC_MIN, so we use it instead. Of course, if there
+ * are more than 3/6 records in RRSet, measurement will not be precise.
+ */
+ est->rrset_size += (sizeof(knot_rrset_t) + MALLOC_MIN)
+ * RRSET_MULT + RRSET_ADD;
+ // Add pointer in node's array
+ est->node_size += sizeof(knot_rrset_t *);
+ } else {
+ // Merge would happen, so just RDATA index is added
+ //est->rrset_size += sizeof(uint32_t);
+ }
+}
+
+void *estimator_malloc(void *ctx, size_t len)
+{
+ size_t *count = (size_t *)ctx;
+ *count += len + MALLOC_OVER;
+ return xmalloc(len);
+}
+
+void estimator_free(void *p)
+{
+ free(p);
+}
+
+static void get_ahtable_size(void *t, void *d)
+{
+ ahtable_t *table = (ahtable_t *)t;
+ size_t *size = (size_t *)d;
+ // info about allocated chunks starts at table->n-th index
+ for (size_t i = table->n; i < table->n * 2; ++i) {
+ // add actual slot size (= allocated for slot)
+ *size += table->slot_sizes[i];
+ // each non-empty slot means allocation overhead
+ *size += table->slot_sizes[i] ? MALLOC_OVER : 0;
+ }
+ *size += sizeof(ahtable_t);
+ // slot sizes + allocated sizes
+ *size += (table->n * 2) * sizeof(uint32_t);
+ // slots
+ *size += table->n * sizeof(void *);
+ *size += AHTABLE_ADD;
+}
+
+size_t estimator_trie_ahtable_memsize(hattrie_t *table)
+{
+ /*
+ * Iterate through trie's node, and get stats from each ahtable.
+ * Space taken up by the trie itself is measured using malloc wrapper.
+ * (Even for large zones, space taken by trie itself is very small)
+ */
+ size_t size = 0;
+ hattrie_apply_rev_ahtable(table, get_ahtable_size, &size);
+ return size;
+}
+
+void estimator_rrset_memsize_wrap(const scanner_t *scanner)
+{
+ rrset_memsize(scanner->data, scanner);
+}
+
+void estimator_free_trie_node(value_t *val, void *data)
+{
+ UNUSED(data);
+ dummy_node_t *trie_n = (dummy_node_t *)(*val);
+ WALK_LIST_FREE(trie_n->node_list);
+ free(trie_n);
+}
diff --git a/src/knot/zone/estimator.h b/src/knot/zone/estimator.h
new file mode 100644
index 0000000..5029b45
--- /dev/null
+++ b/src/knot/zone/estimator.h
@@ -0,0 +1,89 @@
+/* Copyright (C) 2013 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 estimator.h
+ *
+ * \author Jan Kadlec <jan.kadlec@nic.cz>
+ *
+ * \brief Memory estimation for zone files.
+ *
+ * \addtogroup config
+ * @{
+ */
+
+#ifndef _KNOT_ESTIMATOR_H_
+#define _KNOT_ESTIMATOR_H_
+
+#include "common/hattrie/hat-trie.h"
+#include "zscanner/scanner.h"
+
+// Mutiplicative constant, needed because of malloc's fragmentation
+static const double ESTIMATE_MAGIC = 1.2;
+
+/*!
+ * \brief Memory estimation context.
+ */
+typedef struct zone_estim {
+ hattrie_t *node_table; /*!< Same trie is in actual zone. */
+ hattrie_t *dname_table; /*!< RDATA section DNAMEs. */
+ size_t rdata_size; /*!< Estimated RDATA size. */
+ size_t dname_size; /*!< Estimated DNAME size. */
+ size_t node_size; /*!< Estimated node size. */
+ size_t ahtable_size; /*!< Estimated ahtable size. */
+ size_t rrset_size; /*!< Estimated RRSet size. */
+ size_t record_count; /*!< Total record count for zone. */
+} zone_estim_t;
+
+/*!
+ * \brief Size counting malloc wrapper.
+ *
+ * \param ctx Data for malloc wrapper.
+ * \param len Size to allocate.
+ *
+ * \retval Alloc'd data on succes.
+ * \retval NULL on error.
+ */
+void *estimator_malloc(void* ctx, size_t len);
+
+/*!
+ * \brief Size counting free wrapper.
+ *
+ * \param p Data to free.
+ */
+void estimator_free(void *p);
+
+/*!
+ * \brief Goes through trie's ahtables and estimates their memory requirements.
+ *
+ * \param table Trie to traverse.
+ */
+size_t estimator_trie_ahtable_memsize(hattrie_t *table);
+
+/*!
+ * \brief For use with scanner - counts memsize of RRSets.
+ *
+ * \param scanner Scanner context.
+ */
+void estimator_rrset_memsize_wrap(const scanner_t *scanner);
+
+/*!
+ * \brief Cleanup function for use with hattrie.
+ *
+ * \param p Data to free.
+ */
+void estimator_free_trie_node(value_t *val, void *data);
+
+#endif /* _KNOT_ESTIMATOR_H_ */
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index 43c1893..1d3c5c4 100644
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -1,90 +1,107 @@
+/* Copyright (C) 2011 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 <config.h>
#include <stdlib.h>
#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
-#include "knot/common.h"
-#include "knot/zone/zone-dump.h"
+#include "knot/knot.h"
#include "knot/other/debug.h"
#include "libknot/libknot.h"
+#include "libknot/sign/key.h"
#include "common/base32hex.h"
#include "common/crc.h"
+#include "common/descriptor.h"
+#include "common/mempattern.h"
#include "semantic-check.h"
-static char *error_messages[(-ZC_ERR_ALLOC) + 1] = {
- [-ZC_ERR_ALLOC] = "Memory allocation error!\n",
-
- [-ZC_ERR_MISSING_SOA] = "SOA record missing in zone!\n",
- [-ZC_ERR_MISSING_NS_DEL_POINT] = "NS record missing in zone apex!\n",
+static char *error_messages[(-ZC_ERR_UNKNOWN) + 1] = {
+ [-ZC_ERR_MISSING_SOA] = "SOA record missing in zone!",
+ [-ZC_ERR_MISSING_NS_DEL_POINT] = "NS record missing in zone apex or in "
+ "delegation point!",
[-ZC_ERR_RRSIG_RDATA_TYPE_COVERED] =
- "RRSIG: Type covered rdata field is wrong!\n",
+ "RRSIG: Type covered rdata field is wrong!",
[-ZC_ERR_RRSIG_RDATA_TTL] =
- "RRSIG: TTL rdata field is wrong!\n",
+ "RRSIG: TTL rdata field is wrong!",
[-ZC_ERR_RRSIG_RDATA_LABELS] =
- "RRSIG: Labels rdata field is wrong!\n",
+ "RRSIG: Labels rdata field is wrong!",
[-ZC_ERR_RRSIG_RDATA_DNSKEY_OWNER] =
- "RRSIG: Signer name is different than in DNSKEY!\n",
+ "RRSIG: Signer name is different than in DNSKEY!",
[-ZC_ERR_RRSIG_RDATA_SIGNED_WRONG] =
- "RRSIG: Key error!\n",
+ "RRSIG: Key error!",
[-ZC_ERR_RRSIG_NO_RRSIG] =
- "RRSIG: No RRSIG!\n",
+ "RRSIG: No RRSIG!",
[-ZC_ERR_RRSIG_SIGNED] =
- "RRSIG: Signed RRSIG!\n",
+ "RRSIG: Signed RRSIG!",
[-ZC_ERR_RRSIG_OWNER] =
- "RRSIG: Owner name rdata field is wrong!\n",
+ "RRSIG: Owner name rdata field is wrong!",
[-ZC_ERR_RRSIG_CLASS] =
- "RRSIG: Class is wrong!\n",
+ "RRSIG: Class is wrong!",
[-ZC_ERR_RRSIG_TTL] =
- "RRSIG: TTL is wrong!\n",
+ "RRSIG: TTL is wrong!",
[-ZC_ERR_RRSIG_NOT_ALL] =
- "RRSIG: Not all RRs are signed!\n",
+ "RRSIG: Not all RRs are signed!",
[-ZC_ERR_NO_NSEC] =
- "NSEC: Missing NSEC record\n",
+ "NSEC: Missing NSEC record",
[-ZC_ERR_NSEC_RDATA_BITMAP] =
- "NSEC: Wrong NSEC bitmap!\n",
+ "NSEC: Wrong NSEC bitmap!",
[-ZC_ERR_NSEC_RDATA_MULTIPLE] =
- "NSEC: Multiple NSEC records!\n",
+ "NSEC: Multiple NSEC records!",
[-ZC_ERR_NSEC_RDATA_CHAIN] =
- "NSEC: NSEC chain is not coherent!\n",
+ "NSEC: NSEC chain is not coherent!",
[-ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC] =
- "NSEC: NSEC chain is not cyclic!\n",
+ "NSEC: NSEC chain is not cyclic!",
[-ZC_ERR_NSEC3_UNSECURED_DELEGATION] =
- "NSEC3: Zone contains unsecured delegation!\n",
+ "NSEC3: Zone contains unsecured delegation!",
[-ZC_ERR_NSEC3_NOT_FOUND] =
- "NSEC3: Could not find previous NSEC3 record in the zone!\n",
+ "NSEC3: Could not find previous NSEC3 record in the zone!",
[-ZC_ERR_NSEC3_UNSECURED_DELEGATION_OPT] =
"NSEC3: Unsecured delegation is not part "
- "of the Opt-Out span!\n",
+ "of the Opt-Out span!",
[-ZC_ERR_NSEC3_RDATA_TTL] =
- "NSEC3: Original TTL rdata field is wrong!\n",
+ "NSEC3: Original TTL rdata field is wrong!",
[-ZC_ERR_NSEC3_RDATA_CHAIN] =
- "NSEC3: NSEC3 chain is not coherent!\n",
+ "NSEC3: NSEC3 chain is not coherent!",
[-ZC_ERR_NSEC3_RDATA_BITMAP] =
- "NSEC3: NSEC3 bitmap error!\n",
+ "NSEC3: NSEC3 bitmap error!",
[-ZC_ERR_NSEC3_EXTRA_RECORD] =
"NSEC3: NSEC3 node contains extra record. This is valid, however Knot "
- "will not serve this record properly.\n",
+ "will not serve this record properly.",
- [-ZC_ERR_CNAME_CYCLE] =
- "CNAME: CNAME cycle!\n",
- [-ZC_ERR_DNAME_CYCLE] =
- "CNAME: DNAME cycle!\n",
[-ZC_ERR_CNAME_EXTRA_RECORDS] =
- "CNAME: Node with CNAME record has other records!\n",
+ "CNAME: Node with CNAME record has other records!",
[-ZC_ERR_DNAME_CHILDREN] =
- "DNAME: Node with DNAME record has children!\n",
+ "DNAME: Node with DNAME record has children!",
[-ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC] =
"CNAME: Node with CNAME record has other "
- "records than RRSIG and NSEC/NSEC3!\n",
- [-ZC_ERR_CNAME_MULTIPLE] = "CNAME: Multiple CNAME records!\n",
- [-ZC_ERR_DNAME_MULTIPLE] = "DNAME: Multiple DNAME records!\n",
+ "records than RRSIG and NSEC/NSEC3!",
+ [-ZC_ERR_CNAME_MULTIPLE] = "CNAME: Multiple CNAME records!",
+ [-ZC_ERR_DNAME_MULTIPLE] = "DNAME: Multiple DNAME records!",
[-ZC_ERR_CNAME_WILDCARD_SELF] = "CNAME wildcard "
- "pointing to itself!\n",
+ "pointing to itself!",
[-ZC_ERR_DNAME_WILDCARD_SELF] = "DNAME wildcard "
- "pointing to itself!\n",
+ "pointing to itself!",
/* ^
| Important errors (to be logged on first occurence and counted) */
@@ -94,22 +111,19 @@ static char *error_messages[(-ZC_ERR_ALLOC) + 1] = {
specified otherwise */
[-ZC_ERR_GLUE_NODE] =
- "GLUE: Node with glue record missing!\n",
+ "GLUE: Node with glue record missing!",
[-ZC_ERR_GLUE_RECORD] =
- "GLUE: Record with glue address missing\n",
+ "GLUE: Record with glue address missing!",
};
static const uint MAX_CNAME_CYCLE_DEPTH = 15;
-err_handler_t *handler_new(char log_cname, char log_glue,
- char log_rrsigs, char log_nsec,
- char log_nsec3)
+err_handler_t *handler_new(int log_cname, int log_glue, int log_rrsigs,
+ int log_nsec, int log_nsec3)
{
- err_handler_t *handler = malloc(sizeof(err_handler_t));
- CHECK_ALLOC_LOG(handler, NULL);
+ err_handler_t *handler = xmalloc(sizeof(err_handler_t));
- /* It should be initialized, but to be safe */
- memset(handler->errors, 0, sizeof(uint) * (-ZC_ERR_ALLOC + 1));
+ memset(handler->errors, 0, sizeof(uint) * (-ZC_ERR_UNKNOWN + 1));
handler->error_count = 0;
handler->options.log_cname = log_cname;
@@ -132,34 +146,46 @@ err_handler_t *handler_new(char log_cname, char log_glue,
*/
static void log_error_from_node(err_handler_t *handler,
const knot_node_t *node,
- int error)
+ int error, const char *data)
{
if (error > (int)ZC_ERR_GLUE_RECORD) {
- fprintf(stderr, "Unknown error.\n");
+ log_zone_warning("Unknown error.\n");
return;
}
+ char buffer[1024] = {0};
+ size_t offset = 0;
+
if (node != NULL) {
handler->error_count++;
char *name =
knot_dname_to_str(knot_node_owner(node));
- fprintf(stderr, "Semantic warning in node: %s: ", name);
+ offset += snprintf(buffer, 1024,
+ "Semantic warning in node: %s: ", name);
if (error_messages[-error] != NULL) {
- fprintf(stderr, "%s", error_messages[-error]);
+ offset += snprintf(buffer + offset, 1024 - offset,
+ "%s", error_messages[-error]);
+ if (data == NULL) {
+ offset += snprintf(buffer + offset,
+ 1024 - offset, "\n");
+ } else {
+ offset += snprintf(buffer + offset,
+ 1024 - offset, " %s\n", data);
+ }
+ log_zone_warning("%s", buffer);
} else {
- fprintf(stderr, "Unknown error (%d).\n", error);
+ log_zone_warning("Unknown error (%d).\n", error);
}
free(name);
} else {
- fprintf(stderr, "Total number of warnings is: %d for error: %s",
+ log_zone_warning("Total number of warnings is: %d for error: %s",
handler->errors[-error],
error_messages[-error]);
}
}
-int err_handler_handle_error(err_handler_t *handler,
- const knot_node_t *node,
- int error)
+int err_handler_handle_error(err_handler_t *handler, const knot_node_t *node,
+ int error, const char *data)
{
assert(handler && node);
if ((error != 0) &&
@@ -167,53 +193,39 @@ int err_handler_handle_error(err_handler_t *handler,
return KNOT_EINVAL;
}
- /*!< \todo #1886 this is so wrong! Should not even return anything. */
- if (error == ZC_ERR_ALLOC || error == 0) {
- return KNOT_EINVAL;
- }
-
- /* missing SOA can only occur once, so there
- * needn't to be an option for it */
+ /*
+ * A missing SOA can only occur once, so there needn't be
+ * an option for it.
+ */
if ((error != 0) &&
(error < ZC_ERR_GENERIC_GENERAL_ERROR)) {
/* The two errors before SOA were handled */
- log_error_from_node(handler, node, error);
+ log_error_from_node(handler, node, error, data);
return KNOT_EOK;
-
} else if ((error < ZC_ERR_RRSIG_GENERAL_ERROR) &&
((handler->errors[-error] == 0) ||
(handler->options.log_rrsigs))) {
-
- log_error_from_node(handler, node, error);
-
+ log_error_from_node(handler, node, error, data);
} else if ((error > ZC_ERR_RRSIG_GENERAL_ERROR) &&
(error < ZC_ERR_NSEC_GENERAL_ERROR) &&
((handler->errors[-error] == 0) ||
(handler->options.log_nsec))) {
-
- log_error_from_node(handler, node, error);
-
+ log_error_from_node(handler, node, error, data);
} else if ((error > ZC_ERR_NSEC_GENERAL_ERROR) &&
(error < ZC_ERR_NSEC3_GENERAL_ERROR) &&
((handler->errors[-error] == 0) ||
(handler->options.log_nsec3))) {
-
- log_error_from_node(handler, node, error);
-
+ log_error_from_node(handler, node, error, data);
} else if ((error > ZC_ERR_NSEC3_GENERAL_ERROR) &&
(error < ZC_ERR_CNAME_GENERAL_ERROR) &&
((handler->errors[-error] == 0) ||
(handler->options.log_cname))) {
-
- log_error_from_node(handler, node, error);
-
+ log_error_from_node(handler, node, error, data);
} else if ((error > ZC_ERR_CNAME_GENERAL_ERROR) &&
(error < ZC_ERR_GLUE_GENERAL_ERROR) &&
handler->options.log_glue) {
-
- log_error_from_node(handler, node, error);
-
+ log_error_from_node(handler, node, error, data);
}
handler->errors[-error]++;
@@ -227,245 +239,13 @@ void err_handler_log_all(err_handler_t *handler)
return;
}
- for (int i = ZC_ERR_ALLOC; i < ZC_ERR_GLUE_GENERAL_ERROR; i++) {
+ for (int i = ZC_ERR_UNKNOWN; i < ZC_ERR_GLUE_GENERAL_ERROR; i++) {
if (handler->errors[-i] > 0) {
- log_error_from_node(handler, NULL, i);
+ log_error_from_node(handler, NULL, i, NULL);
}
}
}
-
-/*!
- * \brief Semantic check - CNAME cycles. Uses constant value with maximum
- * allowed CNAME chain depth.
- *
- * \param zone Zone containing the RRSet.
- * \param rrset RRSet to be tested.
- *
- * \retval KNOT_EOK when there is no cycle.
- * \retval ZC_ERR_CNAME_CYCLE when cycle is present.
- */
-static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
- const knot_rrset_t *rrset,
- char *fatal_error)
-{
- if (rrset->type != KNOT_RRTYPE_CNAME &&
- rrset->type != KNOT_RRTYPE_DNAME) {
- return KNOT_EINVAL;
- }
-
- const knot_rrset_t *next_rrset = rrset;
- assert(rrset);
- const knot_rdata_t *tmp_rdata = knot_rrset_rdata(next_rrset);
- const knot_node_t *next_node = NULL;
-
- uint i = 0;
-
- if (tmp_rdata == NULL) {
- return KNOT_EOK;
- }
-
- const knot_dname_t *next_dname =
- knot_rdata_cname_name(tmp_rdata);
- /* (cname_name == dname_target) */
-
- assert(next_dname);
-
- /* Check wildcard pointing to itself. */
- if (knot_dname_is_wildcard(knot_rrset_owner(rrset))) {
- /* We need to chop the wildcard. */
-
- knot_dname_t *chopped_wc =
- knot_dname_left_chop(knot_rrset_owner(rrset));
- if (!chopped_wc) {
- /* Definitely not a cycle. */
- return KNOT_EOK;
- }
-
- /*
- * And check that no sub-dname up to zone apex is present
- * in its rdata.
- */
-
- knot_dname_t *next_dname_copy =
- knot_dname_deep_copy(next_dname);
- if (!next_dname_copy) {
- knot_dname_free(&chopped_wc);
- return KNOT_ERROR;
- }
-
- const knot_dname_t *zone_origin =
- knot_node_owner(knot_zone_contents_apex(zone));
- if (!zone_origin) {
- knot_dname_free(&chopped_wc);
- knot_dname_free(&next_dname_copy);
- return KNOT_ERROR;
- }
-
- char error_found = 0;
- char cut_offs = 1;
-
- while (knot_dname_compare(next_dname_copy,
- zone_origin) != 0 &&
- !error_found) {
- /* Compare chopped owner with current next dname. */
- error_found =
- knot_dname_compare(next_dname_copy,
- chopped_wc) == 0;
- if (error_found && cut_offs == 1) {
- /* WC without * == link. */
- knot_dname_free(&next_dname_copy);
- knot_dname_free(&chopped_wc);
- return KNOT_EOK;
- }
-
- knot_dname_t *tmp_chopped =
- knot_dname_left_chop(next_dname_copy);
- if (!tmp_chopped &&
- !(knot_dname_is_fqdn(next_dname_copy) &&
- knot_dname_label_count(next_dname_copy) == 0)) {
- knot_dname_free(&chopped_wc);
- knot_dname_free(&next_dname_copy);
- return KNOT_ERROR;
- } else if ((knot_dname_is_fqdn(next_dname_copy) &&
- knot_dname_label_count(next_dname_copy) == 0)) {
- knot_dname_free(&next_dname_copy);
- knot_dname_free(&tmp_chopped);
- /* Root domain, end of search. */
- break;
- }
- knot_dname_free(&next_dname_copy);
-
- cut_offs++;
-
- next_dname_copy = tmp_chopped;
- }
-
- if (error_found) {
- knot_dname_free(&next_dname_copy);
- knot_dname_free(&chopped_wc);
- assert(cut_offs > 1);
- *fatal_error = 1;
- return ZC_ERR_CNAME_WILDCARD_SELF;
- }
-
- knot_dname_free(&next_dname_copy);
- knot_dname_free(&chopped_wc);
-
- /*
- * Test for transitive wildcard loops.
- * Basically the same as below, only we look for wildcards and
- * strip them in the same fashion as above.
- */
-
- }
-
- while (i < MAX_CNAME_CYCLE_DEPTH && next_dname != NULL) {
- next_node = knot_zone_contents_get_node(zone, next_dname);
- if (next_node == NULL) {
- next_node =
- knot_zone_contents_get_nsec3_node(zone,
- next_dname);
- }
-
-/*!< \todo #1887 this might replace some of the code above. */
-// /* Still NULL, try wildcards. */
-// if (next_node == NULL && knot_dname_is_wildcard(next_dname)) {
-// /* We can only use the wildcard so many times. */
-
-// /* Create chopped copy of wc. */
-// knot_dname_t *chopped_wc =
-// knot_dname_left_chop(next_dname);
-// if (chopped_wc == NULL) {
-// /* If name with this wc is in the zone,
-// we have a problem (eg. cycle continues). */
-// next_node =
-// knot_zone_contents_get_node(zone,
-// chopped_wc);
-// /* (No need to consider NSEC3 nodes.) */
-// knot_dname_free(&chopped_wc);
-// }
-// }
-
- /* Just a guess. */
- knot_dname_t *chopped_next =
- knot_dname_left_chop(next_dname);
- if (chopped_next == NULL) {
- return KNOT_ERROR;
- }
- while (next_node == NULL && chopped_next != NULL) {
- /* Cat '*' .*/
- knot_dname_t *wc =
- knot_dname_new_from_str("*", strlen("*"),
- NULL);
- if (wc == NULL) {
- knot_dname_free(&chopped_next);
- return KNOT_ENOMEM;
- }
-
- if (knot_dname_cat(wc, chopped_next) == NULL) {
- knot_dname_free(&chopped_next);
- knot_dname_free(&wc);
- return KNOT_ERROR;
- }
-
- next_node =
- knot_zone_contents_get_node(zone, wc);
- knot_dname_free(&wc);
- knot_dname_t *tmp = chopped_next;
- chopped_next = knot_dname_left_chop(chopped_next);
- knot_dname_free(&tmp);
- }
-
- knot_dname_free(&chopped_next);
-
- if (next_node != NULL) {
- next_rrset = knot_node_rrset(next_node,
- rrset->type);
- if (next_rrset != NULL && next_rrset->rdata != NULL) {
- next_dname =
- knot_rdata_cname_name(next_rrset->rdata);
- } else {
- next_node = NULL;
- next_dname = NULL;
- }
- } else {
- next_dname = NULL;
- }
- i++;
- }
-
- /* even if the length is 0, i will be 1 */
- if (i >= MAX_CNAME_CYCLE_DEPTH) {
- *fatal_error = 1;
- return ZC_ERR_CNAME_CYCLE;
- }
-
- return KNOT_EOK;
-}
-
-/*!
- * \brief Return raw data from rdata item structure (without length).
- *
- * \param item Item to get rdata from.
- * \return uint16_t * raw data without length.
- */
-static inline uint16_t *rdata_item_data(const knot_rdata_item_t *item)
-{
- return (uint16_t *)(item->raw_data + 1);
-}
-
-/*!
- * \brief Returns type covered field from RRSIG RRSet's rdata.
- *
- * \param rdata RRSIG rdata.
- * \return uint16_t Type covered.
- */
-uint16_t type_covered_from_rdata(const knot_rdata_t *rdata)
-{
- return ntohs(*(uint16_t *) rdata_item_data(&(rdata->items[0])));
-}
-
/*!
* \brief Check whether DNSKEY rdata are valid.
*
@@ -474,14 +254,13 @@ uint16_t type_covered_from_rdata(const knot_rdata_t *rdata)
* \retval KNOT_EOK when rdata are OK.
* \retval ZC_ERR_RRSIG_RDATA_DNSKEY_OWNER when rdata are not OK.
*/
-static int check_dnskey_rdata(const knot_rdata_t *rdata)
+static int check_dnskey_rdata(const knot_rrset_t *rrset, size_t rdata_pos)
{
/* check that Zone key bit it set - position 7 in net order */
- uint16_t mask = 1 << 8; //0b0000000100000000;
+ const uint16_t mask = 1 << 8; //0b0000000100000000;
uint16_t flags =
- knot_wire_read_u16((uint8_t *)rdata_item_data
- (knot_rdata_item(rdata, 0)));
+ knot_wire_read_u16(knot_rrset_get_rdata(rrset, rdata_pos));
if (flags & mask) {
return KNOT_EOK;
@@ -493,102 +272,6 @@ static int check_dnskey_rdata(const knot_rdata_t *rdata)
}
/*!
- * \brief Calculates keytag for RSA/SHA algorithm.
- *
- * \param key Key wireformat.
- * \param keysize Wireformat size.
- *
- * \return uint16_t Calculated keytag.
- */
-static uint16_t keytag_1(uint8_t *key, uint16_t keysize)
-{
- uint16_t ac = 0;
- if (keysize > 4) {
- memmove(&ac, key + keysize - 3, 2);
- }
-
- ac = ntohs(ac);
- return ac;
-}
-
-/*!
- * \brief Calculates keytag from key wire.
- *
- * \param key Key wireformat.
- * \param keysize Wireformat size.
- *
- * \return uint16_t Calculated keytag.
- */
-static uint16_t keytag(uint8_t *key, uint16_t keysize )
-{
- uint32_t ac = 0; /* assumed to be 32 bits or larger */
-
- /* algorithm RSA/SHA */
- if (key[3] == 1) {
- return keytag_1(key, keysize);
- } else {
- for(int i = 0; i < keysize; i++) {
- ac += (i & 1) ? key[i] : key[i] << 8;
- }
-
- ac += (ac >> 16) & 0xFFFF;
- return (uint16_t)ac & 0xFFFF;
- }
-}
-
-/*!
- * \brief Returns size of raw data item.
- *
- * \param item Raw data item.
- *
- * \return uint16_t Size of raw data item.
- */
-static inline uint16_t rdata_item_size(const knot_rdata_item_t *item)
-{
- return item->raw_data[0];
-}
-
-/*!
- * \brief Converts DNSKEY rdata to wireformat.
- *
- * \param rdata DNSKEY rdata to be converted.
- * \param wire Created wire.
- * \param size Size of created wire.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_ENOMEM on memory error.
- */
-static int dnskey_to_wire(const knot_rdata_t *rdata, uint8_t **wire,
- uint *size)
-{
- assert(*wire == NULL);
- /* flags + algorithm + protocol + keysize */
- *size = 2 + 1 + 1 + knot_rdata_item(rdata, 3)->raw_data[0];
- *wire = malloc(sizeof(uint8_t) * *size);
- CHECK_ALLOC_LOG(*wire, KNOT_ENOMEM);
-
- /* copy the wire octet by octet */
-
- if (rdata->count < 4) {
- free(*wire);
- *wire = NULL;
- *size = 0;
- return KNOT_ERROR;
- }
-
- (*wire)[0] = ((uint8_t *)(knot_rdata_item(rdata, 0)->raw_data))[2];
- (*wire)[1] = ((uint8_t *)(knot_rdata_item(rdata, 0)->raw_data))[3];
-
- (*wire)[2] = ((uint8_t *)(knot_rdata_item(rdata, 1)->raw_data))[2];
- (*wire)[3] = ((uint8_t *)(knot_rdata_item(rdata, 2)->raw_data))[2];
-
- memcpy(*wire + 4, knot_rdata_item(rdata, 3)->raw_data + 1,
- knot_rdata_item(rdata, 3)->raw_data[0]);
-
- return KNOT_EOK;
-}
-
-/*!
* \brief Semantic check - RRSIG rdata.
*
* \param rdata_rrsig RRSIG rdata to be checked.
@@ -599,27 +282,31 @@ static int dnskey_to_wire(const knot_rdata_t *rdata, uint8_t **wire,
*
* \return Appropriate error code if error was found.
*/
-static int check_rrsig_rdata(const knot_rdata_t *rdata_rrsig,
- const knot_rrset_t *rrset,
- const knot_rrset_t *dnskey_rrset)
+static int check_rrsig_rdata(err_handler_t *handler,
+ const knot_node_t *node,
+ const knot_rrset_t *rrsig,
+ size_t rr_pos,
+ const knot_rrset_t *rrset,
+ const knot_rrset_t *dnskey_rrset)
{
- if (rdata_rrsig == NULL) {
- return ZC_ERR_RRSIG_NO_RRSIG;
+ if (knot_rrset_rdata_rr_count(rrsig) == 0) {
+ err_handler_handle_error(handler, node, ZC_ERR_RRSIG_NO_RRSIG,
+ NULL);
+ return KNOT_EOK;
}
- if (type_covered_from_rdata(rdata_rrsig) !=
+ if (knot_rrset_rdata_rrsig_type_covered(rrsig) !=
knot_rrset_type(rrset)) {
/* zoneparser would not let this happen
* but to be on the safe side
*/
- return ZC_ERR_RRSIG_RDATA_TYPE_COVERED;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_RDATA_TYPE_COVERED,
+ NULL);
}
/* label number at the 2nd index should be same as owner's */
- uint16_t *raw_data =
- rdata_item_data(knot_rdata_item(rdata_rrsig, 2));
-
- uint8_t labels_rdata = ((uint8_t *)raw_data)[0];
+ uint8_t labels_rdata = knot_rrset_rdata_rrsig_labels(rrsig, rr_pos);
int tmp = knot_dname_label_count(knot_rrset_owner(rrset)) -
labels_rdata;
@@ -627,83 +314,83 @@ static int check_rrsig_rdata(const knot_rdata_t *rdata_rrsig,
if (tmp != 0) {
/* if name has wildcard, label must not be included */
if (!knot_dname_is_wildcard(knot_rrset_owner(rrset))) {
- return ZC_ERR_RRSIG_RDATA_LABELS;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_RDATA_LABELS,
+ NULL);
} else {
if (abs(tmp) != 1) {
- return ZC_ERR_RRSIG_RDATA_LABELS;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_RDATA_LABELS,
+ NULL);
}
}
}
/* check original TTL */
uint32_t original_ttl =
- knot_wire_read_u32((uint8_t *)rdata_item_data(
- knot_rdata_item(rdata_rrsig, 3)));
+ knot_rrset_rdata_rrsig_original_ttl(rrsig, rr_pos);
if (original_ttl != knot_rrset_ttl(rrset)) {
- return ZC_ERR_RRSIG_RDATA_TTL;
+ err_handler_handle_error(handler, node, ZC_ERR_RRSIG_RDATA_TTL,
+ NULL);
}
/* signer's name is same as in the zone apex */
- knot_dname_t *signer_name =
- knot_rdata_item(rdata_rrsig, 7)->dname;
+ const knot_dname_t *signer_name =
+ knot_rrset_rdata_rrsig_signer_name(rrsig, rr_pos);
/* dnskey is in the apex node */
if (knot_dname_compare(signer_name,
knot_rrset_owner(dnskey_rrset)) != 0) {
- return ZC_ERR_RRSIG_RDATA_DNSKEY_OWNER;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_RDATA_DNSKEY_OWNER,
+ NULL);
}
/* Compare algorithm, key tag and signer's name with DNSKEY rrset
* one of the records has to match. Signer name has been checked
* before */
- char match = 0;
- const knot_rdata_t *tmp_dnskey_rdata =
- knot_rrset_rdata(dnskey_rrset);
- do {
- uint8_t alg =
- ((uint8_t *)(knot_rdata_item(rdata_rrsig, 1)->raw_data))[2];
- uint8_t alg_dnskey =
- ((uint8_t *)(knot_rdata_item(tmp_dnskey_rdata,
- 2)->raw_data))[2];
-
- raw_data = rdata_item_data(knot_rdata_item(rdata_rrsig, 6));
- uint16_t key_tag_rrsig =
- knot_wire_read_u16((uint8_t *)raw_data);
-
-/* raw_data =
- rdata_item_data(knot_rdata_item(
- tmp_dnskey_rdata, 3));
-
- uint16_t raw_length = rdata_item_size(knot_rdata_item(
- tmp_dnskey_rdata, 3)); */
-
- uint8_t *dnskey_wire = NULL;
- uint dnskey_wire_size = 0;
-
- int ret = 0;
- if ((ret = dnskey_to_wire(tmp_dnskey_rdata, &dnskey_wire,
- &dnskey_wire_size)) != KNOT_EOK) {
- return ret;
+
+ int match = 0;
+ uint8_t rrsig_alg = knot_rrset_rdata_rrsig_algorithm(rrsig, rr_pos);
+ uint16_t key_tag_rrsig = knot_rrset_rdata_rrsig_key_tag(rrsig, rr_pos);
+ for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(dnskey_rrset) &&
+ !match; ++i) {
+ uint8_t dnskey_alg =
+ knot_rrset_rdata_dnskey_alg(dnskey_rrset, i);
+ if (rrsig_alg != dnskey_alg) {
+ continue;
}
-
- uint16_t key_tag_dnskey =
- keytag(dnskey_wire, dnskey_wire_size);
-
- free(dnskey_wire);
-
- match = (alg == alg_dnskey) &&
- (key_tag_rrsig == key_tag_dnskey) &&
- !check_dnskey_rdata(tmp_dnskey_rdata);
-
- } while (!match &&
- ((tmp_dnskey_rdata =
- knot_rrset_rdata_next(dnskey_rrset,
- tmp_dnskey_rdata))
- != NULL));
-
+
+ /* Calculate keytag. */
+ uint16_t dnskey_key_tag =
+ knot_keytag(knot_rrset_get_rdata(dnskey_rrset, i),
+ rrset_rdata_item_size(dnskey_rrset, i));
+ if (key_tag_rrsig != dnskey_key_tag) {
+ continue;
+ }
+
+ /* Final step - check DNSKEY validity. */
+ if (check_dnskey_rdata(dnskey_rrset, i) == KNOT_EOK) {
+ match = 1;
+ } else {
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_RDATA_SIGNED_WRONG,
+ "DNSKEY RDATA not matching");
+ }
+ }
+
if (!match) {
- return ZC_ERR_RRSIG_RDATA_SIGNED_WRONG;
+ /* Prepare additional info string. */
+ char info_str[50];
+ int ret = snprintf(info_str, sizeof(info_str),
+ "Record type: %d.",
+ knot_rrset_type(rrset));
+ if (ret < 0 || ret >= sizeof(info_str)) {
+ return KNOT_ENOMEM;
+ }
+ err_handler_handle_error(handler, node, ZC_ERR_RRSIG_NO_RRSIG,
+ info_str);
}
return KNOT_EOK;
@@ -720,68 +407,85 @@ static int check_rrsig_rdata(const knot_rdata_t *rdata_rrsig,
*
* \return Appropriate error code if error was found.
*/
-static int check_rrsig_in_rrset(const knot_rrset_t *rrset,
- const knot_rrset_t *dnskey_rrset,
- char nsec3)
+static int check_rrsig_in_rrset(err_handler_t *handler,
+ const knot_node_t *node,
+ const knot_rrset_t *rrset,
+ const knot_rrset_t *dnskey_rrset,
+ char nsec3)
{
+ if (handler == NULL || node == NULL || rrset == NULL ||
+ dnskey_rrset == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ /* Prepare additional info string. */
+ char info_str[50];
+ int ret = snprintf(info_str, sizeof(info_str), "Record type: %d.",
+ knot_rrset_type(rrset));
+ if (ret < 0 || ret >= sizeof(info_str)) {
+ return KNOT_ENOMEM;
+ }
+
assert(dnskey_rrset && rrset);
const knot_rrset_t *rrsigs = knot_rrset_rrsigs(rrset);
if (rrsigs == NULL) {
- return ZC_ERR_RRSIG_NO_RRSIG;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_NO_RRSIG,
+ info_str);
+ return KNOT_EOK;
}
/* signed rrsig - nonsense */
if (knot_rrset_rrsigs(rrsigs) != NULL) {
- return ZC_ERR_RRSIG_SIGNED;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_SIGNED,
+ info_str);
+ /* Safe to continue, nothing is malformed. */
}
/* Different owner, class, ttl */
if (knot_dname_compare(knot_rrset_owner(rrset),
knot_rrset_owner(rrsigs)) != 0) {
- return ZC_ERR_RRSIG_OWNER;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_OWNER,
+ info_str);
}
if (knot_rrset_class(rrset) != knot_rrset_class(rrsigs)) {
- return ZC_ERR_RRSIG_CLASS;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_CLASS,
+ info_str);
}
if (knot_rrset_ttl(rrset) != knot_rrset_ttl(rrset)) {
- return ZC_ERR_RRSIG_TTL;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_TTL,
+ info_str);
}
- const knot_rdata_t *tmp_rdata = knot_rrset_rdata(rrset);
- const knot_rdata_t *tmp_rrsig_rdata = knot_rrset_rdata(rrsigs);
-
- assert(tmp_rrsig_rdata != NULL);
- if (tmp_rdata == NULL) {
- /* Only RRSIG, valid, but we can't check anything. */
+ if (knot_rrset_rdata_rr_count(rrsigs) == 0) {
+ /* Nothing to check, and should not happen. */
return KNOT_EOK;
}
- int ret = 0;
- do {
- if ((ret = check_rrsig_rdata(tmp_rrsig_rdata,
- rrset,
- dnskey_rrset)) != 0) {
- /*!< \todo This should go to handler. */
- return ret;
+ for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rrsigs); ++i) {
+ int ret = check_rrsig_rdata(handler, node, rrsigs, i, rrset,
+ dnskey_rrset);
+ if (ret != KNOT_EOK) {
+ dbg_semcheck("Could not check RRSIG properly (%s).\n",
+ knot_strerror(ret));
}
- tmp_rdata = knot_rrset_rdata_next(rrset, tmp_rdata);
- tmp_rrsig_rdata = knot_rrset_rdata_next(rrsigs,
- tmp_rrsig_rdata);
- } while (tmp_rdata != NULL && tmp_rrsig_rdata != NULL);
+ }
- /*!< \todo JK 03-08-2012 #1972
- * This check is not very informative, its output
- * does not contain any info about which RRSet is not completely signed.
- * A rewrite is needed.
- */
- char all_signed = tmp_rdata == NULL && tmp_rrsig_rdata == NULL;
+ int all_signed =
+ knot_rrset_rdata_rr_count(rrset) == knot_rrset_rdata_rr_count(rrsigs);
if (!all_signed) {
- return ZC_ERR_RRSIG_NOT_ALL;
+ err_handler_handle_error(handler, node,
+ ZC_ERR_RRSIG_NOT_ALL,
+ info_str);
}
return KNOT_EOK;
@@ -814,18 +518,26 @@ static int get_bit(uint8_t *bits, size_t index)
* \retval KNOT_OK on success.
* \retval KNOT_NOMEM on memory error.
*/
-static int rdata_nsec_to_type_array(const knot_rdata_item_t *item,
- uint16_t **array,
- uint *count)
+static int rdata_nsec_to_type_array(const knot_rrset_t *rrset, size_t pos,
+ uint16_t **array, size_t *count)
{
assert(*array == NULL);
-
- uint8_t *data = (uint8_t *)rdata_item_data(item);
-
- int increment = 0;
+ assert(rrset->type == KNOT_RRTYPE_NSEC || rrset->type == KNOT_RRTYPE_NSEC3);
+
+ uint8_t *data = NULL;
+ uint16_t rr_bitmap_size = 0;
+ if (rrset->type == KNOT_RRTYPE_NSEC) {
+ knot_rrset_rdata_nsec_bitmap(rrset, pos, &data, &rr_bitmap_size);
+ } else {
+ knot_rrset_rdata_nsec3_bitmap(rrset, pos, &data, &rr_bitmap_size);
+ }
+ if (data == NULL) {
+ return KNOT_EMALF;
+ }
+
*count = 0;
-
- for (int i = 0; i < rdata_item_size(item); i += increment) {
+ int increment = 0;
+ for (int i = 0; i < rr_bitmap_size; i += increment) {
increment = 0;
uint8_t window = data[i];
increment++;
@@ -881,8 +593,8 @@ static int rdata_nsec_to_type_array(const knot_rdata_item_t *item,
*
* \return Appropriate error code if error was found.
*/
-static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *node,
- err_handler_t *handler)
+static int check_nsec3_node_in_zone(knot_zone_contents_t *zone,
+ knot_node_t *node, err_handler_t *handler)
{
assert(handler);
const knot_node_t *nsec3_node = knot_node_nsec3_node(node);
@@ -892,19 +604,21 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
* do for now. */
if (knot_node_rrset(node, KNOT_RRTYPE_DS) != NULL) {
err_handler_handle_error(handler, node,
- ZC_ERR_NSEC3_UNSECURED_DELEGATION);
+ ZC_ERR_NSEC3_UNSECURED_DELEGATION,
+ NULL);
} else {
/* Unsecured delegation, check whether it is part of
* opt-out span */
- const knot_node_t *nsec3_previous = NULL;
- const knot_node_t *nsec3_node = NULL;
+ const knot_node_t *nsec3_previous;
+ const knot_node_t *nsec3_node;
if (knot_zone_contents_find_nsec3_for_name(zone,
knot_node_owner(node),
&nsec3_node,
&nsec3_previous) != 0) {
err_handler_handle_error(handler, node,
- ZC_ERR_NSEC3_NOT_FOUND);
+ ZC_ERR_NSEC3_NOT_FOUND, NULL);
+ return KNOT_EOK;
}
if (nsec3_node == NULL) {
@@ -916,19 +630,19 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
const knot_rrset_t *previous_rrset =
knot_node_rrset(nsec3_previous,
- KNOT_RRTYPE_NSEC3);
+ KNOT_RRTYPE_NSEC3);
assert(previous_rrset);
/* check for Opt-Out flag */
uint8_t flags =
- ((uint8_t *)(previous_rrset->rdata->items[1].raw_data))[2];
-
+ knot_rrset_rdata_nsec3_flags(previous_rrset, 0);
uint8_t opt_out_mask = 1;
if (!(flags & opt_out_mask)) {
err_handler_handle_error(handler, node,
- ZC_ERR_NSEC3_UNSECURED_DELEGATION_OPT);
+ ZC_ERR_NSEC3_UNSECURED_DELEGATION_OPT,
+ NULL);
}
}
}
@@ -942,44 +656,28 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
knot_node_rrset(knot_zone_contents_apex(zone),
KNOT_RRTYPE_SOA);
assert(soa_rrset);
-
- const knot_rdata_t *soa_rdata = knot_rrset_rdata(soa_rrset);
- if (soa_rdata == NULL) {
- err_handler_handle_error(handler, node, ZC_ERR_UNKNOWN);
- return KNOT_EOK;
- }
-
- uint32_t minimum_ttl = knot_rdata_soa_minimum(soa_rdata);
+ uint32_t minimum_ttl = knot_rrset_rdata_soa_minimum(soa_rrset);
if (knot_rrset_ttl(nsec3_rrset) != minimum_ttl) {
err_handler_handle_error(handler, node,
- ZC_ERR_NSEC3_RDATA_TTL);
+ ZC_ERR_NSEC3_RDATA_TTL, NULL);
}
/* check that next dname is in the zone */
+ uint8_t *next_dname_str = NULL;
+ uint8_t next_dname_size = 0;
uint8_t *next_dname_decoded = NULL;
- size_t real_size = 0;
- int32_t b32_ret;
-
- /* Make sure RRSet has enough data. */
- if (!knot_rrset_rdata(nsec3_rrset) ||
- knot_rdata_item_count(knot_rrset_rdata(nsec3_rrset)) <= 5) {
- /* Not enough data to do complete check -> incomplete chain. */
- err_handler_handle_error(handler, node, ZC_ERR_NSEC3_NOT_FOUND);
- return KNOT_EOK;
- }
-
- if (((b32_ret = base32hex_encode_alloc((uint8_t *)
- (rdata_item_data(&(nsec3_rrset->rdata->items[4]))) + 1,
- rdata_item_size(&nsec3_rrset->rdata->items[4]) - 1,
- &next_dname_decoded)) <= 0) ||
- (next_dname_decoded == NULL)) {
- fprintf(stderr, "Could not encode base32 string!\n");
+ knot_rrset_rdata_nsec3_next_hashed(nsec3_rrset, 0, &next_dname_str,
+ &next_dname_size);
+ size_t real_size =
+ base32hex_encode_alloc(next_dname_str,
+ next_dname_size, &next_dname_decoded);
+ if (real_size <= 0 || next_dname_decoded == NULL) {
+ dbg_semcheck("Could not encode base32 string!\n");
+ free(next_dname_decoded);
return KNOT_ERROR;
}
- real_size = b32_ret;
-
/* This is why we allocate maximum length of decoded string + 1 */
// memmove(next_dname_decoded + 1, next_dname_decoded, real_size);
// next_dname_decoded[0] = real_size;
@@ -988,52 +686,60 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
knot_dname_t *next_dname =
knot_dname_new_from_str((char *)next_dname_decoded,
real_size, NULL);
- CHECK_ALLOC_LOG(next_dname, KNOT_ENOMEM);
-
+ if (next_dname == NULL) {
+ free(next_dname_decoded);
+ log_zone_warning("Could not create new dname!\n");
+ return KNOT_ERROR;
+ }
+
free(next_dname_decoded);
+ knot_dname_to_lower(next_dname);
if (knot_dname_cat(next_dname,
knot_node_owner(knot_zone_contents_apex(zone))) == NULL) {
- fprintf(stderr, "Could not concatenate dnames!\n");
+ log_zone_warning("Could not concatenate dnames!\n");
+ knot_dname_free(&next_dname);
return KNOT_ERROR;
}
if (knot_zone_contents_find_nsec3_node(zone, next_dname) == NULL) {
err_handler_handle_error(handler, node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
+ ZC_ERR_NSEC3_RDATA_CHAIN, NULL);
}
/* Directly discard. */
knot_dname_free(&next_dname);
- uint count;
+ size_t arr_size;
uint16_t *array = NULL;
- if (rdata_nsec_to_type_array(
- knot_rdata_item(
- knot_rrset_rdata(nsec3_rrset), 5),
- &array, &count) != 0) {
- err_handler_handle_error(handler, node,
- ZC_ERR_ALLOC);
- return KNOT_ERROR;
+ /* TODO only works for one NSEC3 RR. */
+ int ret = rdata_nsec_to_type_array(nsec3_rrset, 0, &array, &arr_size);
+ if (ret != KNOT_EOK) {
+ dbg_semcheck("semchecks: check_nsec3_node: Could not "
+ "convert NSEC to type array. Reason: %s\n",
+ knot_strerror(ret));
+ return ret;
}
-
+
uint16_t type = 0;
- for (int j = 0; j < count; j++) {
+ for (int j = 0; j < arr_size; j++) {
/* test for each type's presence */
type = array[j];
if (type == KNOT_RRTYPE_RRSIG) {
continue;
}
+
if (knot_node_rrset(node,
type) == NULL) {
err_handler_handle_error(handler, node,
- ZC_ERR_NSEC3_RDATA_BITMAP);
+ ZC_ERR_NSEC3_RDATA_BITMAP,
+ NULL);
}
}
/* Check that the node only contains NSEC3 and RRSIG. */
- const knot_rrset_t **rrsets = knot_node_rrsets(nsec3_node);
+ const knot_rrset_t **rrsets = knot_node_rrsets_no_copy(nsec3_node);
if (rrsets == NULL) {
return KNOT_ENOMEM;
}
@@ -1043,7 +749,8 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
if (!(type == KNOT_RRTYPE_NSEC3 ||
type == KNOT_RRTYPE_RRSIG)) {
err_handler_handle_error(handler, nsec3_node,
- ZC_ERR_NSEC3_EXTRA_RECORD);
+ ZC_ERR_NSEC3_EXTRA_RECORD,
+ NULL);
}
}
@@ -1068,42 +775,28 @@ static void count_nodes_in_tree(knot_node_t *node, void *data)
param->node_count++;
}
-/*!
- * \brief Run semantic checks for node without DNSSEC-related types.
- *
- * \param zone Current zone.
- * \param node Node to be checked.
- * \param do_checks Level of checks to be done.
- * \param handler Error handler.
- *
- * \retval KNOT_EOK if no error was found.
- *
- * \return Appropriate error code if error was found.
- */
-static int semantic_checks_plain(knot_zone_contents_t *zone,
- knot_node_t *node,
- char do_checks,
- err_handler_t *handler,
- int only_mandatory,
- char *fatal_error)
+static int zone_is_secure(const knot_zone_contents_t *z)
+{
+ const knot_rrset_t *soa_rr =
+ knot_node_rrset(knot_zone_contents_apex(z),
+ KNOT_RRTYPE_SOA);
+ return (soa_rr && soa_rr->rrsigs ? 1 : 0);
+}
+
+static int sem_check_node_mandatory(knot_zone_contents_t *zone,
+ knot_node_t *node, int level,
+ err_handler_t *handler, int *fatal_error)
{
- assert(handler);
const knot_rrset_t *cname_rrset =
knot_node_rrset(node, KNOT_RRTYPE_CNAME);
if (cname_rrset != NULL) {
- int ret = check_cname_cycles_in_zone(zone, cname_rrset,
- fatal_error);
- if (ret != KNOT_EOK) {
- err_handler_handle_error(handler, node,
- ret);
- }
-
/* No DNSSEC and yet there is more than one rrset in node */
- if (do_checks == 1 &&
+ if (level == 1 &&
knot_node_rrset_count(node) != 1) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_CNAME_EXTRA_RECORDS);
+ ZC_ERR_CNAME_EXTRA_RECORDS,
+ NULL);
} else if (knot_node_rrset_count(node) != 1) {
/* With DNSSEC node can contain RRSIG or NSEC */
if (!(knot_node_rrset(node, KNOT_RRTYPE_RRSIG) ||
@@ -1111,38 +804,25 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
knot_node_rrset_count(node) > 3) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC);
+ ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC, NULL);
}
}
- if (knot_rrset_rdata(cname_rrset) &&
- knot_rrset_rdata(cname_rrset)->next !=
- knot_rrset_rdata(cname_rrset)) {
+ if (knot_rrset_rdata_rr_count(cname_rrset) != 1) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_CNAME_MULTIPLE);
+ ZC_ERR_CNAME_MULTIPLE, NULL);
}
}
const knot_rrset_t *dname_rrset =
knot_node_rrset(node, KNOT_RRTYPE_DNAME);
if (dname_rrset != NULL) {
- int ret = check_cname_cycles_in_zone(zone, dname_rrset,
- fatal_error);
- if (ret == ZC_ERR_CNAME_CYCLE) {
- *fatal_error = 1;
- err_handler_handle_error(handler, node,
- ZC_ERR_DNAME_CYCLE);
- } else if (ret == ZC_ERR_CNAME_WILDCARD_SELF) {
- *fatal_error = 1;
- err_handler_handle_error(handler, node,
- ZC_ERR_DNAME_WILDCARD_SELF);
- }
-
if (knot_node_rrset(node, KNOT_RRTYPE_CNAME)) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_CNAME_EXTRA_RECORDS);
+ ZC_ERR_CNAME_EXTRA_RECORDS,
+ NULL);
}
if (node->children != 0) {
@@ -1161,7 +841,8 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
if (ret_apply != KNOT_EOK || param.node_count != 1) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_DNAME_CHILDREN);
+ ZC_ERR_DNAME_CHILDREN,
+ NULL);
/*
* Valid case: Node is apex, it has NSEC3 node
* and that node has only one RRSet.
@@ -1172,33 +853,34 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
node)) == 1)) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
- ZC_ERR_DNAME_CHILDREN);
+ ZC_ERR_DNAME_CHILDREN,
+ NULL);
}
}
}
- if (only_mandatory) {
- return KNOT_EOK;
- }
-
- /*!< \todo #1887 Good Lord, move this to ist own function. */
+ return KNOT_EOK;
+}
- /* check for glue records at zone cuts and in apex. */
+static int sem_check_node_optional(knot_zone_contents_t *zone,
+ knot_node_t *node, err_handler_t *handler)
+{
if (knot_node_is_deleg_point(node) || knot_zone_contents_apex(zone) ==
node) {
const knot_rrset_t *ns_rrset =
knot_node_rrset(node, KNOT_RRTYPE_NS);
if (ns_rrset == NULL) {
err_handler_handle_error(handler, node,
- ZC_ERR_MISSING_NS_DEL_POINT);
+ ZC_ERR_MISSING_NS_DEL_POINT,
+ NULL);
return KNOT_EOK;
}
//FIXME this should be an error as well ! (i guess)
+ /* TODO How about multiple RRs? */
knot_dname_t *ns_dname =
- knot_dname_deep_copy(
- knot_rdata_get_item(knot_rrset_rdata
- (ns_rrset), 0)->dname);
+ knot_dname_deep_copy(knot_rrset_rdata_ns_name(ns_rrset,
+ 0));
if (ns_dname == NULL) {
return KNOT_ENOMEM;
}
@@ -1231,7 +913,8 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
wildcard);
if (wildcard_node == NULL) {
err_handler_handle_error(handler, node,
- ZC_ERR_GLUE_NODE);
+ ZC_ERR_GLUE_NODE,
+ NULL );
} else {
/* Look for A or AAAA. */
if ((knot_node_rrset(wildcard_node,
@@ -1239,16 +922,19 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
(knot_node_rrset(wildcard_node,
KNOT_RRTYPE_AAAA) == NULL)) {
err_handler_handle_error(handler, node,
- ZC_ERR_GLUE_RECORD);
+ ZC_ERR_GLUE_RECORD,
+ NULL);
}
- }
+ }
+ knot_dname_free(&wildcard);
} else {
if ((knot_node_rrset(glue_node,
KNOT_RRTYPE_A) == NULL) &&
(knot_node_rrset(glue_node,
KNOT_RRTYPE_AAAA) == NULL)) {
err_handler_handle_error(handler, node,
- ZC_ERR_GLUE_RECORD);
+ ZC_ERR_GLUE_RECORD,
+ NULL);
}
}
}
@@ -1262,6 +948,44 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
*
* \param zone Current zone.
* \param node Node to be checked.
+ * \param do_checks Level of checks to be done.
+ * \param handler Error handler.
+ *
+ * \retval KNOT_EOK if no error was found.
+ *
+ * \return Appropriate error code if error was found.
+ */
+int sem_check_node_plain(knot_zone_contents_t *zone,
+ knot_node_t *node,
+ int do_checks,
+ err_handler_t *handler,
+ int only_mandatory,
+ int *fatal_error)
+{
+ assert(handler);
+ if (do_checks == -1) {
+ /* Determine level for our own. */
+ do_checks = (zone_is_secure(zone) ? 2 : 1);
+ }
+
+ if (only_mandatory == 1) {
+ /* Check CNAME and DNAME, else no-op. */
+ return sem_check_node_mandatory(zone, node, do_checks, handler,
+ fatal_error);
+ } else {
+ /*
+ * This is an extra run, so we do not need to check mandatory
+ * things, since they've already been checked during parsing.
+ */
+ return sem_check_node_optional(zone, node, handler);
+ }
+}
+
+/*!
+ * \brief Run semantic checks for node without DNSSEC-related types.
+ *
+ * \param zone Current zone.
+ * \param node Node to be checked.
* \param first_node First node in canonical order.
* \param last_node Last node in canonical order.
* \param handler Error handler.
@@ -1283,7 +1007,7 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
char auth = !knot_node_is_non_auth(node);
char deleg = knot_node_is_deleg_point(node);
uint rrset_count = knot_node_rrset_count(node);
- const knot_rrset_t **rrsets = knot_node_rrsets(node);
+ const knot_rrset_t **rrsets = knot_node_rrsets_no_copy(node);
const knot_rrset_t *dnskey_rrset =
knot_node_rrset(knot_zone_contents_apex(zone),
KNOT_RRTYPE_DNSKEY);
@@ -1293,9 +1017,10 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
for (int i = 0; i < rrset_count; i++) {
const knot_rrset_t *rrset = rrsets[i];
if (auth && !deleg &&
- (ret = check_rrsig_in_rrset(rrset, dnskey_rrset,
+ (ret = check_rrsig_in_rrset(handler, node,
+ rrset, dnskey_rrset,
nsec3)) != 0) {
- err_handler_handle_error(handler, node, ret);
+ err_handler_handle_error(handler, node, ret, NULL);
}
if (!nsec3 && auth) {
@@ -1306,25 +1031,22 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
if (nsec_rrset == NULL) {
err_handler_handle_error(handler, node,
- ZC_ERR_NO_NSEC);
+ ZC_ERR_NO_NSEC, NULL);
} else {
-
/* check NSEC/NSEC3 bitmap */
-
- uint count;
-
+ size_t count;
uint16_t *array = NULL;
-
- if (rdata_nsec_to_type_array(
- knot_rdata_item(
- knot_rrset_rdata(nsec_rrset),
- 1),
- &array, &count) != 0) {
- err_handler_handle_error(handler,
- NULL,
- ZC_ERR_ALLOC);
- return ZC_ERR_ALLOC; /* ... */
- /*return; */
+
+ int ret = rdata_nsec_to_type_array(nsec_rrset,
+ 0,
+ &array,
+ &count);
+ if (ret != KNOT_EOK) {
+ dbg_semcheck("semchecks: "
+ "Could not create type "
+ "array. Reason: %s.\n",
+ knot_strerror(ret));
+ return ret;
}
uint16_t type = 0;
@@ -1339,7 +1061,7 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
err_handler_handle_error(
handler,
node,
- ZC_ERR_NSEC_RDATA_BITMAP);
+ ZC_ERR_NSEC_RDATA_BITMAP, NULL);
}
}
free(array);
@@ -1348,12 +1070,11 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
/* Test that only one record is in the
* NSEC RRSet */
- if ((nsec_rrset != NULL) &&
- knot_rrset_rdata(nsec_rrset)->next !=
- knot_rrset_rdata(nsec_rrset)) {
+ if (knot_rrset_rdata_rr_count(nsec_rrset) != 1) {
err_handler_handle_error(handler,
node,
- ZC_ERR_NSEC_RDATA_MULTIPLE);
+ ZC_ERR_NSEC_RDATA_MULTIPLE,
+ NULL);
}
/*
@@ -1365,18 +1086,16 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
*/
if (nsec_rrset != NULL) {
- knot_dname_t *next_domain =
- knot_rdata_item(
- knot_rrset_rdata(nsec_rrset),
- 0)->dname;
-
+ const knot_dname_t *next_domain =
+ knot_rrset_rdata_nsec_next(nsec_rrset, 0);
assert(next_domain);
- if (knot_zone_contents_find_node(zone, next_domain) ==
+ if (knot_zone_contents_find_node(zone,
+ next_domain) ==
NULL) {
err_handler_handle_error(handler,
node,
- ZC_ERR_NSEC_RDATA_CHAIN);
+ ZC_ERR_NSEC_RDATA_CHAIN, NULL);
}
if (knot_dname_compare(next_domain,
@@ -1391,12 +1110,14 @@ static int semantic_checks_dnssec(knot_zone_contents_t *zone,
int ret = check_nsec3_node_in_zone(zone, node,
handler);
if (ret != KNOT_EOK) {
- free(rrsets);
+ dbg_semcheck("semchecks: check_dnssec: "
+ "Checking of NSEC3 node "
+ "failed. Reason: %s.\n",
+ knot_strerror(ret));
return ret;
}
}
}
- free(rrsets);
return KNOT_EOK;
}
@@ -1432,18 +1153,16 @@ static void do_checks_in_tree(knot_node_t *node, void *data)
char do_checks = *((char *)(args->arg3));
if (do_checks) {
- semantic_checks_plain(zone, node, do_checks, handler, 0,
- (char *)args->arg7);
+ sem_check_node_plain(zone, node, do_checks, handler, 0,
+ (int *)args->arg7);
} else {
assert(handler);
/* All CNAME/DNAME checks are mandatory. */
handler->options.log_cname = 1;
int check_level = 1 + (zone_is_secure(zone) ? 1 : 0);
- semantic_checks_plain(zone, node, check_level, handler, 1,
- (char *)args->arg7);
-
+ sem_check_node_plain(zone, node, check_level, handler, 1,
+ (int *)args->arg7);
free(rrsets);
- assert(do_checks == 0);
return;
}
@@ -1455,20 +1174,21 @@ static void do_checks_in_tree(knot_node_t *node, void *data)
free(rrsets);
}
-int zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
- err_handler_t *handler,
- knot_node_t **last_node)
+int zone_do_sem_checks(knot_zone_contents_t *zone, int do_checks,
+ err_handler_t *handler, knot_node_t *first_nsec3_node,
+ knot_node_t *last_nsec3_node)
{
if (!handler) {
return KNOT_EINVAL;
}
+ knot_node_t *last_node = NULL;
arg_t arguments;
arguments.arg1 = zone;
arguments.arg3 = &do_checks;
arguments.arg4 = NULL;
- arguments.arg5 = last_node;
+ arguments.arg5 = &last_node;
arguments.arg6 = handler;
- char fatal_error = 0;
+ int fatal_error = 0;
arguments.arg7 = (void *)&fatal_error;
knot_zone_contents_tree_apply_inorder(zone,
@@ -1479,81 +1199,68 @@ int zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
return KNOT_ERROR;
}
+ log_cyclic_errors_in_zone(handler, zone, last_node, first_nsec3_node,
+ last_nsec3_node, do_checks);
+
return KNOT_EOK;
}
void log_cyclic_errors_in_zone(err_handler_t *handler,
- knot_zone_contents_t *zone,
- knot_node_t *last_node,
- const knot_node_t *first_nsec3_node,
- const knot_node_t *last_nsec3_node,
- char do_checks)
+ knot_zone_contents_t *zone,
+ knot_node_t *last_node,
+ const knot_node_t *first_nsec3_node,
+ const knot_node_t *last_nsec3_node,
+ char do_checks)
{
if (do_checks == 3) {
/* Each NSEC3 node should only contain one RRSET. */
if (last_nsec3_node == NULL || first_nsec3_node == NULL) {
- /* No NSEC3, but NSEC3PARAM present. */
- err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
return;
}
- assert(last_nsec3_node && first_nsec3_node);
const knot_rrset_t *nsec3_rrset =
knot_node_rrset(last_nsec3_node,
KNOT_RRTYPE_NSEC3);
if (nsec3_rrset == NULL) {
err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
+ ZC_ERR_NSEC3_RDATA_CHAIN, NULL);
return;
}
/* check that next dname is in the zone */
+ uint8_t *next_dname_str = NULL;
+ uint8_t next_dname_size = 0;
uint8_t *next_dname_decoded = NULL;
- size_t real_size = 0;
- int32_t b32_ret;
-
- /* Make sure RRSet has enough data. */
- if (!knot_rrset_rdata(nsec3_rrset) ||
- knot_rdata_item_count(knot_rrset_rdata(nsec3_rrset)) <= 5) {
- /* Not enough data to do complete check -> incomplete chain. */
- err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_NOT_FOUND);
- return;
- }
-
- if (((b32_ret = base32hex_encode_alloc(((uint8_t *)
- rdata_item_data(&(nsec3_rrset->rdata->items[4]))) + 1,
- rdata_item_size(&nsec3_rrset->rdata->items[4]) - 1,
- &next_dname_decoded)) <= 0) ||
- (next_dname_decoded == NULL)) {
- fprintf(stderr, "Could not encode base32 string!\n");
- err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
+ knot_rrset_rdata_nsec3_next_hashed(nsec3_rrset, 0, &next_dname_str,
+ &next_dname_size);
+ size_t real_size =
+ base32hex_encode_alloc(next_dname_str,
+ next_dname_size, &next_dname_decoded);
+ if (real_size <= 0 || next_dname_decoded == NULL) {
+ dbg_semcheck("Could not encode base32 string!\n");
+ free(next_dname_decoded);
return;
}
- real_size = b32_ret;
-
/* Local allocation, will be discarded. */
knot_dname_t *next_dname =
knot_dname_new_from_str((char *)next_dname_decoded,
real_size, NULL);
if (next_dname == NULL) {
- fprintf(stderr, "Could not allocate dname!\n");
- err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_ALLOC);
+ dbg_semcheck("Could not allocate dname!\n");
+ free(next_dname_decoded);
return;
}
free(next_dname_decoded);
+ knot_dname_to_lower(next_dname);
- /*! \todo #1887 Free result and dname! */
if (knot_dname_cat(next_dname,
knot_node_owner(knot_zone_contents_apex(zone))) ==
NULL) {
- fprintf(stderr, "Could not concatenate dnames!\n");
+ dbg_semcheck("Could not concatenate dnames!\n");
err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
+ ZC_ERR_NSEC3_RDATA_CHAIN, NULL);
+ knot_dname_free(&next_dname);
return;
}
@@ -1563,13 +1270,13 @@ void log_cyclic_errors_in_zone(err_handler_t *handler,
next_dname) ==
NULL);
err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
+ ZC_ERR_NSEC3_RDATA_CHAIN, NULL);
} else {
/* Compare with the actual first NSEC3 node. */
- if (knot_dname_compare(first_nsec3_node->owner,
- next_dname) != 0) {
+ if (knot_dname_compare_non_canon(first_nsec3_node->owner,
+ next_dname) != 0) {
err_handler_handle_error(handler, last_nsec3_node,
- ZC_ERR_NSEC3_RDATA_CHAIN);
+ ZC_ERR_NSEC3_RDATA_CHAIN, NULL);
}
}
@@ -1579,7 +1286,7 @@ void log_cyclic_errors_in_zone(err_handler_t *handler,
} else if (do_checks == 2 ) {
if (last_node == NULL) {
err_handler_handle_error(handler, last_node,
- ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC);
+ ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC, NULL);
return;
} else {
const knot_rrset_t *nsec_rrset =
@@ -1588,13 +1295,12 @@ void log_cyclic_errors_in_zone(err_handler_t *handler,
if (nsec_rrset == NULL) {
err_handler_handle_error(handler, last_node,
- ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC);
+ ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC, NULL);
return;
}
const knot_dname_t *next_dname =
- knot_rdata_item(
- knot_rrset_rdata(nsec_rrset), 0)->dname;
+ knot_rrset_rdata_nsec_next(nsec_rrset, 0);
assert(next_dname);
const knot_dname_t *apex_dname =
@@ -1603,7 +1309,7 @@ void log_cyclic_errors_in_zone(err_handler_t *handler,
if (knot_dname_compare(next_dname, apex_dname) !=0) {
err_handler_handle_error(handler, last_node,
- ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC);
+ ZC_ERR_NSEC_RDATA_CHAIN_NOT_CYCLIC, NULL);
}
}
}
diff --git a/src/knot/zone/semantic-check.h b/src/knot/zone/semantic-check.h
index 2f6dad7..819c9ff 100644
--- a/src/knot/zone/semantic-check.h
+++ b/src/knot/zone/semantic-check.h
@@ -27,13 +27,15 @@
#ifndef _KNOT_SEMANTIC_CHECK_H_
#define _KNOT_SEMANTIC_CHECK_H_
+#include "libknot/zone/node.h"
+#include "libknot/zone/zone-contents.h"
+
/*!
*\brief Internal error constants. General errors are added for convenience,
* so that code does not have to change if new errors are added.
*/
enum zonechecks_errors {
- ZC_ERR_ALLOC = -50,
- ZC_ERR_UNKNOWN,
+ ZC_ERR_UNKNOWN = -50,
ZC_ERR_MISSING_SOA,
ZC_ERR_MISSING_NS_DEL_POINT,
@@ -72,8 +74,6 @@ enum zonechecks_errors {
ZC_ERR_NSEC3_GENERAL_ERROR,
- ZC_ERR_CNAME_CYCLE,
- ZC_ERR_DNAME_CYCLE,
ZC_ERR_CNAME_EXTRA_RECORDS,
ZC_ERR_DNAME_CHILDREN,
ZC_ERR_CNAME_EXTRA_RECORDS_DNSSEC,
@@ -93,6 +93,7 @@ enum zonechecks_errors {
/*!
* \brief Arguments to be used with tree traversal functions. Uses void pointers
* to be more versatile.
+ * \todo This is not needed. Just enumerate all the variables.
*
*/
struct arg {
@@ -125,7 +126,7 @@ struct handler_options {
struct err_handler {
/* Consider moving error messages here */
struct handler_options options; /*!< Handler options. */
- uint errors[(-ZC_ERR_ALLOC) + 1]; /*!< Array with error messages */
+ uint errors[(-ZC_ERR_UNKNOWN) + 1]; /*!< Array with error messages */
uint error_count; /*!< Total error count */
};
@@ -142,9 +143,8 @@ typedef struct err_handler err_handler_t;
*
* \return err_handler_t * Created error handler.
*/
-err_handler_t *handler_new(char log_cname, char log_glue,
- char log_rrsigs, char log_nsec,
- char log_nsec3);
+err_handler_t *handler_new(int log_cname, int log_glue, int log_rrsigs,
+ int log_nsec, int log_nsec3);
/*!
* \brief Called when error has been encountered in node. Will either log error
@@ -153,6 +153,7 @@ err_handler_t *handler_new(char log_cname, char log_glue,
* \param handler Error handler.
* \param node Node with semantic error in it.
* \param error Type of error.
+ * \param data Additional info in string.
*
* \retval KNOT_EOK on success.
* \retval ZC_ERR_UNKNOWN if unknown error.
@@ -160,7 +161,7 @@ err_handler_t *handler_new(char log_cname, char log_glue,
*/
int err_handler_handle_error(err_handler_t *handler,
const knot_node_t *node,
- int error);
+ int error, const char *data);
/*!
* \brief Checks if last node in NSEC/NSEC3 chain points to first node in the
@@ -190,14 +191,20 @@ void err_handler_log_all(err_handler_t *handler);
* calls function that does the actual work.
*
* \param zone Zone to be searched / checked
- * \param list Skip list of closests enclosers.
- * \param do_checks Level of semantic checks.
+ * \param check_level Level of semantic checks.
* \param handler Semantic error handler.
- * \param last_node Last checked node, which is part of NSEC(3) chain.
+ * \param last_node Last checked node, that is a part of NSEC(3) chain.
*/
-int zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
- err_handler_t *handler,
- knot_node_t **last_node);
+int zone_do_sem_checks(knot_zone_contents_t *zone, int check_level,
+ err_handler_t *handler, knot_node_t *first_nsec3_node,
+ knot_node_t *last_nsec3_node);
+
+int sem_check_node_plain(knot_zone_contents_t *zone,
+ knot_node_t *node,
+ int do_checks,
+ err_handler_t *handler,
+ int only_mandatory,
+ int *fatal_error);
#endif // _KNOT_SEMANTIC_CHECK_H_
diff --git a/src/knot/zone/zone-dump-text.c b/src/knot/zone/zone-dump-text.c
deleted file mode 100644
index 0a1dcfd..0000000
--- a/src/knot/zone/zone-dump-text.c
+++ /dev/null
@@ -1,1099 +0,0 @@
-/*!
- * \file zone-dump-text.c
- *
- * \author modifications (non-buffer implementation, zone-specific functions)
- * by Jan Kadlec <jan.kadlec@nic.cz>,
- * conversion functions by NLnet Labs,
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- * b64ntop by ISC.
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <config.h>
-
-#include <ctype.h>
-#include <assert.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include "libknot/libknot.h"
-#include "libknot/common.h"
-#include "common/skip-list.h"
-#include "common/base32hex.h"
-
-/*!< \todo #1683 Find all maximum lengths to be used in strcnat. */
-
-enum uint_max_length {
- U8_MAX_STR_LEN = 4, U16_MAX_STR_LEN = 6,
- U32_MAX_STR_LEN = 11, MAX_RR_TYPE_LEN = 20,
- MAX_NSEC_BIT_STR_LEN = 4096,
- };
-
-#define APL_NEGATION_MASK 0x80U
-#define APL_LENGTH_MASK (~APL_NEGATION_MASK)
-
-/* RFC 4025 - codes for different types that IPSECKEY can hold. */
-#define IPSECKEY_NOGATEWAY 0
-#define IPSECKEY_IP4 1
-#define IPSECKEY_IP6 2
-#define IPSECKEY_DNAME 3
-
-/* Following copyrights are only valid for b64_ntop function */
-/*
- * Copyright (c) 1996, 1998 by Internet Software Consortium.
- *
- * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Portions Copyright (c) 1995 by International Business Machines, Inc.
- *
- * International Business Machines, Inc. (hereinafter called IBM) grants
- * permission under its copyrights to use, copy, modify, and distribute this
- * Software with or without fee, provided that the above copyright notice and
- * all paragraphs of this notice appear in all copies, and that the name of IBM
- * not be used in connection with the marketing of any product incorporating
- * the Software or modifications thereof, without specific, written prior
- * permission.
- *
- * To the extent it has a right to do so, IBM grants an immunity from suit
- * under its patents, if any, for the use, sale or manufacture of products to
- * the extent that such products are used for performing Domain Name System
- * dynamic updates in TCP/IP networks by means of the Software. No immunity is
- * granted for any product per se or for any other function of any product.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
- * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
- * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
- */
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define Assert(Cond) if (!(Cond)) abort()
-
-static const char Base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char Pad64 = '=';
-
-/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
- The following encoding technique is taken from RFC 1521 by Borenstein
- and Freed. It is reproduced here in a slightly edited form for
- convenience.
-
- A 65-character subset of US-ASCII is used, enabling 6 bits to be
- represented per printable character. (The extra 65th character, "=",
- is used to signify a special processing function.)
-
- The encoding process represents 24-bit groups of input bits as output
- strings of 4 encoded characters. Proceeding from left to right, a
- 24-bit input group is formed by concatenating 3 8-bit input groups.
- These 24 bits are then treated as 4 concatenated 6-bit groups, each
- of which is translated into a single digit in the base64 alphabet.
-
- Each 6-bit group is used as an index into an array of 64 printable
- characters. The character referenced by the index is placed in the
- output string.
-
- Table 1: The Base64 Alphabet
-
- Value Encoding Value Encoding Value Encoding Value Encoding
- 0 A 17 R 34 i 51 z
- 1 B 18 S 35 j 52 0
- 2 C 19 T 36 k 53 1
- 3 D 20 U 37 l 54 2
- 4 E 21 V 38 m 55 3
- 5 F 22 W 39 n 56 4
- 6 G 23 X 40 o 57 5
- 7 H 24 Y 41 p 58 6
- 8 I 25 Z 42 q 59 7
- 9 J 26 a 43 r 60 8
- 10 K 27 b 44 s 61 9
- 11 L 28 c 45 t 62 +
- 12 M 29 d 46 u 63 /
- 13 N 30 e 47 v
- 14 O 31 f 48 w (pad) =
- 15 P 32 g 49 x
- 16 Q 33 h 50 y
-
- Special processing is performed if fewer than 24 bits are available
- at the end of the data being encoded. A full encoding quantum is
- always completed at the end of a quantity. When fewer than 24 input
- bits are available in an input group, zero bits are added (on the
- right) to form an integral number of 6-bit groups. Padding at the
- end of the data is performed using the '=' character.
-
- Since all base64 input is an integral number of octets, only the
- -------------------------------------------------
- following cases can arise:
-
- (1) the final quantum of encoding input is an integral
- multiple of 24 bits; here, the final unit of encoded
- output will be an integral multiple of 4 characters
- with no "=" padding,
- (2) the final quantum of encoding input is exactly 8 bits;
- here, the final unit of encoded output will be two
- characters followed by two "=" padding characters, or
- (3) the final quantum of encoding input is exactly 16 bits;
- here, the final unit of encoded output will be three
- characters followed by one "=" padding character.
- */
-
-int b64_ntop(uint8_t const *src, size_t srclength, char *target,
- size_t targsize) {
- size_t datalength = 0;
- uint8_t input[3];
- uint8_t output[4];
- size_t i;
-
- while (2 < srclength) {
- input[0] = *src++;
- input[1] = *src++;
- input[2] = *src++;
- srclength -= 3;
-
- output[0] = input[0] >> 2;
- output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
- output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
- output[3] = input[2] & 0x3f;
- Assert(output[0] < 64);
- Assert(output[1] < 64);
- Assert(output[2] < 64);
- Assert(output[3] < 64);
-
- if (datalength + 4 > targsize)
- return (-1);
- target[datalength++] = Base64[output[0]];
- target[datalength++] = Base64[output[1]];
- target[datalength++] = Base64[output[2]];
- target[datalength++] = Base64[output[3]];
- }
-
- /* Now we worry about padding. */
- if (0 != srclength) {
- /* Get what's left. */
- input[0] = input[1] = input[2] = '\0';
- for (i = 0; i < srclength; i++)
- input[i] = *src++;
-
- output[0] = input[0] >> 2;
- output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
- output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
- Assert(output[0] < 64);
- Assert(output[1] < 64);
- Assert(output[2] < 64);
-
- if (datalength + 4 > targsize)
- return (-1);
- target[datalength++] = Base64[output[0]];
- target[datalength++] = Base64[output[1]];
- if (srclength == 1)
- target[datalength++] = Pad64;
- else
- target[datalength++] = Base64[output[2]];
- target[datalength++] = Pad64;
- }
- if (datalength >= targsize)
- return (-1);
- target[datalength] = '\0'; /* Returned value doesn't count \0. */
- return (datalength);
-}
-
-/* Taken from RFC 4398, section 2.1. */
-knot_lookup_table_t knot_dns_certificate_types[] = {
-/* 0 Reserved */
- { 1, "PKIX" }, /* X.509 as per PKIX */
- { 2, "SPKI" }, /* SPKI cert */
- { 3, "PGP" }, /* OpenPGP packet */
- { 4, "IPKIX" }, /* The URL of an X.509 data object */
- { 5, "ISPKI" }, /* The URL of an SPKI certificate */
- { 6, "IPGP" }, /* The fingerprint and URL of an OpenPGP packet */
- { 7, "ACPKIX" }, /* Attribute Certificate */
- { 8, "IACPKIX" }, /* The URL of an Attribute Certificate */
- { 253, "URI" }, /* URI private */
- { 254, "OID" }, /* OID private */
-/* 255 Reserved */
-/* 256-65279 Available for IANA assignment */
-/* 65280-65534 Experimental */
-/* 65535 Reserved */
- { 0, NULL }
-};
-
-/* Taken from RFC 2535, section 7. */
-knot_lookup_table_t knot_dns_algorithms[] = {
- { 1, "RSAMD5" }, /* RFC 2537 */
- { 2, "DH" }, /* RFC 2539 */
- { 3, "DSA" }, /* RFC 2536 */
- { 4, "ECC" },
- { 5, "RSASHA1" }, /* RFC 3110 */
- { 252, "INDIRECT" },
- { 253, "PRIVATEDNS" },
- { 254, "PRIVATEOID" },
- { 0, NULL }
-};
-
-static int get_bit(uint8_t bits[], size_t index)
-{
- /*
- * The bits are counted from left to right, so bit #0 is the
- * left most bit.
- */
- return bits[index / 8] & (1 << (7 - index % 8));
-}
-
-static inline uint8_t * rdata_item_data(knot_rdata_item_t item)
-{
- return (uint8_t *)(item.raw_data + 1);
-}
-
-static inline uint16_t rdata_item_size(knot_rdata_item_t item)
-{
- return item.raw_data[0];
-}
-
-static char *rdata_dname_to_string(knot_rdata_item_t item)
-{
- return knot_dname_to_str(item.dname);
-}
-
-static char *rdata_binary_dname_to_string(knot_rdata_item_t item)
-{
- if (item.raw_data == NULL) {
- return NULL;
- }
-
- if (item.raw_data[0] == 0) {
- return NULL;
- }
-
- /* Create new dname frow raw data - probably the easiest way. */
- knot_dname_t *dname = knot_dname_new_from_wire((uint8_t *)(item.raw_data + 1),
- item.raw_data[0], NULL);
- if (dname == NULL) {
- return NULL;
- }
-
- /* Create string. */
- char *str = knot_dname_to_str(dname);
- knot_dname_free(&dname);
-
- return str;
-}
-
-static char *rdata_dns_name_to_string(knot_rdata_item_t item)
-{
- return knot_dname_to_str(item.dname);
-}
-
-static char *rdata_txt_data_to_string(const uint8_t *data, uint32_t *count)
-{
- uint8_t length = data[0];
- uint32_t i = 0;
- /*
- * * 4 because: unprintable chars look like \123.
- * + 3 because: opening '"', closing '"' and \0 at the end.
- * + 1 because: malloc + gcc optimization requires out_length >= 4.
- *
- * NOTE: length can be 0.
- */
- uint32_t out_length = length * 4 + 3 + 1;
-
- char *ret = malloc(out_length);
- if (ret == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- memset(ret, 0, out_length);
-
- // Opening '"'
- strcat(ret, "\"");
-
- for (i = 1; i <= length; i++) {
- char ch = (char) data[i];
- char tmp_str[5];
-
- if (isprint((int)ch)) {
- if (ch == '"' || ch == '\\') {
- strcat(ret, "\\");
- }
- tmp_str[0] = ch;
- tmp_str[1] = 0;
- strcat(ret, tmp_str);
- } else {
- sprintf(tmp_str, "\\%03u", ch);
- strcat(ret, tmp_str);
- }
- }
-
- // Closing '"'
- strcat(ret, "\"");
-
- *count = length + 1; // 1 - leading length byte.
-
- return ret;
-}
-
-static char *rdata_text_array_to_string(knot_rdata_item_t item)
-{
- /* Create delimiter. */
- char *del = " ";
-
- uint16_t size = item.raw_data[0];
- /*
- * * 6 because: item can consists of one length unprintable char strings
- * "\123" "\123" ...
- * + 1 because: ending \0.
- *
- * NOTE: txt_size is always bigger than 4 bytes (zero string has size = 1).
- */
- uint32_t txt_size = size * 6 + 1;
-
- char *ret = malloc(txt_size);
- if (ret == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- memset(ret, 0, txt_size);
-
- const uint8_t *data = (uint8_t *)(item.raw_data + 1);
- uint32_t read_count = 0;
-
- while (read_count < size) {
- uint32_t txt_count = 0;
-
- char *txt = rdata_txt_data_to_string(data + read_count, &txt_count);
- if (txt == NULL) {
- free(ret);
- return NULL;
- }
-
- /* Append text string to output. */
- strcat(ret, txt);
- read_count += txt_count;
-
- if (read_count < size) {
- strcat(ret, del);
- }
-
- free(txt);
- }
-
- return ret;
-}
-
-static char *rdata_byte_to_string(knot_rdata_item_t item)
-{
- assert(item.raw_data[0] == 1);
- uint8_t data = *((uint8_t *)(item.raw_data + 1));
- char *ret = malloc(sizeof(char) * U8_MAX_STR_LEN);
- snprintf(ret, U8_MAX_STR_LEN, "%d", (char) data);
- return ret;
-}
-
-static char *rdata_short_to_string(knot_rdata_item_t item)
-{
- uint16_t data = knot_wire_read_u16(rdata_item_data(item));
- char *ret = malloc(sizeof(char) * U16_MAX_STR_LEN);
- snprintf(ret, U16_MAX_STR_LEN, "%u", data);
- /* XXX Use proper macros - see response tests*/
- /* XXX check return value, return NULL on failure */
- return ret;
-}
-
-static char *rdata_long_to_string(knot_rdata_item_t item)
-{
- uint32_t data = knot_wire_read_u32(rdata_item_data(item));
- char *ret = malloc(sizeof(char) * U32_MAX_STR_LEN);
- /* u should be enough */
- snprintf(ret, U32_MAX_STR_LEN, "%u", data);
- return ret;
-}
-
-static char *rdata_a_to_string(knot_rdata_item_t item)
-{
- /* 200 seems like a little too much */
- char *ret = malloc(sizeof(char) * 200);
- if (inet_ntop(AF_INET, rdata_item_data(item), ret, 200)) {
- return ret;
- } else {
- return NULL;
- }
-}
-
-static char *rdata_aaaa_to_string(knot_rdata_item_t item)
-{
- char *ret = malloc(sizeof(char) * 200);
- if (inet_ntop(AF_INET6, rdata_item_data(item), ret, 200)) {
- return ret;
- } else {
- return NULL;
- }
-}
-
-static char *rdata_rrtype_to_string(knot_rdata_item_t item)
-{
- uint16_t type = knot_wire_read_u16(rdata_item_data(item));
- const char *tmp = knot_rrtype_to_string(type);
- char *ret = malloc(sizeof(char) * MAX_RR_TYPE_LEN);
- strncpy(ret, tmp, MAX_RR_TYPE_LEN);
- return ret;
-}
-
-static char *rdata_algorithm_to_string(knot_rdata_item_t item)
-{
- uint8_t id = *rdata_item_data(item);
- char *ret = malloc(sizeof(char) * MAX_RR_TYPE_LEN);
- knot_lookup_table_t *alg
- = knot_lookup_by_id(knot_dns_algorithms, id);
- if (alg) {
- strncpy(ret, alg->name, MAX_RR_TYPE_LEN);
- } else {
- snprintf(ret, U8_MAX_STR_LEN, "%u", id);
- }
-
- return ret;
-}
-
-static char *rdata_certificate_type_to_string(knot_rdata_item_t item)
-{
- uint16_t id = knot_wire_read_u16(rdata_item_data(item));
- char *ret = malloc(sizeof(char) * MAX_RR_TYPE_LEN);
- knot_lookup_table_t *type
- = knot_lookup_by_id(knot_dns_certificate_types, id);
- if (type) {
- strncpy(ret, type->name, MAX_RR_TYPE_LEN);
- } else {
- snprintf(ret, U16_MAX_STR_LEN, "%u", id);
- }
-
- return ret;
-}
-
-static char *rdata_period_to_string(knot_rdata_item_t item)
-{
- /* uint32 but read 16 XXX */
- uint32_t period = knot_wire_read_u32(rdata_item_data(item));
- char *ret = malloc(sizeof(char) * U32_MAX_STR_LEN);
- snprintf(ret, U32_MAX_STR_LEN, "%u", period);
- return ret;
-}
-
-static char *rdata_time_to_string(knot_rdata_item_t item)
-{
- time_t time = (time_t) knot_wire_read_u32(rdata_item_data(item));
- struct tm tm_conv;
- if (gmtime_r(&time, &tm_conv) == 0) {
- return 0;
- }
- char *ret = malloc(sizeof(char) * 15);
- if (strftime(ret, 15, "%Y%m%d%H%M%S", &tm_conv)) {
- return ret;
- } else {
- free(ret);
- return 0;
- }
-}
-
-static char *rdata_base32_to_string(knot_rdata_item_t item)
-{
- char *ret = NULL;
- size_t size = rdata_item_size(item);
-
- if (size == 0) {
- ret = malloc(2);
-
- ret[0] = '-';
- ret[1] = '\0';
- } else {
- int32_t b32_out;
- uint32_t out_len = ((size + 4) / 5) * 8;
-
- ret = malloc(out_len + 1);
-
- b32_out = base32hex_encode(rdata_item_data(item) + 1,
- size - 1,
- (uint8_t *)ret,
- out_len);
- if (b32_out <= 0) {
- free(ret);
- ret = NULL;
- }
-
- ret[b32_out] = '\0';
- }
-
- return ret;
-}
-
-/*!< \todo Replace with function from .../common after release. */
-static char *rdata_base64_to_string(knot_rdata_item_t item)
-{
- int length;
- size_t size = rdata_item_size(item);
- char *ret = malloc((sizeof(char) * 2 * size) + 1 * sizeof(char));
- length = b64_ntop(rdata_item_data(item), size,
- ret, (sizeof(char)) * (size * 2 + 1));
- if (length > 0) {
- return ret;
- } else {
- free(ret);
- return NULL;
- }
-}
-
-static char *knot_hex_to_string(const uint8_t *data, size_t size)
-{
- static const char hexdigits[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
- };
- size_t i;
-
- char *ret = malloc(sizeof(char) * (size * 2 + 1));
-
- for (i = 0; i < size * 2; i += 2) {
- uint8_t octet = *data++;
- ret[i] = hexdigits [octet >> 4];
- ret[i + 1] = hexdigits [octet & 0x0f];
- }
-
- ret[i] = '\0';
-
- return ret;
-}
-
-char *rdata_hex_to_string(knot_rdata_item_t item)
-{
- return knot_hex_to_string(rdata_item_data(item), rdata_item_size(item));
-}
-
-char *rdata_hexlen_to_string(knot_rdata_item_t item)
-{
- if(rdata_item_size(item) <= 1) {
- // NSEC3 salt hex can be empty
- char *ret = malloc(sizeof(char) * 2);
- ret[0] = '-';
- ret[1] = '\0';
- return ret;
- } else {
- return knot_hex_to_string(rdata_item_data(item) + 1,
- rdata_item_size(item) - 1);
- }
-}
-
-char *rdata_nsap_to_string(knot_rdata_item_t item)
-{
- char *ret = malloc(sizeof(char) * ((rdata_item_size(item) * 2) + 7));
- if (ret == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
-
- memset(ret, 0, sizeof(char) * ((rdata_item_size(item) * 2) + 7));
-
- /* String is already terminated. */
- memcpy(ret, "0x", strlen("0x"));
- char *converted = knot_hex_to_string(rdata_item_data(item),
- rdata_item_size(item));
- if (converted == NULL) {
- free(ret);
- return NULL;
- }
-
- strncat(ret, converted, rdata_item_size(item) * 2 + 1);
- free(converted);
- return ret;
-}
-
-char *rdata_apl_to_string(knot_rdata_item_t item)
-{
- uint8_t *data = rdata_item_data(item);
- size_t read = 0;
- char *pos = malloc(sizeof(char) * MAX_NSEC_BIT_STR_LEN);
- if (pos == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- memset(pos, 0, MAX_NSEC_BIT_STR_LEN);
-
- char *ret_base = pos;
-
- while (read < rdata_item_size(item)) {
- uint16_t address_family = knot_wire_read_u16(data);
- uint8_t prefix = data[2];
- uint8_t length = data[3];
- int negated = length & APL_NEGATION_MASK;
- int af = -1;
-
- length &= APL_LENGTH_MASK;
- switch (address_family) {
- case 1: af = AF_INET; break;
- case 2: af = AF_INET6; break;
- }
-
- if (af != -1) {
- char text_address[1024];
- memset(text_address, 0, sizeof(text_address));
- uint8_t address[128];
- memset(address, 0, sizeof(address));
- memcpy(address, data + 4, length);
- /* Only valid data should be present here. */
- assert((data + 4) - rdata_item_data(item) <= rdata_item_size(item));
- /* Move pointer at the end of already written data. */
- pos = ret_base + strlen(ret_base);
- if (inet_ntop(af, address,
- text_address,
- sizeof(text_address))) {
- snprintf(pos, sizeof(text_address) +
- U32_MAX_STR_LEN * 2,
- "%s%d:%s/%d%s",
- negated ? "!" : "",
- (int) address_family,
- text_address,
- (int) prefix,
- /* Last item should not have trailing space. */
- (read + 4 + length < rdata_item_size(item))
- ? " " : "");
- }
- }
-
- data += 4 + length;
- read += 4 + length;
- }
-
- return ret_base;
-}
-
-char *rdata_services_to_string(knot_rdata_item_t item)
-{
- uint8_t *data = rdata_item_data(item);
- uint8_t protocol_number = data[0];
- ssize_t bitmap_size = rdata_item_size(item) - 1;
- uint8_t *bitmap = data + 1;
- struct protoent *proto = getprotobynumber(protocol_number);
-
- char *ret = malloc(sizeof(char) * MAX_NSEC_BIT_STR_LEN);
-
- memset(ret, 0, MAX_NSEC_BIT_STR_LEN);
-
- if (proto) {
- int i;
-
- strncpy(ret, proto->p_name, strlen(proto->p_name));
- strncat(ret, " ", 2);
-
- for (i = 0; i < bitmap_size * 8; ++i) {
- if (get_bit(bitmap, i)) {
- struct servent *service =
- getservbyport((int)htons(i),
- proto->p_name);
- if (service) {
- strncat(ret, service->s_name,
- strlen(service->s_name));
- strncat(ret, " ", 2);
- } else {
- char tmp[U32_MAX_STR_LEN];
- snprintf(tmp, U32_MAX_STR_LEN,
- "%d ", i);
- strncat(ret, tmp, U32_MAX_STR_LEN);
- }
- }
- }
- }
-
- return ret;
-}
-
-char *rdata_ipsecgateway_to_string(knot_rdata_item_t item,
- const knot_rrset_t *rrset)
-{
- const knot_rdata_item_t *gateway_type_item =
- knot_rdata_item(knot_rrset_rdata(rrset), 1);
- if (gateway_type_item == NULL) {
- return NULL;
- }
- /* First two bytes store length. */
- int gateway_type = ((uint8_t *)(gateway_type_item->raw_data))[2];
- switch(gateway_type) {
- case IPSECKEY_NOGATEWAY: {
- char *ret = malloc(sizeof(char) * 4);
- if (ret == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- memset(ret, 0, sizeof(char) * 4);
- memcpy(ret, "\".\"", 4);
- return ret;
- }
- case IPSECKEY_IP4:
- return rdata_a_to_string(item);
- case IPSECKEY_IP6:
- return rdata_aaaa_to_string(item);
- case IPSECKEY_DNAME:
- return rdata_binary_dname_to_string(item);
- default:
- return NULL;
- }
-
- /* Flow *should* not get here. */
- return NULL;
-}
-
-char *rdata_nxt_to_string(knot_rdata_item_t item)
-{
- size_t i;
- uint8_t *bitmap = rdata_item_data(item);
- size_t bitmap_size = rdata_item_size(item);
-
- char *ret = malloc(sizeof(char) * MAX_NSEC_BIT_STR_LEN);
-
- memset(ret, 0, MAX_NSEC_BIT_STR_LEN);
-
- for (i = 0; i < bitmap_size * 8; ++i) {
- if (get_bit(bitmap, i)) {
- strncat(ret, knot_rrtype_to_string(i),
- MAX_RR_TYPE_LEN);
- strncat(ret, " ", 2);
- }
- }
-
- return ret;
-}
-
-
-char *rdata_nsec_to_string(knot_rdata_item_t item)
-{
- char *ret = malloc(sizeof(char) * MAX_NSEC_BIT_STR_LEN);
- if (ret == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- memset(ret, 0, MAX_NSEC_BIT_STR_LEN);
- uint8_t *data = rdata_item_data(item);
-
- int increment = 0;
- for (int i = 0; i < rdata_item_size(item); i += increment) {
- increment = 0;
- uint8_t window = data[i];
- increment++;
-
- uint8_t bitmap_size = data[i + increment];
- increment++;
-
- uint8_t *bitmap = malloc(sizeof(uint8_t) * bitmap_size);
-
- memcpy(bitmap, data + i + increment,
- bitmap_size);
-
- increment += bitmap_size;
-
- for (int j = 0; j < bitmap_size * 8; j++) {
- if (get_bit(bitmap, j)) {
- strncat(ret,
- knot_rrtype_to_string(j +
- window * 256),
- MAX_RR_TYPE_LEN);
- strncat(ret, " ", 2);
- }
- }
-
- free(bitmap);
- }
-
- return ret;
-}
-
-char *rdata_unknown_to_string(knot_rdata_item_t item)
-{
- uint16_t size = rdata_item_size(item);
- char *ret =
- malloc(sizeof(char) * (2 * rdata_item_size(item) +
- strlen("\\# ") + U16_MAX_STR_LEN + 1));
- if (ret == NULL) {
- return NULL;
- }
- memcpy(ret, "\\# \0", strlen("\\# \0"));
- snprintf(ret + strlen("\\# "),
- strlen("\\# ") + U16_MAX_STR_LEN + 1, "%lu ",
- (unsigned long) size);
- char *converted = knot_hex_to_string(rdata_item_data(item), size);
- strncat(ret, converted, size * 2 + 1);
- free(converted);
- return ret;
-}
-
-char *rdata_loc_to_string(knot_rdata_item_t item)
-{
- return rdata_unknown_to_string(item);
-}
-
-typedef char * (*item_to_string_t)(knot_rdata_item_t);
-
-static item_to_string_t item_to_string_table[KNOT_RDATA_ZF_UNKNOWN + 1] = {
- rdata_dname_to_string,
- rdata_dns_name_to_string,
- rdata_text_array_to_string,
- rdata_text_array_to_string,
- rdata_byte_to_string,
- rdata_short_to_string,
- rdata_long_to_string,
- rdata_a_to_string,
- rdata_aaaa_to_string,
- rdata_rrtype_to_string,
- rdata_algorithm_to_string,
- rdata_certificate_type_to_string,
- rdata_period_to_string,
- rdata_time_to_string,
- rdata_base64_to_string,
- rdata_base32_to_string,
- rdata_hex_to_string,
- rdata_hexlen_to_string,
- rdata_nsap_to_string,
- rdata_apl_to_string,
- NULL, //rdata_ipsecgateway_to_string,
- rdata_services_to_string,
- rdata_nxt_to_string,
- rdata_nsec_to_string,
- rdata_loc_to_string,
- rdata_unknown_to_string
-};
-
-char *rdata_item_to_string(knot_rdata_zoneformat_t type,
- knot_rdata_item_t item)
-{
- return item_to_string_table[type](item);
-}
-
-int rdata_dump_text(const knot_rdata_t *rdata, uint16_t type, FILE *f,
- const knot_rrset_t *rrset)
-{
- if (rdata == NULL || rrset == NULL) {
- return KNOT_EINVAL;
- }
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- char *item_str = NULL;
- assert(rdata->count <= desc->length);
- for (int i = 0; i < rdata->count; i++) {
- /* Workaround for IPSec gateway. */
- if (desc->zoneformat[i] == KNOT_RDATA_ZF_IPSECGATEWAY) {
- item_str = rdata_ipsecgateway_to_string(rdata->items[i],
- rrset);
- } else {
- item_str = rdata_item_to_string(desc->zoneformat[i],
- rdata->items[i]);
- }
- if (item_str == NULL) {
- item_str =
- rdata_item_to_string(KNOT_RDATA_ZF_UNKNOWN,
- rdata->items[i]);
- }
-
- if (item_str == NULL) {
- /* Fatal error. */
- return KNOT_ERROR;
- }
-
- if (i != rdata->count - 1) {
- fprintf(f, "%s ", item_str);
- } else {
- fprintf(f, "%s", item_str);
- }
-
- free(item_str);
- }
- fprintf(f, "\n");
-
- return KNOT_EOK;
-}
-
-void dump_rrset_header(const knot_rrset_t *rrset, FILE *f)
-{
- char *name = knot_dname_to_str(rrset->owner);
- fprintf(f, "%-20s ", name);
- free(name);
- fprintf(f, "%-5u ", rrset->ttl);
- fprintf(f, "%-2s ", knot_rrclass_to_string(rrset->rclass));
- fprintf(f, "%-5s ", knot_rrtype_to_string(rrset->type));
-}
-
-int rrsig_set_dump_text(knot_rrset_t *rrsig, FILE *f)
-{
- dump_rrset_header(rrsig, f);
- knot_rdata_t *tmp = rrsig->rdata;
-
- while (tmp->next != rrsig->rdata) {
- int ret = rdata_dump_text(tmp, KNOT_RRTYPE_RRSIG, f, rrsig);
- if (ret != KNOT_EOK) {
- return KNOT_ERROR;
- }
-
- dump_rrset_header(rrsig, f);
- tmp = tmp->next;
- }
-
- int ret = rdata_dump_text(tmp, KNOT_RRTYPE_RRSIG, f, rrsig);
- if (ret != KNOT_EOK) {
- return KNOT_ERROR;
- }
-
- return KNOT_EOK;
-}
-
-
-int rrset_dump_text(const knot_rrset_t *rrset, FILE *f)
-{
- if (rrset->rdata != NULL) { // No sense in dumping empty RR
- dump_rrset_header(rrset, f);
-
- knot_rdata_t *tmp = rrset->rdata;
-
- while (tmp->next != rrset->rdata) {
- int ret = rdata_dump_text(tmp, rrset->type, f, rrset);
- if (ret != KNOT_EOK) {
- return ret;
- }
- dump_rrset_header(rrset, f);
- tmp = tmp->next;
- }
-
- rdata_dump_text(tmp, rrset->type, f, rrset);
- }
-
- knot_rrset_t *rrsig_set = rrset->rrsigs;
- if (rrsig_set != NULL) {
- rrsig_set_dump_text(rrsig_set, f);
- }
-
- return KNOT_EOK;
-}
-
-struct dump_param {
- FILE *f;
- const knot_dname_t *origin;
-};
-
-int apex_node_dump_text(knot_node_t *node, FILE *f)
-{
- knot_rrset_t dummy_rrset;
- dummy_rrset.type = KNOT_RRTYPE_SOA;
- knot_rrset_t *tmp_rrset =
- (knot_rrset_t *)gen_tree_find(node->rrset_tree,
- &dummy_rrset);
- assert(tmp_rrset);
- int ret = rrset_dump_text(tmp_rrset, f);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- const knot_rrset_t **rrsets =
- knot_node_rrsets(node);
-
- for (int i = 0; i < node->rrset_count; i++) {
- if (rrsets[i]->type != KNOT_RRTYPE_SOA) {
- ret = rrset_dump_text(rrsets[i], f);
- if (ret != KNOT_EOK) {
- return ret;
- }
- }
- }
-
- free(rrsets);
-
- return KNOT_EOK;
-}
-
-void node_dump_text(knot_node_t *node, void *data)
-{
- struct dump_param *param;
- param = (struct dump_param *)data;
- FILE *f = param->f;
- const knot_dname_t *origin = param->origin;
-
- /* pointers should do in this case */
- if (node->owner == origin) {
- apex_node_dump_text(node, f);
- return;
- }
-
- const knot_rrset_t **rrsets =
- knot_node_rrsets(node);
-
- for (int i = 0; i < node->rrset_count; i++) {
- rrset_dump_text(rrsets[i], f);
- }
-
- free(rrsets);
-}
-
-int zone_dump_text(knot_zone_contents_t *zone, FILE *f)
-{
- if (f == NULL) {
- return KNOT_EINVAL;
- }
-
- fprintf(f, ";Dumped using %s v. %s\n", PACKAGE_NAME, PACKAGE_VERSION);
-
- struct dump_param param;
- param.f = f;
- assert(zone->apex != NULL && zone->apex->owner != NULL);
- param.origin = knot_node_owner(knot_zone_contents_apex(zone));
- knot_zone_contents_tree_apply_inorder(zone, node_dump_text, &param);
- knot_zone_contents_nsec3_apply_inorder(zone, node_dump_text, &param);
-
- return KNOT_EOK;
-}
diff --git a/src/knot/zone/zone-dump.c b/src/knot/zone/zone-dump.c
index 97e8a57..aa630ef 100644
--- a/src/knot/zone/zone-dump.c
+++ b/src/knot/zone/zone-dump.c
@@ -15,1111 +15,165 @@
*/
#include <config.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <assert.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
+#include <inttypes.h>
-#include "libknot/common.h"
#include "knot/zone/zone-dump.h"
+#include "common/descriptor.h"
+#include "knot/conf/conf.h"
+#include "knot/server/zones.h"
#include "libknot/libknot.h"
-#include "common/crc.h"
-#include "knot/other/debug.h"
-#include "common/skip-list.h"
-#include "semantic-check.h"
-#define ZONECHECKS_VERBOSE
+/*! \brief Size of auxiliary buffer. */
+#define DUMP_BUF_LEN (70 * 1024)
-/*! \note Contents of a dump file:
- * MAGIC(knotxx) db_filename dname_table
- * NUMBER_OF_NORMAL_NODES NUMBER_OF_NSEC3_NODES
- * [normal_nodes] [nsec3_nodes]
- * --------------------------------------------
- * dname_table is dumped as follows:
- * NUMBER_OF_DNAMES [dname_wire_length dname_wire label_count dname_labels ID]
- * node has following format:
- * owner_id
- * node_flags node_rrset_count [node_rrsets]
- * rrset has following format:
- * rrset_type rrset_class rrset_ttl rrset_rdata_count rrset_rrsig_count
- * [rrset_rdata] [rrset_rrsigs]
- * rdata can contain either dname ID,
- * or raw data stored like this: data_len [data]
- */
-
-static const size_t BUFFER_SIZE = 4096;
-
-static inline int write_to_file_crc(const void *src,
- size_t size, size_t n, int fd,
- crc_t *crc)
-{
- if (src == NULL || fd < 0) {
- return KNOT_EINVAL;
- }
- ssize_t rc = write(fd, src, size * n);
- if (rc != size * n) {
- fprintf(stderr, "write: invalid write %zd (expected %zu)\n", rc,
- n);
- }
-
- if (size * n > 0) {
- *crc =
- crc_update(*crc, (unsigned char *)src,
- size * n);
- }
-
- return rc == size * n;
-}
-
-static inline int write_to_stream(const void *src,
- size_t size, size_t n,
- uint8_t *stream,
- size_t max_size,
- size_t *written_bytes)
-{
- if (src == NULL || stream == NULL || written_bytes == NULL) {
- return KNOT_EINVAL;
- }
-
- /* Check that the stream boundary will not be crossed. */
- if (*written_bytes + (size * n) > max_size) {
- /* Buffer overflown. */
- dbg_zdump("zdump: write_to_stream: Cannot write to stream, no "
- "space left.\n");
- return KNOT_ERANGE;
- }
-
- /* Do the actual write. */
- memcpy(stream + *written_bytes, src, size * n);
- /* Expand size. */
- *written_bytes += (size * n);
-
- return KNOT_EOK;
-}
-
-static int write_wrapper(const void *src,
- size_t size, size_t n, int fd,
- uint8_t *stream, size_t max_size,
- size_t *written_bytes, crc_t *crc)
-{
- if (src == NULL) {
- dbg_zdump("zdump: write_wrapper: NULL source.\n");
- return KNOT_EINVAL;
- }
-
- dbg_zdump_detail("zdump: write_wrapper: Writing %zu bytes to fd: %d.\n",
- size * n, fd);
-
- if (fd < 0) {
- assert(stream && written_bytes);
- assert(crc == NULL);
- /*!< \todo To comply with calling convention of write_wrapper,
- * we have to lose the error. */
- int ret = write_to_stream(src, size, n, stream, max_size,
- written_bytes);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: write_wrapper: Could not write to "
- "stream. Reason: %s.\n", knot_strerror(ret));
- /* Intentional! */
- return 0;
- } else {
- /* Intentional! */
- return 1;
- }
- } else {
- /* Write to buffer first, if possible. */
- if (*written_bytes + (size * n) < BUFFER_SIZE) {
- dbg_zdump_detail("zdump: write_wrapper: Fits to "
- "buffer. Remaining=%lu.\n",
- BUFFER_SIZE - *written_bytes);
- int ret = write_to_stream(src, size, n,
- stream,
- BUFFER_SIZE, written_bytes);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: write_wrapper: "
- "Could not write to "
- "stream. Reason: %s.\n",
- knot_strerror(ret));
- /* Intentional! */
- return 0;
- } else {
- /* Intentional! */
- return 1;
- }
- } else {
- /* Fill remainder of buffer. */
- size_t remainder = BUFFER_SIZE - *written_bytes;
- dbg_zdump_detail("zdump: write_wrapper: "
- "Flushing buffer, "
- "appending %zu bytes.\n", remainder);
- int ret = write_to_stream(src, 1,
- remainder,
- stream,
- BUFFER_SIZE,
- written_bytes);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: write_wrapper: "
- "Could not write to stream: %s\n",
- knot_strerror(ret));
- // failure
- return 0;
- }
-
- assert(*written_bytes == BUFFER_SIZE);
-
- /* Buffer is filled, write to the actual file. */
- ret = write_to_file_crc(stream, 1,
- *written_bytes, fd, crc);
- if (!ret) {
- dbg_zdump("zdump: write_wrapper: "
- "Could not write to file.\n");
- // failure
- return 0;
- }
-
- /* Reset counter. */
- *written_bytes = 0;
-
- /* Write remaining data to new buffer. */
- if ((size * n) - remainder > BUFFER_SIZE) {
- /* Write through. */
- dbg_zdump("zdump: Attempting buffer write "
- "through. Total: %zu bytes.\n",
- (size * n) - remainder);
- ret = write_to_file_crc(src + remainder, 1,
- (size * n) - remainder,
- fd, crc);
- if (!ret) {
- dbg_zdump("zdump: write_wrapper: "
- "Could not write rest of buffer to "
- "file: %s.\n", knot_strerror(ret));
- // failure
- return 0;
- }
- } else {
- /* Normal buffer filling. */
- ret = write_to_stream(src + remainder,
- 1, (size * n) - remainder,
- stream, BUFFER_SIZE,
- written_bytes);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: write_wrapper: "
- "Could not write rest of buffer to "
- "stream: %s.\n", knot_strerror(ret));
- // failure
- return 0;
- }
- }
-
- // OK
- return 1;
- }
- }
-}
-
-/*!
- * \brief Dumps dname labels in binary format to given file.
- *
- * \param dname Dname whose labels are to be dumped.
- * \param f Output file.
- */
-static int knot_labels_dump_binary(const knot_dname_t *dname, int fd,
- uint8_t *stream, size_t max_size,
- size_t *written_bytes, crc_t *crc)
-{
- if (dname == NULL) {
- dbg_zdump("zdump: dump_labels: NULL dname.\n");
- return KNOT_EINVAL;
- }
-
- uint16_t label_count = dname->label_count;
- if (!write_wrapper(&label_count, sizeof(label_count), 1, fd, stream,
- max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_labels: Could not write label count.\n");
- return KNOT_ERROR;
- }
-
- if (!write_wrapper(dname->labels, sizeof(uint8_t), dname->label_count,
- fd, stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_labels: Could not write labels.\n");
- return KNOT_ERROR;
- }
-
- dbg_zdump_verb("zdump: dump_labels: Labels dumped successfully.\n");
- return KNOT_EOK;
-}
-
-/*!
- * \brief Dumps dname in binary format to given file.
- *
- * \param dname Dname to be dumped.
- * \param f Output file.
- */
-static int knot_dname_dump_binary(const knot_dname_t *dname, int fd,
- uint8_t *stream, size_t max_size,
- size_t *written_bytes,
- crc_t *crc)
-{
- if (dname == NULL) {
- dbg_zdump("zdump: dump_dname: NULL dname.\n");
- return KNOT_EINVAL;
- }
-
- /*! \todo too big */
- uint32_t dname_size = dname->size;
- if (!write_wrapper(&dname_size, sizeof(dname_size), 1, fd, stream,
- max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_dname: Cannot write dname size.\n");
- return KNOT_ERROR;
- }
-
- if (!write_wrapper(dname->name, sizeof(uint8_t), dname->size, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_dname: Cannot write dname name.\n");
- return KNOT_ERROR;
- }
-
- dbg_zdump_verb("zdump: dump_dname: Dname dumped successfully.\n");
- return knot_labels_dump_binary(dname, fd, stream, max_size,
- written_bytes, crc);
-}
-
-/*!< \todo #1684 some global variable indicating error! */
-static int dump_dname_with_id(const knot_dname_t *dname, int fd,
- uint8_t *stream, size_t max_size,
- size_t *written_bytes, crc_t *crc)
-{
- if (dname == NULL) {
- dbg_zdump("zdump: dump_dname: NULL dname.\n");
- return KNOT_EINVAL;
- }
-
- uint32_t id = dname->id;
- if (!write_wrapper(&id, sizeof(id), 1, fd, stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_dname: Cannot write ID.\n");
- return KNOT_ERROR;
- }
- return knot_dname_dump_binary(dname, fd, stream, max_size,
- written_bytes, crc);
-}
+/*! \brief Dump parameters. */
+typedef struct {
+ int ret;
+ FILE *file;
+ char *buf;
+ size_t buflen;
+ uint64_t rr_count;
+ const knot_dname_t *origin;
+ const knot_dump_style_t *style;
+} dump_params_t;
-/*!
- * \brief Dumps given rdata in binary format to given file.
- *
- * \param rdata Rdata to be dumped.
- * \param type Type of rdata.
- * \param data Arguments to be propagated.
- */
-static int knot_rdata_dump_binary(knot_rdata_t *rdata,
- uint32_t type, int fd, int use_ids,
- uint8_t *stream, size_t max_size,
- size_t *written_bytes,
- crc_t *crc)
+static void apex_node_dump_text(knot_node_t *node, dump_params_t *params)
{
- if (rdata == NULL) {
- dbg_zdump("zdump: dump_rdata: NULL rdata.\n");
- return KNOT_EINVAL;
- }
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- assert(desc != NULL);
+ knot_rrset_t *rr = knot_node_get_rrset(node, KNOT_RRTYPE_SOA);
- if (desc->fixed_items) {
- assert(desc->length == rdata->count);
+ // Dump SOA record as a first.
+ if (knot_rrset_txt_dump(rr, params->buf, params->buflen,
+ params->style) < 0) {
+ params->ret = KNOT_ENOMEM;
+ return;
}
-
- /* Write rdata count. */
- if (!write_wrapper(&(rdata->count),
- sizeof(rdata->count), 1, fd, stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_rdata: Could not write RDATA count.\n");
- return KNOT_ERROR;
+ params->rr_count += rr->rdata_count;
+ if (rr->rrsigs != NULL) {
+ params->rr_count += rr->rrsigs->rdata_count;
}
+ fprintf(params->file, "%s", params->buf);
- for (int i = 0; i < rdata->count; i++) {
- if (&(rdata->items[i]) == NULL) {
- dbg_zdump("zdump: dump_rdata: "
- "Item n. %d is not set!\n", i);
- continue;
- }
- dbg_zdump_detail("zdump: dump_rdata: Dumping item nr: %d\n", i);
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ) {
- /* some temp variables - this is way too long */
- assert(rdata->items[i].dname != NULL);
- knot_dname_t *wildcard = NULL;
-
- if (rdata->items[i].dname->node != NULL &&
- rdata->items[i].dname->node->owner !=
- rdata->items[i].dname) {
- wildcard = rdata->items[i].dname->node->owner;
- }
-
- dbg_zdump_detail("zdump: dump_rdata: "
- "Writing dname: %s.\n",
- knot_dname_to_str(
- rdata->items[i].dname));
-
- if (use_ids) {
- /* Write ID. */
- assert(rdata->items[i].dname->id != 0);
-
- uint32_t id = rdata->items[i].dname->id;
- if (!write_wrapper(&id,
- sizeof(id),
- 1, fd, stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_rdata: Cannot "
- "write dname ID.\n");
- return KNOT_ERROR;
- }
- } else {
- int ret = dump_dname_with_id(
- rdata->items[i].dname,
- fd, stream,
- max_size,
- written_bytes,
- crc);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: dump_rdata: Cannot "
- "dump dname.\n");
- return ret;
- }
- }
-
- /* Write in the zone bit */
- /*! \todo Does not have to be so complex.
- * Create extra variable. */
- if (rdata->items[i].dname->node != NULL && !wildcard) {
- dbg_zdump("zdump: dump_rdata: "
- "This dname is in the zone.\n");
- if (!write_wrapper((uint8_t *)"\1",
- sizeof(uint8_t), 1, fd,
- stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_rdata: Cannot "
- "write zone bit.\n");
- return KNOT_ERROR;
- }
- } else {
- dbg_zdump("zdump: dump_rdata: "
- "This dname is not in the zone.\n");
- if (!write_wrapper((uint8_t *)"\0",
- sizeof(uint8_t),
- 1, fd,
- stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_rdata: Cannot "
- "write zone bit.\n");
- return KNOT_ERROR;
- }
- }
+ const knot_rrset_t **rrsets = knot_node_rrsets(node);
- if (use_ids && wildcard) {
- if (!write_wrapper((uint8_t *)"\1",
- sizeof(uint8_t), 1,
- fd, stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_rdata: Cannot "
- "write wildcard bit.\n");
- return KNOT_ERROR;
- }
-
- uint32_t wildcard_id = wildcard->id;
- dbg_zdump("zdump: dump_rdata: "
- "This dname is covered by wc (%s).\n",
- knot_dname_to_str(wildcard));
- if (!write_wrapper(&wildcard_id,
- sizeof(wildcard_id), 1,
- fd, stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_rdata: Cannot "
- "write wildcard ID.\n");
- return KNOT_ERROR;
- }
- } else {
- if (!write_wrapper((uint8_t *)"\0",
- sizeof(uint8_t),
- 1, fd, stream,
- max_size, written_bytes,
- crc)) {
- dbg_zdump("zdump: dump_rdata: Cannot "
- "write wildcard bit.\n");
- return KNOT_ERROR;
- }
+ // Dump other records.
+ for (uint16_t i = 0; i < node->rrset_count; i++) {
+ if (rrsets[i]->type != KNOT_RRTYPE_SOA) {
+ if (knot_rrset_txt_dump(rrsets[i], params->buf,
+ params->buflen, params->style)
+ < 0) {
+ params->ret = KNOT_ENOMEM;
+ free(rrsets);
+ return;
}
- } else {
- dbg_zdump_detail("zdump: dump_rdata: "
- "Writing raw data. Item nr.: %d\n",
- i);
- assert(rdata->items[i].raw_data != NULL);
- if (!write_wrapper(rdata->items[i].raw_data,
- sizeof(uint8_t),
- rdata->items[i].raw_data[0] + 2, fd,
- stream, max_size,
- written_bytes, crc)) {
- dbg_zdump("zdump: dump_rdata: Cannot write raw "
- "data.\n");
- return KNOT_ERROR;
+ params->rr_count += rrsets[i]->rdata_count;
+ if (rrsets[i]->rrsigs != NULL) {
+ params->rr_count +=
+ rrsets[i]->rrsigs->rdata_count;
}
-
- dbg_zdump_detail("zdump: dump_rdata: "
- "Written %d long raw data.\n",
- rdata->items[i].raw_data[0]);
+ fprintf(params->file, "%s", params->buf);
}
}
-
- dbg_zdump_verb("zdump: dump_rdata: RDATA dumped successfully.\n");
- return KNOT_EOK;
-}
-/*!
- * \brief Dumps RRSIG in binary format to given file.
- *
- * \param rrsig RRSIG to be dumped.
- * \param data Arguments to be propagated.
- *
- * \todo This whole function is obsolete. Change after 1.0.2 release.
- */
-static int knot_rrsig_set_dump_binary(knot_rrset_t *rrsig, int fd,
- int use_ids,
- uint8_t *stream, size_t max_size,
- size_t *written_bytes, crc_t *crc)
-{
- if (rrsig == NULL) {
- dbg_zdump("zdump: dump_rrsig: NULL RRSIG.\n");
- return KNOT_EINVAL;
- }
-
-dbg_zdump_exec_detail(
- char *name = knot_dname_to_str(knot_rrset_owner(rrsig));
- dbg_zdump_detail("zdump: dump_rrsig: Dumping RRSIG \\w owner: %s.\n",
- name);
- free(name);
-);
- assert(rrsig->type == KNOT_RRTYPE_RRSIG);
- assert(rrsig->rdata);
- if (!write_wrapper(&rrsig->type, sizeof(rrsig->type), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrsig: Cannot write type.\n");
- return KNOT_ERROR;
- }
-
- if (!write_wrapper(&rrsig->rclass, sizeof(rrsig->rclass), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrsig: Cannot write class.\n");
- return KNOT_ERROR;
- }
-
- if (!write_wrapper(&rrsig->ttl, sizeof(rrsig->ttl), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrsig: Cannot write TTL.\n");
- return KNOT_ERROR;
- }
-
- uint32_t rdata_count = 1;
- /* Calculate rrset rdata count. */
- knot_rdata_t *tmp_rdata = rrsig->rdata;
- while(tmp_rdata->next != rrsig->rdata) {
- tmp_rdata = tmp_rdata->next;
- rdata_count++;
- }
-
- if (!write_wrapper(&rdata_count, sizeof(rdata_count), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrsig: Cannot write rdata count.\n");
- return KNOT_ERROR;
- }
+ free(rrsets);
- dbg_zdump_verb("zdump: dump_rrsig: Static data dumped.\n");
-
- tmp_rdata = rrsig->rdata;
- while (tmp_rdata->next != rrsig->rdata) {
- int ret = knot_rdata_dump_binary(tmp_rdata, KNOT_RRTYPE_RRSIG,
- fd,
- use_ids, stream, max_size,
- written_bytes, crc);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: rrsig_to_binary: Could not dump "
- "rdata. Reason: %s.\n", knot_strerror(ret));
- return ret;
- }
- tmp_rdata = tmp_rdata->next;
- }
- return knot_rdata_dump_binary(tmp_rdata, KNOT_RRTYPE_RRSIG, fd, use_ids,
- stream, max_size, written_bytes, crc);
+ params->ret = KNOT_EOK;
}
-/*!
- * \brief Dumps RRSet in binary format to given file.
- *
- * \param rrset RRSSet to be dumped.
- * \param data Arguments to be propagated.
- */
-static int knot_rrset_dump_binary(const knot_rrset_t *rrset, int fd,
- int use_ids,
- uint8_t *stream, size_t max_size,
- size_t *written_bytes,
- crc_t *crc)
+static void node_dump_text(knot_node_t *node, void *data)
{
- if (rrset == NULL) {
- dbg_zdump("zdump: dump_rrset: NULL RRSet.\n");
- return KNOT_EINVAL;
- }
-
- dbg_zdump_exec_detail(
- char *name = knot_dname_to_str(knot_rrset_owner(rrset));
- dbg_zdump_detail("zdump: dump_rrset: "
- "Dumping RRSet \\w owner: %s.\n",
- name);
- free(name);
- );
-
- if (!use_ids) {
- assert(rrset->rrsigs == NULL);
- }
-
- if (!use_ids) {
- /*!< \todo IDs in changeset do no good. Change loading too. */
- int ret = dump_dname_with_id(rrset->owner,
- fd, stream, max_size,
- written_bytes, crc);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: rrset_dump_binary: Could not dump "
- "RRSet's owner.\n");
- return ret;
- }
- }
-
- if (!write_wrapper(&rrset->type, sizeof(rrset->type), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrset: Cannot write type.\n");
- return KNOT_ERROR;
- }
- if (!write_wrapper(&rrset->rclass, sizeof(rrset->rclass), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrset: Cannot write class.\n");
- return KNOT_ERROR;
- }
- if (!write_wrapper(&rrset->ttl, sizeof(rrset->ttl), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrset: Cannot write TTL.\n");
- return KNOT_ERROR;
- }
-
- uint32_t rdata_count = 1;
- uint8_t has_rrsig = rrset->rrsigs != NULL;
+ dump_params_t *params = (dump_params_t *)data;
- /* Calculate rrset rdata count. */
- knot_rdata_t *tmp_rdata = rrset->rdata;
- while(tmp_rdata && (tmp_rdata->next != rrset->rdata)) {
- tmp_rdata = tmp_rdata->next;
- rdata_count++;
- }
-
- if (rrset->rdata == NULL) {
- rdata_count = 0;
+ // Zone apex rrsets.
+ if (node->owner == params->origin) {
+ apex_node_dump_text(node, params);
+ return;
}
- if (!write_wrapper(&rdata_count, sizeof(rdata_count), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_rrset: Cannot write rdata count.\n");
- return KNOT_ERROR;
- }
-
- if (!write_wrapper(&has_rrsig, sizeof(has_rrsig), 1, fd,
- stream, max_size, written_bytes, crc)) {
- return KNOT_ERROR;
- }
-
- dbg_zdump_verb("zdump: rrset_dump_binary: Static data dumped.\n");
-
- if (rdata_count != 0) {
-
- tmp_rdata = rrset->rdata;
+ const knot_rrset_t **rrsets = knot_node_rrsets(node);
- while (tmp_rdata->next != rrset->rdata) {
- int ret = knot_rdata_dump_binary(tmp_rdata, rrset->type,
- fd, use_ids,
- stream, max_size,
- written_bytes, crc);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: rrset_to_binary: Could not "
- "dump "
- "rdata. Reason: %s.\n",
- knot_strerror(ret));
- return ret;
- }
- tmp_rdata = tmp_rdata->next;
+ // Dump non-apex rrsets.
+ for (uint16_t i = 0; i < node->rrset_count; i++) {
+ if (knot_rrset_txt_dump(rrsets[i], params->buf, params->buflen,
+ params->style) < 0) {
+ params->ret = KNOT_ENOMEM;
+ free(rrsets);
+ return;
}
-
- int ret = knot_rdata_dump_binary(tmp_rdata, rrset->type,
- fd, use_ids,
- stream,
- max_size, written_bytes, crc);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: rrset_to_binary: Could not dump "
- "rdata. Reason: %s.\n", knot_strerror(ret));
- return ret;
+ params->rr_count += rrsets[i]->rdata_count;
+ if (rrsets[i]->rrsigs != NULL) {
+ params->rr_count += rrsets[i]->rrsigs->rdata_count;
}
+ fprintf(params->file, "%s", params->buf);
}
-
- dbg_zdump_verb("zdump: rrset_dump_binary: Rdata dumped.\n");
- /* This is now obsolete, although I'd rather not use recursion - that
- * would probably not work */
+ free(rrsets);
- if (rrset->rrsigs != NULL) {
- return knot_rrsig_set_dump_binary(rrset->rrsigs, fd, use_ids,
- stream,
- max_size, written_bytes, crc);
- } else {
- return KNOT_EOK;
- }
+ params->ret = KNOT_EOK;
}
-/*!
- * \brief Dumps all RRSets in node to file in binary format.
- *
- * \param node Node to dumped.
- * \param data Arguments to be propagated.
- */
-static int knot_node_dump_binary(knot_node_t *node, int fd,
- uint8_t *stream,
- size_t max_size,
- size_t *written_bytes,
- crc_t *crc)
+int zone_dump_text(knot_zone_contents_t *zone, FILE *file)
{
- if (node == NULL) {
- dbg_zdump("zdump: dump_node: NULL node.\n");
+ if (zone == NULL || file == NULL) {
return KNOT_EINVAL;
}
-
- /* first write dname */
- assert(node->owner != NULL);
-
- /* Write owner ID. */
-dbg_zdump_exec_detail(
- char *name = knot_dname_to_str(knot_node_owner(node));
- dbg_zdump_detail("zdump: dump_node: Dumping node owned by %s\n",
- name);
- free(name);
-);
- assert(node->owner->id != 0);
- uint32_t owner_id = node->owner->id;
- if (!write_wrapper(&owner_id, sizeof(owner_id), 1, fd, stream,
- max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_node: Cannot write ID.\n");
- return KNOT_ERROR;
- }
-
- /*!< \todo Fix after release. */
- if (knot_node_parent(node) != NULL) {
- uint32_t parent_id = knot_dname_id(
- knot_node_owner(knot_node_parent(node)));
- if (!write_wrapper(&parent_id, sizeof(parent_id), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_node: Cannot write parent "
- "ID.\n");
- return KNOT_ERROR;
- }
- } else {
- uint32_t parent_id = 0;
- if (!write_wrapper(&parent_id, sizeof(parent_id), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_node: Cannot write parent "
- "ID.\n");
- return KNOT_ERROR;
- }
- }
-
- if (!write_wrapper(&(node->flags), sizeof(node->flags), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_node: Cannot write node flags.\n");
- return KNOT_ERROR;
- }
-
- if (knot_node_nsec3_node(node) != NULL) {
- uint32_t nsec3_id =
- knot_node_owner(knot_node_nsec3_node(node))->id;
- if (!write_wrapper(&nsec3_id, sizeof(nsec3_id), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_node: Cannot write NSEC3 ID.\n");
- return KNOT_ERROR;
- }
-
- dbg_zdump_detail("Written nsec3 node id: %u\n",
- knot_node_owner(
- knot_node_nsec3_node(node))->id);
- } else {
- uint32_t nsec3_id = 0;
- if (!write_wrapper(&nsec3_id, sizeof(nsec3_id), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_node: Cannot write NSEC3 ID.\n");
- return KNOT_ERROR;
- }
- }
-
- /* Now we need (or do we?) count of rrsets to be read
- * but that number is yet unknown */
-
- uint16_t rrset_count = node->rrset_count;
- if (!write_wrapper(&rrset_count, sizeof(rrset_count), 1, fd,
- stream, max_size, written_bytes, crc)) {
- dbg_zdump("zdump: dump_node: Cannot write RRSet count.\n");
- return KNOT_ERROR;
- }
- const knot_rrset_t **node_rrsets = knot_node_rrsets(node);
- for (int i = 0; i < rrset_count; i++)
- {
- int ret = knot_rrset_dump_binary(node_rrsets[i], fd, 1,
- stream, max_size,
- written_bytes, crc);
- if (ret != KNOT_EOK) {
- dbg_zdump("zdump: dump_node: Could not dump RRSet. "
- "Reason: %s.\n", knot_strerror(ret));
- return ret;
- }
- }
-
- free(node_rrsets);
-
- dbg_zdump_verb("zdump: dump_node: Node dumped successfully.\n");
-
- return KNOT_EOK;
-}
-
-int zone_is_secure(knot_zone_contents_t *zone)
-{
- if (knot_node_rrset(knot_zone_contents_apex(zone),
- KNOT_RRTYPE_DNSKEY) == NULL) {
- return 0;
- } else {
- if (knot_node_rrset(knot_zone_contents_apex(zone),
- KNOT_RRTYPE_NSEC3PARAM) != NULL) {
- return 2;
- } else {
- return 1;
- }
- }
-}
-
-static void dump_dname_from_tree(knot_dname_t *dname,
- void *data)
-{
- arg_t *arg = (arg_t *)data;
- if (arg->error_code != KNOT_EOK) {
- dbg_zdump("zdump: dump_dname_from_tree: "
- "Error occured previously.\n");
- return;
- }
-
- int *fd_pointer = (int *)arg->arg1;
- int fd = -1;
- if (fd_pointer != NULL) {
- fd = *fd_pointer;
- } else {
- dbg_zdump("zdump: dump_dname_from_tree: Bad fd.\n");
- arg->error_code = KNOT_EINVAL;
- return;
- }
-
- uint8_t *buffer = (uint8_t *)arg->arg5;
- size_t *written_bytes = (size_t *)arg->arg6;
- crc_t *crc = (crc_t*)arg->arg2;
-
- arg->error_code = dump_dname_with_id(dname, fd, buffer,
- BUFFER_SIZE, written_bytes, crc);
-}
-
-static int knot_dump_dname_table(const knot_dname_table_t *dname_table,
- int fd, crc_t *crc, uint8_t *buffer,
- size_t *written_bytes)
-{
- arg_t arg;
- arg.arg2 = crc;
- arg.arg5 = buffer;
- arg.arg6 = written_bytes;
- arg.arg1 = &fd;
- assert(arg.arg1 == &fd);
- arg.error_code = KNOT_EOK;
- /* Go through the tree and dump each dname along with its ID. */
- knot_dname_table_tree_inorder_apply(dname_table,
- dump_dname_from_tree, &arg);
-
- return arg.error_code;
-}
-
-static void save_node_from_tree(knot_node_t *node, void *data)
-{
- arg_t *arg = (arg_t *)data;
- if (arg == NULL) {
- return;
- }
-
- /* Increment node count */
- (*((uint32_t *)(arg->arg1)))++;
- /* Save the first node only */
- if (arg->arg2 == NULL) {
- arg->arg2 = (void *)node;
- }
- arg->arg3 = (void *)node;
-}
-
-static void dump_node_to_file(knot_node_t *node, void *data)
-{
- arg_t *arg = (arg_t *)data;
- if (arg == NULL) {
- return;
- }
-
- if (arg->error_code != KNOT_EOK) {
- dbg_zdump("zdump: dump_node_to_file: "
- "Error occured previously.\n");
- return;
- }
-
- int *fd_pointer = (int *)arg->arg1;
- int fd = -1;
- if (fd_pointer != NULL) {
- fd = *fd_pointer;
- }
-
- uint8_t *buffer = (uint8_t *)arg->arg5;
- size_t *written_bytes = (size_t *)arg->arg6;
-
- arg->error_code =
- knot_node_dump_binary(node,
- fd, buffer, BUFFER_SIZE, written_bytes,
- (crc_t *)arg->arg7);
-}
-
-char *knot_zdump_crc_file(const char* filename)
-{
- char *crc_path =
- malloc(sizeof(char) * (strlen(filename) +
- strlen(".crc") + 1));
- CHECK_ALLOC_LOG(crc_path, NULL);
- memset(crc_path, 0,
- sizeof(char) * (strlen(filename) +
- strlen(".crc") + 1));
- memcpy(crc_path, filename,
- sizeof(char) * strlen(filename));
- crc_path = strncat(crc_path, ".crc", strlen(".crc"));
- return crc_path;
-}
-
-int knot_zdump_binary(knot_zone_contents_t *zone, int fd,
- int do_checks, const char *sfilename,
- crc_t *crc)
-{
-
- if (fd < 0 || sfilename == NULL) {
- dbg_zdump("zdump: Bad arguments.\n");
- return KNOT_EINVAL;
- }
-
- dbg_zdump("zdump: Dumping zone %p.\n", zone);
-
- uint8_t buffer[BUFFER_SIZE];
- size_t written_bytes = 0;
-
- arg_t arguments;
- /* Memory to be derefenced in the save_node_from_tree function. */
- uint32_t node_count = 0;
- arguments.arg1 = &node_count;
- arguments.arg2 = NULL;
-
- /* Count number of normal nodes. This cannot fail. */
- knot_zone_contents_tree_apply_inorder(zone, save_node_from_tree,
- &arguments);
- /* arg1 is now count of normal nodes */
- uint32_t normal_node_count = *((uint32_t *)arguments.arg1);
-
- node_count = 0;
- arguments.arg1 = &node_count;
- arguments.arg2 = NULL;
-
- /* Count number of NSEC3 nodes. This cannot fail. */
- knot_zone_contents_nsec3_apply_inorder(zone,
- save_node_from_tree, &arguments);
- uint32_t nsec3_node_count = *((uint32_t *)arguments.arg1);
- /* arg2 is the first NSEC3 node - used in sem checks. */
- /* arg3 is the last NSEC3 node - used in sem checks. */
- const knot_node_t *first_nsec3_node = (knot_node_t *)arguments.arg2;
- const knot_node_t *last_nsec3_node = (knot_node_t *)arguments.arg3;
-
- if (do_checks && zone_is_secure(zone)) {
- do_checks += zone_is_secure(zone);
- }
-
- /* FIXME(OS): Really descriptive call 1,1,1,1, some #defines here? */
- err_handler_t *handler = handler_new(1, 1, 1, 1, 1);
- if (handler == NULL) {
+ // Allocate auxiliary buffer for dumping operations.
+ char *buf = malloc(DUMP_BUF_LEN);
+ if (buf == NULL) {
+ ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
- } else { /* Do check for SOA right now */
- if (knot_node_rrset(knot_zone_contents_apex(zone),
- KNOT_RRTYPE_SOA) == NULL) {
- err_handler_handle_error(handler,
- knot_zone_contents_apex(zone),
- ZC_ERR_MISSING_SOA);
- }
- }
-
- knot_node_t *last_node = NULL;
- int ret = zone_do_sem_checks(zone,
- do_checks, handler, &last_node);
- log_cyclic_errors_in_zone(handler, zone, last_node,
- first_nsec3_node, last_nsec3_node,
- do_checks);
- err_handler_log_all(handler);
- free(handler);
-
- if (ret != KNOT_EOK) {
- fprintf(stderr, "Zone will not be dumped because of "
- "fatal semantic errors.\n");
- /* If remove fails, there is nothing we can do. */
- return KNOT_ERROR;
}
- *crc = crc_init();
+ fprintf(file, ";; Zone dump (Knot DNS %s)\n", PACKAGE_VERSION);
- /* Start writing header - magic bytes. */
- static const uint8_t MAGIC[MAGIC_LENGTH] = MAGIC_BYTES;
- if (!write_wrapper(&MAGIC, sizeof(uint8_t), MAGIC_LENGTH,
- fd, buffer, BUFFER_SIZE, &written_bytes, crc)) {
- dbg_zdump("zdump: Cannot write magic bytes.\n");
- return KNOT_ERROR;
- }
+ // Set structure with parameters.
+ dump_params_t params;
+ params.ret = KNOT_ERROR;
+ params.file = file;
+ params.buf = buf;
+ params.buflen = DUMP_BUF_LEN;
+ params.rr_count = 0;
+ params.origin = knot_node_owner(knot_zone_contents_apex(zone));
+ params.style = &KNOT_DUMP_STYLE_DEFAULT;
- /* Write source file length. */
- uint32_t sflen = strlen(sfilename) + 1;
- if (!write_wrapper(&sflen, sizeof(uint32_t), 1, fd,
- buffer, BUFFER_SIZE, &written_bytes, crc)) {
- dbg_zdump("zdump: Cannot write source file length.\n");
- return KNOT_ERROR;
+ // Dump standard zone records.
+ knot_zone_contents_tree_apply_inorder(zone, node_dump_text, &params);
+ if (params.ret != KNOT_EOK) {
+ return params.ret;
}
- /* Write source file. */
- if (!write_wrapper(sfilename, sflen, 1, fd, buffer,
- BUFFER_SIZE, &written_bytes, crc)) {
- dbg_zdump("zdump: Cannot write source file name.\n");
- return KNOT_ERROR;
+ // Dump NSEC3 zone records.
+ knot_zone_contents_nsec3_apply_inorder(zone, node_dump_text, &params);
+ if (params.ret != KNOT_EOK) {
+ return params.ret;
}
- /* Notice: End of header,
- */
+ // Create formated date-time string.
+ time_t now = time(NULL);
+ struct tm tm;
+ localtime_r(&now, &tm);
+ char date[64];
+ strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S %Z", &tm);
- /* Start writing compiled data. */
- if (!write_wrapper(&normal_node_count, sizeof(normal_node_count), 1, fd,
- buffer, BUFFER_SIZE, &written_bytes, crc)) {
- dbg_zdump("zdump: Cannot write node count.\n");
- return KNOT_ERROR;
- }
-
- if (!write_wrapper(&nsec3_node_count, sizeof(nsec3_node_count), 1, fd,
- buffer, BUFFER_SIZE, &written_bytes, crc)) {
- dbg_zdump("zdump: Cannot write NSEC3 node count.\n");
- return KNOT_ERROR;
- }
- uint32_t auth_node_count = zone->node_count;
- if (!write_wrapper(&auth_node_count,
- sizeof(auth_node_count),
- 1, fd, buffer, BUFFER_SIZE, &written_bytes, crc)) {
- dbg_zdump("zdump: Cannot write authoritative node count.\n");
- return KNOT_ERROR;
- }
+ // Dump trailing statistics.
+ fprintf(file, ";; Written %"PRIu64" records\n"
+ ";; Time %s\n",
+ params.rr_count, date);
- /* Write total number of dnames */
- assert(zone->dname_table);
- uint32_t total_dnames = zone->dname_table->id_counter;
- if (!write_wrapper(&total_dnames,
- sizeof(total_dnames), 1, fd,
- buffer, BUFFER_SIZE, &written_bytes, crc)) {
- dbg_zdump("zdump: Cannot write dname count.\n");
- return KNOT_ERROR;
- }
+ // Get master information.
+ sockaddr_t *master = &((zonedata_t *)zone->zone->data)->xfr_in.master;
- /* Write dname table. */
- if (knot_dump_dname_table(zone->dname_table, fd, crc, buffer,
- &written_bytes)
- != KNOT_EOK) {
- dbg_zdump("zdump: Cannot write dname table.\n");
- return KNOT_ERROR;
- }
-
- arguments.arg1 = &fd;
- arguments.arg3 = zone;
- arguments.arg5 = buffer;
- arguments.arg6 = &written_bytes;
- arguments.arg7 = crc;
-
- arguments.error_code = KNOT_EOK;
+ int port = sockaddr_portnum(master);
- /*!< \todo #1685 Stop traversal upon error. */
- knot_zone_contents_tree_apply_inorder(zone, dump_node_to_file,
- (void *)&arguments);
-
- if (arguments.error_code != KNOT_EOK) {
- dbg_zdump("zdump: Dump of normal tree failed. Reason: %s.\n",
- knot_strerror(arguments.error_code));
- return arguments.error_code;
- }
-
- arguments.error_code = KNOT_EOK;
- knot_zone_contents_nsec3_apply_inorder(zone, dump_node_to_file,
- (void *)&arguments);
-
- if (arguments.error_code != KNOT_EOK) {
- dbg_zdump("zdump: Dump of NSEC3 tree failed. Reason: %s.\n",
- knot_strerror(arguments.error_code));
- return arguments.error_code;
- }
-
- /* Finish the dump. */
- if (!write_to_file_crc(buffer, 1, written_bytes, fd, crc)) {
- fprintf(stderr, "Failed to finalize zone db!\n");
- return KNOT_ERROR;
- }
-
- *crc = crc_finalize(*crc);
- dbg_zdump("zdump: Zone %p dumped successfully.\n", zone);
-
- return KNOT_EOK;
-}
+ // If a master server is configured, dump info about it.
+ if (port >= 0) {
+ char addr[INET6_ADDRSTRLEN] = "NULL";
+ sockaddr_tostr(master, addr, sizeof(addr));
-int knot_zdump_rrset_serialize(const knot_rrset_t *rrset, uint8_t *stream,
- size_t max_size, size_t *written_bytes)
-{
- if (stream == NULL || rrset == NULL ||
- written_bytes == NULL) {
- dbg_zdump("zdump: rrset_serialize: Bad arguments.\n");
- return KNOT_EINVAL;
+ fprintf(file, ";; Transfered from %s#%i\n", addr, port);
}
-
- *written_bytes = 0;
- /* This fd will signal functions to use streams. */
- int fd = -1;
-
- return knot_rrset_dump_binary(rrset, fd, 0, stream, max_size,
- written_bytes, NULL);
-}
-
-int knot_zdump_dump(knot_zone_contents_t *zone, int fd, const char *sfilename,
- crc_t *crc)
-{
- int rc = knot_zdump_binary(zone, fd, 0, sfilename, crc);
- if (rc != KNOT_EOK) {
- dbg_zdump("Failed to save the zone to binary zone db\n.");
- return KNOT_ERROR;
- }
+ free(buf);
return KNOT_EOK;
}
diff --git a/src/knot/zone/zone-dump.h b/src/knot/zone/zone-dump.h
index 538cb87..8b8cb0b 100644
--- a/src/knot/zone/zone-dump.h
+++ b/src/knot/zone/zone-dump.h
@@ -16,82 +16,30 @@
/*!
* \file zone-dump.h
*
- * \author Jan Kadlec <jan.kadlec@nic.cz>
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
*
- * \brief Functions for dumping zone to binary file.
+ * \brief Zone text dump facility.
*
* \addtogroup zone-load-dump
* @{
*/
-#ifndef _KNOT_ZONEDUMP_H_
-#define _KNOT_ZONEDUMP_H_
+#ifndef _KNOTD_ZONEDUMP_H_
+#define _KNOTD_ZONEDUMP_H_
-#include "common/crc.h"
#include "libknot/zone/zone.h"
/*!
- * \brief Zone loader enums.
- */
-enum {
- MAGIC_LENGTH = 7 /*!< Compiled zone magic length. */
-};
-
-/*! \brief Magic identifier: { "knot", maj_ver, min_ver, revision } */
-#define MAGIC_BYTES {'k', 'n', 'o', 't', '1', '1', '0'}
-
-/*!
- * \brief Dumps given zone to binary file.
+ * \brief Dumps given zone to text file.
*
* \param zone Zone to be saved.
- * \param fd File descriptor to be written to.
- * \param do_checks Set to 1 to enable checking the zone for semantic errors.
- * \param sfilename Source filename of the text zone file.
- * \param crc Returns a calculated CRC.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_EINVAL if the file cannot be opened for writing.
- */
-int knot_zdump_binary(knot_zone_contents_t *zone, int fd,
- int do_checks, const char *sfilename,
- crc_t *crc);
-
-/*!
- * \brief Serializes RRSet into binary stream. Expects NULL pointer, memory
- * is handled inside function.
- *
- * \param rrset RRSet to be serialized.
- * \param stream Stream containing serialized RRSet.
- * \param max_size Maximum size of stream.
- * \param bytes_written Actually written data.
+ * \param file File to write to.
*
* \retval KNOT_EOK on success.
- * \retval KNOT_EINVAL if wrong arguments are supplied.
- * \retval KNOT_ENOMEM on memory error.
- */
-int knot_zdump_rrset_serialize(const knot_rrset_t *rrset, uint8_t *stream,
- size_t max_size, size_t *bytes_written);
-
-/*!
- * \brief Checks if zone uses DNSSEC and/or NSEC3
- *
- * \param zone Zone to be checked.
- *
- * \retval 0 if zone is not secured.
- * \retval 2 if zone uses NSEC3
- * \retval 1 if zone uses NSEC
- */
-int zone_is_secure(knot_zone_contents_t *zone);
-
-/*! \todo Document me (issue #1586). */
-int knot_zdump_dump(knot_zone_contents_t *zone, int fd, const char *sfilename,
- crc_t *crc);
-
-/*!
- * \brief Return name of the CRC file associated with filename.
+ * \retval < 0 if error.
*/
-char *knot_zdump_crc_file(const char* filename);
+int zone_dump_text(knot_zone_contents_t *zone, FILE *file);
-#endif /* _KNOT_ZONEDUMP_H_ */
+#endif // _KNOTD_ZONEDUMP_H_
/*! @} */
diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c
index 9973d75..ac414f1 100644
--- a/src/knot/zone/zone-load.c
+++ b/src/knot/zone/zone-load.c
@@ -25,1181 +25,632 @@
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
+#include <inttypes.h>
#include "common/crc.h"
#include "libknot/common.h"
+#include "knot/zone/semantic-check.h"
+#include "libknot/zone/zone-contents.h"
#include "knot/other/debug.h"
#include "knot/zone/zone-load.h"
-#include "knot/zone/zone-dump.h"
-#include "libknot/libknot.h"
+#include "zscanner/file_loader.h"
+
+/* ZONE LOADING FROM FILE USING RAGEL PARSER */
/*!
- * \brief Compares two time_t values.
- *
- * \param x First time_t value to be compared.
- * \param y Second time_t value to be compared.
+ * \brief Adds RRSet to list.
*
- * \retval 0 when times are the some.
- * \retval 1 when x > y.
- * \retval -1 when x < y.
+ * \param head Head of list.
+ * \param rrsig RRSet to be added.
*/
-static int timet_cmp(time_t x, time_t y)
+static int rrset_list_add(rrset_list_t **head, knot_rrset_t *rrsig)
{
- if (x > y) return 1;
- if (x < y) return -1;
- return 0;
+ if (*head == NULL) {
+ *head = xmalloc(sizeof(rrset_list_t));
+ (*head)->next = NULL;
+ (*head)->data = rrsig;
+ } else {
+ rrset_list_t *tmp = xmalloc(sizeof(*tmp));
+ tmp->next = *head;
+ tmp->data = rrsig;
+ *head = tmp;
+ }
+
+ dbg_zp_verb("zp: rrset_add: Added RRSIG %p to list.\n", rrsig);
+
+ return KNOT_EOK;
}
/*!
- * \brief Safe wrapper around fread.
- *
- * \param dst Destination pointer.
- * \param size Size of element to be read.
- * \param n Number of elements to be read.
- * \param fp File to read from.
+ * \brief Deletes RRSet list. Sets pointer to NULL.
*
- * \retval > 0 if succesfull.
- * \retval 0 if failed.
+ * \param head Head of list to be deleted.
*/
-static inline int fread_safe_from_file(void *dst,
- size_t size, size_t n, void *source)
+static void rrset_list_delete(rrset_list_t **head)
{
- if (dst == NULL || source == NULL) {
- dbg_zload("zload: fread_safe_from_file: NULL arguments.\n");
- return 0;
+ rrset_list_t *tmp;
+ if (*head == NULL) {
+ return;
}
- FILE *fp = (FILE *)source;
- int rc = fread(dst, size, n, fp);
- if (rc != n) {
- dbg_zload("zload: fread_safe_from_file: "
- "invalid read %d (exp. %zu)\n",
- rc, n);
+
+ while (*head != NULL) {
+ tmp = *head;
+ *head = (*head)->next;
+ free(tmp);
}
- return rc == n;
+ *head = NULL;
+
+ dbg_zp("zp: list_delete: List deleleted.\n");
}
-struct load_stream {
- uint8_t *stream;
- size_t stream_remaining;
- size_t stream_size;
-};
-
-typedef struct load_stream load_stream_t;
-
-static inline int read_from_stream(void *dst,
- size_t size, size_t n, void *source)
+static int find_rrset_for_rrsig_in_node(knot_zone_contents_t *zone,
+ knot_node_t *node,
+ knot_rrset_t *rrsig)
{
- if (dst == NULL || source == NULL) {
- dbg_zload("zload: read_from_stream: NULL arguments.\n");
- return 0;
+ assert(node);
+
+ assert(knot_dname_compare(rrsig->owner, node->owner) == 0);
+
+ knot_rrset_t *tmp_rrset =
+ knot_node_get_rrset(node,
+ knot_rrset_rdata_rrsig_type_covered(rrsig));
+
+ int ret;
+
+ if (tmp_rrset == NULL) {
+ dbg_zp("zp: find_rr_for_sig_in_node: Node does not contain "
+ "RRSet of type %d.\n",
+ knot_rrset_rdata_rrsig_type_covered(rrsig));
+ tmp_rrset = knot_rrset_new(rrsig->owner,
+ knot_rrset_rdata_rrsig_type_covered(rrsig),
+ rrsig->rclass,
+ rrsig->ttl);
+ if (tmp_rrset == NULL) {
+ dbg_zp("zp: find_rr_for_sig_in_node: Cannot create "
+ "dummy RRSet.\n");
+ return KNOT_ERROR;
+ }
+
+ ret = knot_zone_contents_add_rrset(zone, tmp_rrset, &node,
+ KNOT_RRSET_DUPL_MERGE);
+ assert(ret <= 0);
+ if (ret < 0) {
+ dbg_zp("zp: Failed to add new dummy RRSet to the zone."
+ "\n");
+ return KNOT_ERROR;
+ }
}
- /* Extract information from source data. */
- load_stream_t *data = (load_stream_t *)source;
-
+ assert(tmp_rrset);
- if (data->stream_remaining < (size * n)) {
- dbg_zload("zload: read_from_stream: Buffer depleted.\n");
- return 0;
+ if (tmp_rrset->ttl != rrsig->ttl) {
+ char *name = knot_dname_to_str(tmp_rrset->owner);
+ assert(name);
+ log_zone_warning("RRSIG owned by: %s (covering type %d) cannot be added to "
+ "its RRSet, because their TTLs differ. "
+ "Changing TTL=%d to value=%d.\n",
+ name, knot_rrset_rdata_rrsig_type_covered(rrsig),
+ rrsig->ttl, tmp_rrset->ttl);
+ free(name);
+ }
+
+ ret = knot_zone_contents_add_rrsigs(zone, rrsig, &tmp_rrset, &node,
+ KNOT_RRSET_DUPL_MERGE);
+ if (ret < 0) {
+ dbg_zp("zp: find_rr_for_sig: Cannot add RRSIG.\n");
+ return KNOT_EINVAL;
+ } else if (ret > 0) {
+ /* Merged, free data + owner, but not DNAMEs inside RDATA. */
+ knot_rrset_deep_free(&rrsig, 1, 0);
}
+ assert(tmp_rrset->rrsigs != NULL);
- memcpy(dst,
- data->stream +
- (data->stream_size - data->stream_remaining),
- size * n);
- data->stream_remaining -= size * n;
-
- return 1;
+ return KNOT_EOK;
}
-/*! \note Contents of dump file:
- * MAGIC(knotxx) NUMBER_OF_NORMAL_NODES NUMBER_OF_NSEC3_NODES
- * [normal_nodes] [nsec3_nodes]
- * node has following format:
- * owner_size owner_wire owner_label_size owner_labels owner_id
- * node_flags node_rrset_count [node_rrsets]
- * rrset has following format:
- * rrset_type rrset_class rrset_ttl rrset_rdata_count rrset_rrsig_count
- * [rrset_rdata] [rrset_rrsigs]
- * rdata can either contain full dnames (that is with labels but without ID)
- * or dname ID, if dname is in the zone
- * or raw data stored like this: data_len [data]
- */
-
-enum { DNAME_MAX_WIRE_LENGTH = 256 };
-
-/*!
- * \brief Helper function. Frees rdata items and temporary array of items.
- *
- * \param rdata Rdata to be freed.
- * \param items Items to be freed.
- * \param count Current count of rdata items.
- * \param type RRSet type.
- */
-static void load_rdata_purge(knot_rdata_t *rdata,
- knot_rdata_item_t *items,
- int count,
- knot_rrtype_descriptor_t *desc,
- uint16_t type)
+static knot_node_t *create_node(knot_zone_contents_t *zone,
+ knot_rrset_t *current_rrset,
+ int (*node_add_func)(knot_zone_contents_t *zone,
+ knot_node_t *node,
+ int create_parents, uint8_t))
{
- /* Increase refcount manually, as the set_items() doesn't see the dname
- * type and thus is unable to increment refcounter.
- */
- for (int i = 0; i < count; ++i) {
- switch(desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME:
- knot_dname_retain(items[i].dname);
- break;
- default:
- /*!< \todo This would leak wire data! */
- break;
- }
+ dbg_zp_verb("zp: create_node: Creating node using RRSet: %p.\n",
+ current_rrset);
+ knot_node_t *node =
+ knot_node_new(current_rrset->owner, NULL, 0);
+ int ret = node_add_func(zone, node, 1, 0);
+ if (ret != KNOT_EOK) {
+ log_zone_warning("Node could not be added (%s).\n",
+ knot_strerror(ret));
+ return NULL;
}
+
+ assert(current_rrset->owner == node->owner);
- /* Copy items to rdata and free the temporary rdata. */
- knot_rdata_set_items(rdata, items, count);
- knot_rdata_deep_free(&rdata, type, 0);
- free(items);
+ return node;
}
-static knot_dname_t *read_dname_with_id(FILE *f, int use_ids)
+static void process_rrsigs_in_node(parser_context_t *parser,
+ knot_zone_contents_t *zone,
+ knot_node_t *node)
{
- if (f == NULL) {
- dbg_zload("zload: read_dname_id: NULL file.\n");
- }
- knot_dname_t *ret = knot_dname_new();
- CHECK_ALLOC_LOG(ret, NULL);
-
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- if (use_ids) {
- fread_wrapper = fread_safe_from_file;
- } else {
- fread_wrapper = read_from_stream;
- }
-
- /* Read ID. */
- uint32_t dname_id = 0;
- if (!fread_wrapper(&dname_id, sizeof(dname_id), 1, f)) {
- knot_dname_release(ret);
- dbg_zload("zload: read_dname_id: Cannot read dname ID.\n");
- return NULL;
- }
-
- ret->id = dname_id;
- dbg_zload_detail("zload: read_dname_id: dname id: %u\n", dname_id);
-
- /* Read size of dname. */
- uint32_t dname_size = 0;
- if (!fread_wrapper(&dname_size, sizeof(dname_size), 1, f)) {
- knot_dname_release(ret);
- dbg_zload("zload: read_dname_id: Cannot read dname size.\n");
- return NULL;
- }
- ret->size = dname_size;
- dbg_zload_detail("loaded: dname length: %u\n", ret->size);
- if (ret->size > DNAME_MAX_WIRE_LENGTH) {
- dbg_zload("zload: read_dname_id: Name too long.\n");
- knot_dname_release(ret);
- return NULL;
- }
-
- /* Read wireformat of dname. */
- ret->name = malloc(sizeof(uint8_t) * ret->size);
- if (ret->name == NULL) {
- ERR_ALLOC_FAILED;
- knot_dname_release(ret);
- return NULL;
- }
-
- if (!fread_wrapper(ret->name, sizeof(uint8_t), ret->size, f)) {
- knot_dname_release(ret);
- dbg_zload("zload: read_dname_id: Cannot read dname name.\n");
- return NULL;
- }
-
- /* Read labels. */
- uint16_t label_count = 0;
- if (!fread_wrapper(&label_count, sizeof(label_count), 1, f)) {
- knot_dname_release(ret);
- dbg_zload("zload: read_dname_id: Cannot read "
- "dname label count.\n");
- return NULL;
- }
-
- ret->label_count = label_count;
-
- ret->labels = malloc(sizeof(uint8_t) * ret->label_count);
- if (ret->labels == NULL) {
- ERR_ALLOC_FAILED;
- knot_dname_release(ret);
- return NULL;
- }
-
- if (!fread_wrapper(ret->labels, sizeof(uint8_t), ret->label_count, f)) {
- free(ret->name);
- free(ret);
- dbg_zload("zload: read_dname_id: Cannot read dname labels.\n");
- return NULL;
+ dbg_zp_verb("zp: process_rrsigs: Processing RRSIGS in node: %p.\n",
+ node);
+ rrset_list_t *tmp = parser->node_rrsigs;
+ while (tmp != NULL) {
+ if (find_rrset_for_rrsig_in_node(zone, node,
+ tmp->data) != KNOT_EOK) {
+ parser->ret = KNOT_ERROR;
+ log_zone_error("Could not add RRSIG to zone!\n");
+ return;
+ }
+ tmp = tmp->next;
}
-
-dbg_zload_exec_detail(
- char *name = knot_dname_to_str(ret);
- dbg_zload_detail("zload: Loaded dname: %s (id: %d).\n", name,
- ret->id);
- free(name);
-);
-
- return ret;
}
-/*!
- * \brief Load rdata in binary format from file.
- *
- * \param type Type of RRSet containing read rdata.
- * \param f File to read binary data from.
- *
- * \return Pointer to read and created rdata on success, NULL otherwise.
- */
-static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
- knot_dname_t **id_array,
- int use_ids)
+void process_error(const scanner_t *s)
{
- if (f == NULL) {
- dbg_zload("zload: load_rdata: NULL arguments.\n");
- return NULL;
- }
-
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- if (use_ids) {
- fread_wrapper = fread_safe_from_file;
+ if (s->stop == true) {
+ log_zone_error("Fatal error in zone file %s:%"PRIu64": %s "
+ "Stopping zone loading.\n",
+ s->file_name, s->line_counter,
+ knot_strerror(s->error_code));
} else {
- fread_wrapper = read_from_stream;
- }
-
- knot_rdata_t *rdata = knot_rdata_new();
- if (rdata == NULL) {
- dbg_zload("zload: load_rdata: Cannot create new rdata.\n");
- return NULL;
+ log_zone_error("Error in zone file %s:%"PRIu64": %s\n",
+ s->file_name, s->line_counter,
+ knot_strerror(s->error_code));
}
+}
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- assert(desc != NULL);
-
- /* First we should read rdata count. */
-
- uint32_t rdata_count = 0;
-
- if(!fread_wrapper(&rdata_count, sizeof(rdata_count), 1, f)) {
- knot_rdata_free(&rdata);
- dbg_zload("zload: load_rdata: Cannot read rdata count.\n");
- return NULL;
- }
-
- knot_rdata_item_t *items =
- malloc(sizeof(knot_rdata_item_t) * rdata_count);
- if (items == NULL) {
- ERR_ALLOC_FAILED;
- free(rdata);
- return NULL;
- }
-
- if (rdata_count > desc->length) {
- dbg_zload("zload: load_rdata: Read wrong count of RDATA.\n");
- free(items);
- free(rdata);
- return NULL;
- }
-
- uint16_t raw_data_length = 0;
-
- dbg_zload_detail("zload: load_rdata: Reading %d items\n", rdata_count);
- dbg_zload_detail("zload: load_rdata: Current type: %s\n",
- knot_rrtype_to_string(type));
-
- for (int i = 0; i < rdata_count; i++) {
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ) {
-
- /*!< \todo #1686
- * Refactor these variables, some might be too big.
- */
-
-
- uint32_t dname_id = 0;
- uint8_t has_wildcard = 0;
- uint8_t in_the_zone = 0;
-
- if (use_ids) {
- if(!fread_wrapper(&dname_id, sizeof(dname_id),
- 1, f)) {
- load_rdata_purge(rdata,
- items, i, desc, type);
- dbg_zload("zload: load_rdata: "
- "Cannot read dname ID.\n");
- return NULL;
- }
-
- /* Store reference do dname. */
- knot_dname_retain(id_array[dname_id]);
- items[i].dname = id_array[dname_id];
- } else {
- items[i].dname = read_dname_with_id(f, use_ids);
- }
-
- dbg_zload_detail("zload: load_rdata: "
- "Loading dname: %s.\n",
- knot_dname_to_str(items[i].dname));
-
-
- if(!fread_wrapper(&in_the_zone, sizeof(in_the_zone),
- 1, f)) {
- load_rdata_purge(rdata, items, i, desc, type);
- dbg_zload("zload: load_rdata: "
- "Cannot read zone bit.\n");
- return NULL;
- }
-
- if(!fread_wrapper(&has_wildcard, sizeof(uint8_t),
- 1, f)) {
- load_rdata_purge(rdata, items, i, desc, type);
- dbg_zload("zload: load_rdata: "
- "Cannot read wildcard bit.\n");
- return NULL;
- }
-
- dbg_zload_detail("zload: load_rdata: Has wildcard: "
- "%d\n", has_wildcard);
-
- if (use_ids && !in_the_zone) {
- dbg_zload_detail("zload: load_rdata: "
- "Freeing node owned by: %s.\n",
- knot_dname_to_str(items[i].dname));
- /* Destroy the node */
- assert(!in_the_zone);
- if (items[i].dname->node != NULL &&
- /*
- * This check is here to prevent freeing
- * of previously set wildcard node.
- */
- (items[i].dname->node->owner ==
- items[i].dname)) {
- knot_node_free(&items[i].dname->node);
- assert(items[i].dname->node == NULL);
- }
- }
-
- if (use_ids && has_wildcard) {
- if(!fread_wrapper(&dname_id, sizeof(dname_id),
- 1, f)) {
- load_rdata_purge(rdata, items,
- i, desc, type);
- dbg_zload("zload: load_rdata: "
- "Cannot read wc ID.\n");
- return NULL;
- }
- dbg_zload_detail("zload: load_rdata: "
- "Wildcard: %s\n",
- knot_dname_to_str(
- id_array[dname_id]));
- items[i].dname->node =
- id_array[dname_id]->node;
- }
-
- assert(items[i].dname);
+// TODO this could be a part of the cycle below, but we'd need a buffer.
+static size_t calculate_item_size(const knot_rrset_t *rrset,
+ const scanner_t *scanner)
+{
+ const rdata_descriptor_t *desc = get_rdata_descriptor(rrset->type);
+ assert(desc);
+ size_t size = 0;
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ int item = desc->block_types[i];
+ if (descriptor_item_is_dname(item)) {
+ size += sizeof(knot_dname_t *);
+ } else if (descriptor_item_is_fixed(item)) {
+ assert(item == scanner->r_data_blocks[i + 1] -
+ scanner->r_data_blocks[i]);
+ size += item;
} else {
- if (!fread_wrapper(&raw_data_length,
- sizeof(raw_data_length), 1, f)) {
- load_rdata_purge(rdata, items, i, desc, type);
- dbg_zload("zload: load_rdata: Cannot read "
- "raw data length.\n");
- return NULL;
- }
-
- /*!< \todo this is not proper fix, see #1678 */
- items[i].raw_data =
- malloc(raw_data_length + 2);
- if (items[i].raw_data == NULL) {
- ERR_ALLOC_FAILED;
- load_rdata_purge(rdata, items, i + 1, desc,
- type);
- return NULL;
- }
- items[i].raw_data[0] = raw_data_length;
-
- if (!fread_wrapper(items[i].raw_data + 1,
- sizeof(uint8_t),
- raw_data_length, f)) {
- load_rdata_purge(rdata, items, i + 1, desc,
- type);
- dbg_zload("zload: load_rdata: Cannot read "
- "raw data.\n");
- return NULL;
- }
- dbg_zload_detail("zload: load_rdata: Read raw_data "
- "length=%d.\n",
- raw_data_length);
+ size += scanner->r_data_blocks[i + 1] -
+ scanner->r_data_blocks[i];
}
}
-
- /* Each item has refcount already incremented for saving in rdata. */
- int ret = knot_rdata_set_items(rdata, items, rdata_count);
- if (ret != KNOT_EOK) {
- dbg_zload("zload: read_rdata: Could not set items "
- "when loading rdata. Reason: %s\n.",
- knot_strerror(ret));
- load_rdata_purge(rdata, items, desc->length, desc, type);
- return NULL;
- }
-
- free(items);
- assert(rdata->count == rdata_count);
- dbg_zload_detail("zload: read_rdata: All %d items read "
- "successfully.\n",
- desc->length);
-
- return rdata;
+ return size;
}
-/*!
- * \brief Loads RRSIG from binary file.
- *
- * \param f File to read from.
- *
- * \return pointer to created and read RRSIG on success, NULL otherwise.
- */
-static knot_rrset_t *knot_load_rrsig(void *f, knot_dname_t **id_array,
- int use_ids)
+static int add_rdata_to_rr(knot_rrset_t *rrset, const scanner_t *scanner)
{
- if (f == NULL || id_array == NULL) {
- dbg_zload("zload: load_rrsig: Bad arguments.\n");
- return NULL;
+ if (rrset == NULL) {
+ dbg_zp("zp: add_rdata_to_rr: No RRSet.\n");
+ return KNOT_EINVAL;
}
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- if (use_ids) {
- fread_wrapper = fread_safe_from_file;
- } else {
- fread_wrapper = read_from_stream;
- }
+ parser_context_t *parser = scanner->data;
- knot_rrset_t *rrsig = NULL;
-
- uint16_t rrset_type = 0;
- uint16_t rrset_class = 0;
- uint32_t rrset_ttl = 0;
-
- uint32_t rdata_count = 0;
-
- if (!fread_wrapper(&rrset_type, sizeof(rrset_type), 1, f)) {
- dbg_zload("zload: load_rrsig: Cannot read type.\n");
- return NULL;
- }
-
- if (rrset_type != KNOT_RRTYPE_RRSIG) {
- dbg_zload("zload: load_rrsig: RRSIG has wrong type,"
- " probably data corruption.\n");
- return NULL;
- }
- dbg_zload_detail("zload: load_rrsig: RRSIG type: %d\n", rrset_type);
- if (!fread_wrapper(&rrset_class, sizeof(rrset_class), 1, f)) {
- dbg_zload("zload: load_rrsig: Cannot read class.\n");
- return NULL;
- }
- dbg_zload_detail("zload: load_rrsig: Class=%d\n", rrset_class);
-
- if (!fread_wrapper(&rrset_ttl, sizeof(rrset_ttl), 1, f)) {
- dbg_zload("zload: load_rrsig: Cannot read TTL.\n");
- return NULL;
- }
- dbg_zload_detail("zload: load_rrsig: TTL=%d\n", rrset_ttl);
-
- if (!fread_wrapper(&rdata_count, sizeof(rdata_count), 1, f)) {
- dbg_zload("zload: load_rrsig: Cannot read rdata count.\n");
- return NULL;
- }
-
- rrsig = knot_rrset_new(NULL, rrset_type, rrset_class, rrset_ttl);
- if (rrsig == NULL) {
- dbg_zload("zload: load_rrsig: Cannot create new RRSIG.\n");
- return NULL;
+ const rdata_descriptor_t *desc =
+ get_rdata_descriptor(knot_rrset_type(rrset));
+ assert(desc);
+
+ dbg_zp_detail("zp: add_rdata_to_rr: Adding type %d, RRSet has %d RRs.\n",
+ rrset->type, rrset->rdata_count);
+
+ size_t rdlen = calculate_item_size(rrset, scanner);
+ size_t offset = 0;
+ uint8_t *rdata = knot_rrset_create_rdata(rrset, rdlen);
+ if (rdata == NULL) {
+ dbg_zp("zp: create_rdata: Could not create RR.\n");
+ return KNOT_ENOMEM;
}
-
- knot_rdata_t *tmp_rdata = NULL;
-
- dbg_zload_detail("zload: load_rrsig: Loading %d rdata entries.\n",
- rdata_count);
-
- for (int i = 0; i < rdata_count; i++) {
- tmp_rdata = knot_load_rdata(KNOT_RRTYPE_RRSIG, f,
- id_array, use_ids);
- if (tmp_rdata) {
- int ret = knot_rrset_add_rdata(rrsig, tmp_rdata);
- if (ret != KNOT_EOK) {
- dbg_zload("zload: load_rrsig: Cannot "
- "add RDATA\n.");
- knot_rrset_deep_free(&rrsig, 0, 1, 1);
- return NULL;
+
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ int item = desc->block_types[i];
+ if (descriptor_item_is_dname(item)) {
+ knot_dname_t *dname =
+ knot_dname_new_from_wire(scanner->r_data +
+ scanner->r_data_blocks[i],
+ scanner->r_data_blocks[i + 1] - scanner->r_data_blocks[i],
+ NULL);
+ if (dname == NULL) {
+ return KNOT_ERROR;
}
+ knot_dname_to_lower(dname);
+dbg_zp_exec_detail(
+ char *name = knot_dname_to_str(dname);
+ dbg_zp_detail("zp: arr_rdata_to_rr: "
+ "Offset=%zu:Adding dname=%s (%p)\n",
+ offset, name, dname);
+ free(name);
+);
+ /* Handle DNAME duplications. */
+ knot_zone_contents_insert_dname_into_table(&dname,
+ parser->lookup_tree);
+ memcpy(rdata + offset, &dname, sizeof(knot_dname_t *));
+ offset += sizeof(knot_dname_t *);
+ } else if (descriptor_item_is_fixed(item)) {
+ //copy the whole thing
+ // TODO check the size
+ assert(item == scanner->r_data_blocks[i + 1] -
+ scanner->r_data_blocks[i]);
+ memcpy(rdata + offset,
+ scanner->r_data + scanner->r_data_blocks[i],
+ item);
+ offset += item;
} else {
- dbg_zload("zload: load_rrsig: Cannot load rdata.\n");
- knot_rrset_deep_free(&rrsig, 0, 1, 1);
- return NULL;
+ memcpy(rdata + offset,
+ scanner->r_data + scanner->r_data_blocks[i],
+ scanner->r_data_blocks[i + 1] -
+ scanner->r_data_blocks[i]);
+ offset += scanner->r_data_blocks[i + 1] -
+ scanner->r_data_blocks[i];
}
}
-
- dbg_zload_detail("zload: load_rrsig: RRSIG loaded successfully.\n");
- return rrsig;
+
+ return KNOT_EOK;
}
-/*!
- * \brief Loads RRSet from binary file.
- *
- * \param f File to read from.
- *
- * \return pointer to created and read RRSet on success, NULL otherwise.
- */
-static knot_rrset_t *knot_load_rrset(void *f, knot_dname_t **id_array,
- int use_ids)
+static void process_rr(const scanner_t *scanner)
{
- if (f == NULL) {
- dbg_zload("zload: load_rrset: NULL arguments.\n");
- return NULL;
- }
-
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- if (use_ids) {
- fread_wrapper = fread_safe_from_file;
- } else {
- fread_wrapper = read_from_stream;
- }
-
- knot_rrset_t *rrset = NULL;
-
- uint16_t rrset_type = 0;
- uint16_t rrset_class = 0;
- uint32_t rrset_ttl = 0;
-
- uint32_t rdata_count = 0;
- uint8_t rrsig_count = 0;
-
- knot_dname_t *owner = NULL;
-
- if (!use_ids) {
- dbg_zload_detail("zload: load_rrset: "
- "Loading owner of new RRSet from wire.\n");
- owner = read_dname_with_id(f, use_ids);
- if (owner == NULL) {
- dbg_zload("zload: load_rrset: Cannot load owner.\n");
- return NULL;
- }
+ /*!< \todo Refactor, too long. */
+ dbg_zp_detail("Owner from parser=%s\n",
+ scanner->r_owner);
+ parser_context_t *parser = scanner->data;
+ if (parser->ret != KNOT_EOK) {
+ return;
}
-
- if (!fread_wrapper(&rrset_type, sizeof(rrset_type), 1, f)) {
- dbg_zload("zload: load_rrset: Cannot load RRSet type.\n");
- if (!use_ids) {
- knot_dname_free(&owner);
+ knot_zone_contents_t *contents = parser->current_zone;
+ knot_dname_t *current_owner = NULL;
+ knot_rrset_t *current_rrset = NULL;
+ if (parser->last_node &&
+ (scanner->r_owner_length == parser->last_node->owner->size) &&
+ (strncmp((char *)parser->last_node->owner->name,
+ (char *)scanner->r_owner, scanner->r_owner_length) == 0)) {
+ // no need to create new dname;
+ current_owner = parser->last_node->owner;
+ knot_dname_retain(current_owner);
+ } else {
+ current_owner =
+ knot_dname_new_from_wire(scanner->r_owner,
+ scanner->r_owner_length,
+ NULL);
+ if (current_owner == NULL) {
+ parser->ret = KNOT_ERROR;
+ return;
}
- return NULL;
+ knot_dname_to_lower(current_owner);
+ /*!< \todo
+ * If name is already in the table, we might not need to create
+ * dname object, just compare wires.
+ */
+ knot_zone_contents_insert_dname_into_table(&current_owner,
+ parser->lookup_tree);
}
- dbg_zload_detail("zload: load_rrset: Type=%u\n", rrset_type);
- if (!fread_wrapper(&rrset_class, sizeof(rrset_class), 1, f)) {
- dbg_zload("zload: load_rrset: Cannot load RRSet class.\n");
- if (!use_ids) {
- knot_dname_free(&owner);
- }
- return NULL;
- }
- dbg_zload_detail("zload: load_rrset: Class=%u\n", rrset_class);
- if (!fread_wrapper(&rrset_ttl, sizeof(rrset_ttl), 1, f)) {
- dbg_zload("zload: load_rrset: Cannot load RRSet TTL.\n");
- if (!use_ids) {
- knot_dname_free(&owner);
- }
- return NULL;
- }
- dbg_zload_detail("zload: load_rrset: TTL=%u\n", rrset_ttl);
- if (!fread_wrapper(&rdata_count, sizeof(rdata_count), 1, f)) {
- if (!use_ids) {
- knot_dname_free(&owner);
- }
- return NULL;
- }
- dbg_zload_detail("zload: load_rrset: rdata count=%u\n", rdata_count);
- if (!fread_wrapper(&rrsig_count, sizeof(rrsig_count), 1, f)) {
- if (!use_ids) {
- knot_dname_free(&owner);
- }
- return NULL;
+ /*!< \todo Do not create RRSet each time - merging needs to be sorted though. */
+ current_rrset = knot_rrset_new(current_owner,
+ scanner->r_type,
+ scanner->r_class,
+ scanner->r_ttl);
+ knot_dname_release(current_owner);
+
+ assert(current_owner);
+ assert(current_rrset);
+ parser->current_rrset = current_rrset;
+
+ int ret = add_rdata_to_rr(current_rrset, scanner);
+ if (ret != KNOT_EOK) {
+ log_zone_error("Cannot add RDATA to zone, load failed.\n");
+ parser->ret = ret;
+ return;
}
- dbg_zload_detail("zload: load_rrset: RRSIG count=%u\n", rrsig_count);
+
+ dbg_zp_verb("zp: process_rr: Processing type: %d.\n",
+ parser->current_rrset->type);
-dbg_zload_exec_detail(
- char *name = knot_dname_to_str(owner);
- dbg_zload_detail("zload: load_rrset: Loading RRSet owned by: %s.\n",
- name);
- free(name);
-);
+ assert(current_rrset->rdata_count);
+
+ /* Node add/get functions. */
+ int (*node_add_func)(knot_zone_contents_t *, knot_node_t *, int,
+ uint8_t);
+ knot_node_t *(*node_get_func)(const knot_zone_contents_t *,
+ const knot_dname_t *);
- rrset = knot_rrset_new(owner, rrset_type, rrset_class, rrset_ttl);
- if (rrset == NULL) {
- dbg_zload("zload: load_rrset: Could not create rrset.");
- knot_dname_free(&owner);
- return NULL;
- }
- if (!use_ids) {
- /* Directly release if allocated locally. */
- knot_dname_release(owner);
- owner = NULL;
+ /* If we have RRSIG of NSEC3 type first node will have
+ * to be created in NSEC3 part of the zone */
+ uint16_t type_covered = 0;
+ if (current_rrset->type == KNOT_RRTYPE_RRSIG) {
+ type_covered =
+ knot_rrset_rdata_rrsig_type_covered(current_rrset);
}
- dbg_zload_detail("zload: load_rrset: RRSet type=%d\n", rrset->type);
-
- knot_rdata_t *tmp_rdata = NULL;
-
- for (int i = 0; i < rdata_count; i++) {
- tmp_rdata = knot_load_rdata(rrset->type, f,
- id_array, use_ids);
- if (tmp_rdata) {
- int ret = knot_rrset_add_rdata(rrset, tmp_rdata);
- if (ret != KNOT_EOK) {
- dbg_zload("zload: load_rrset: Cannot add "
- "RDATA.\n");
- knot_rrset_deep_free(&rrset, 0, 1, 1);
- return NULL;
+ if (current_rrset->type != KNOT_RRTYPE_NSEC3 &&
+ type_covered != KNOT_RRTYPE_NSEC3) {
+ node_add_func = &knot_zone_contents_add_node;
+ node_get_func = &knot_zone_contents_get_node;
+ } else {
+ node_add_func = &knot_zone_contents_add_nsec3_node;
+ node_get_func = &knot_zone_contents_get_nsec3_node;
+ }
+
+ if (current_rrset->type == KNOT_RRTYPE_SOA) {
+ if (knot_node_rrset(knot_zone_contents_apex(contents),
+ KNOT_RRTYPE_SOA) != NULL) {
+ /* Receiving another SOA. */
+ if (!knot_rrset_equal(current_rrset,
+ knot_node_rrset(knot_zone_contents_apex(contents),
+ KNOT_RRTYPE_SOA), KNOT_RRSET_COMPARE_WHOLE)) {
+ log_zone_error("Extra SOA record in the "
+ "zone.\n");
+ /*!< \todo consider a new error */
+ parser->ret = KNOT_EMALF;
+ return;
+ } else {
+ log_zone_warning("encountered identical "
+ "extra SOA record");
+ knot_rrset_deep_free(&current_rrset, 1, 1);
+ parser->ret = KNOT_EOK;
+ return;
}
- } else {
- dbg_zload("zload: load_rrset: Cannot load rdata.\n");
- knot_rrset_deep_free(&rrset, 0, 1, 1);
- return NULL;
}
}
- knot_rrset_t *tmp_rrsig = NULL;
-
- dbg_zload_detail("zload: load_rrset: Reading: %d RRSIGs.\n",
- rrsig_count);
- if (rrsig_count) {
- tmp_rrsig = knot_load_rrsig(f, id_array, use_ids);
- if (tmp_rrsig == NULL) {
- dbg_zload("zload: load_rrset: Cannot load RRSIG.\n");
- knot_rrset_deep_free(&rrset, 0, 1, 1);
- return NULL;
- }
- if (!use_ids) {
- knot_rrset_set_owner(tmp_rrsig, rrset->owner);
+ if (current_rrset->type == KNOT_RRTYPE_SOA) {
+ if (knot_dname_compare(current_rrset->owner,
+ parser->origin_from_config) != 0) {
+ log_zone_error("SOA record has a different "
+ "owner than the one specified "
+ "in config! \n");
+ /* Such SOA cannot even be added, because
+ * it would not be in the zone apex. */
+ parser->ret = KNOT_EBADZONE;
+ return;
}
}
- knot_rrset_set_rrsigs(rrset, tmp_rrsig);
+ if (current_rrset->type == KNOT_RRTYPE_RRSIG) {
+ knot_rrset_t *tmp_rrsig = current_rrset;
- dbg_zload_detail("zload: load_rrset: Finished loading RRSet %p.\n",
- rrset);
- return rrset;
-}
+ if (parser->last_node &&
+ knot_dname_compare_non_canon(parser->last_node->owner,
+ current_rrset->owner) != 0) {
+ /* RRSIG is first in the node, so we have to create it
+ * before we return
+ */
+ if (parser->node_rrsigs != NULL) {
+ process_rrsigs_in_node(parser,
+ contents,
+ parser->last_node);
+ rrset_list_delete(&parser->node_rrsigs);
+ }
+
+ /* The node might however been created previously. */
+ parser->last_node =
+ knot_zone_contents_get_node(contents,
+ knot_rrset_owner(current_rrset));
+
+ if (parser->last_node == NULL) {
+ /* Try NSEC3 tree. */
+ if (current_rrset->type == KNOT_RRTYPE_NSEC3 ||
+ current_rrset->type == KNOT_RRTYPE_RRSIG) {
+ parser->last_node =
+ knot_zone_contents_get_nsec3_node(
+ contents,
+ knot_rrset_owner(
+ current_rrset));
+ }
+ }
+
+ if (parser->last_node == NULL) {
+ /* Still NULL, node has to be created. */
+ if ((parser->last_node = create_node(contents,
+ current_rrset,
+ node_add_func))
+ == NULL) {
+ knot_rrset_free(&tmp_rrsig);
+ dbg_zp("zp: process_rr: Cannot "
+ "create new node.\n");
+ log_zone_error("None cannot be created.\n");
+ /*!< \todo consider a new error */
+ parser->ret = KNOT_ERROR;
+ return;
+ }
+ }
+ }
-/*!
- * \brief Loads node from binary file.
- *
- * \param f File to read from.
- *
- * \return Pointer to created and read node on success, NULL otherwise.
- */
-static knot_node_t *knot_load_node(FILE *f, knot_dname_t **id_array)
-{
- if (f == NULL || id_array == NULL) {
- dbg_zload("zload: load_node: Wrong parameters.\n");
- return NULL;
+ if (rrset_list_add(&parser->node_rrsigs, tmp_rrsig) != 0) {
+ dbg_zp("zp: process_rr: Cannot "
+ "create new node.\n");
+ parser->ret = KNOT_ERROR;
+ return;
+ }
+
+ dbg_zp_verb("zp: process_rr: RRSIG proccesed successfully.\n");
+ parser->ret = KNOT_EOK;
+ return;
}
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- fread_wrapper = fread_safe_from_file;
-
- uint8_t flags = 0;
- knot_node_t *node = NULL;
- uint32_t parent_id = 0;
- uint32_t nsec3_node_id = 0;
- uint16_t rrset_count = 0;
- uint32_t dname_id = 0;
+ /*! \todo Move RRSIG and RRSet handling to funtions. */
+ assert(current_rrset->type != KNOT_RRTYPE_RRSIG);
- /* At the beginning of node - just dname_id !!!.*/
- if (!fread_wrapper(&dname_id, sizeof(dname_id), 1, f)) {
- dbg_zload("zload: load_node: Cannot read owner ID.\n");
- return NULL;
- }
-
- if (!fread_wrapper(&parent_id, sizeof(parent_id), 1, f)) {
- dbg_zload("zload: load_node: Cannot read owner ID.\n");
- return NULL;
- }
-
- if (!fread_wrapper(&flags, sizeof(flags), 1, f)) {
- dbg_zload("zload: load_node: Cannot read node flags.\n");
- return NULL;
- }
-
- if (!fread_wrapper(&nsec3_node_id, sizeof(nsec3_node_id), 1, f)) {
- dbg_zload("zload: load_node: Cannot read NSEC3 node.\n");
- return NULL;
- }
-
- if (!fread_wrapper(&rrset_count, sizeof(rrset_count), 1, f)) {
- dbg_zload("zload: load_node: Cannot read rrset count.\n");
- return NULL;
- }
- knot_dname_t *owner = id_array[dname_id];
- if (owner == NULL) {
- dbg_zload("zload: load_node: Wrong dname ID, cannot load.\n");
- return NULL;
- }
-
- dbg_zload_detail("zload: load_node: Node owner id: %d.\n", dname_id);
-dbg_zload_exec_detail(
- char *name = knot_dname_to_str(owner);
- dbg_zload_detail("zload: load_node: Node owned by: %s.\n", name);
- free(name);
-);
- dbg_zload_detail("zload: load_node: Number of RRSets in a node: %d.\n",
- rrset_count);
-
- node = owner->node;
-
- if (node == NULL) {
- dbg_zload("zload: load_node: NULL node, cannot proceed.\n");
- return NULL;
- }
- /* XXX can it be 0, ever? I think not. */
- if (nsec3_node_id != 0) {
- knot_node_set_nsec3_node(node, id_array[nsec3_node_id]->node);
- } else {
- knot_node_set_nsec3_node(node, NULL);
- }
-
- /* Retain new owner while releasing replaced owner. */
- knot_node_set_owner(node, owner);
- node->flags = flags;
-
- //XXX will have to be set already...canonical order should do it
-
- if (parent_id != 0) {
- knot_node_set_parent(node, id_array[parent_id]->node);
- assert(knot_node_parent(node) != NULL);
+ knot_node_t *node = NULL;
+ /* \note this could probably be much simpler */
+ if (parser->last_node && current_rrset->type != KNOT_RRTYPE_SOA &&
+ knot_dname_compare_non_canon(parser->last_node->owner,
+ current_rrset->owner) ==
+ 0) {
+ node = parser->last_node;
} else {
- knot_node_set_parent(node, NULL);
+ if (parser->last_node && parser->node_rrsigs) {
+ process_rrsigs_in_node(parser,
+ contents,
+ parser->last_node);
+ }
+ rrset_list_delete(&parser->node_rrsigs);
+ /* new node */
+ node = node_get_func(contents, current_rrset->owner);
}
- knot_rrset_t *tmp_rrset = NULL;
-
- for (int i = 0; i < rrset_count; i++) {
- if ((tmp_rrset = knot_load_rrset(f, id_array, 1)) == NULL) {
- knot_node_free(&node);
- /*!< \todo #1686
- * Refactor freeing, might not be enough.
- */
- dbg_zload("zload: load_node: Cannot load RRSet.\n");
- return NULL;
- }
- /* Retain new owner while releasing replaced owner. */
- knot_rrset_set_owner(tmp_rrset, node->owner);
- if (tmp_rrset->rrsigs != NULL) {
- knot_rrset_set_owner(tmp_rrset->rrsigs, node->owner);
- }
- if (knot_node_add_rrset(node, tmp_rrset, 0) < 0) {
- dbg_zload("zload: load_node: Cannot add RRSet "
- "to node.\n");
- return NULL;
+ if (node == NULL) {
+ if (parser->last_node && parser->node_rrsigs) {
+ process_rrsigs_in_node(parser,
+ contents,
+ parser->last_node);
}
- }
- assert(node != NULL);
- dbg_zload_detail("zload: load_node: Node loaded: %p\n", node);
- return node;
-}
-/*!
- * \brief Finds and sets wildcard child for given node's owner.
- *
- * \param zone Current zone.
- * \param node Node to be used.
- * \param nsec3 Is NSEC3 node.
- */
-static void find_and_set_wildcard_child(knot_zone_contents_t *zone,
- knot_node_t *node, int nsec3)
-{
- if (zone == NULL || node == NULL) {
- dbg_zload("zload: set_wc: Bad arguments.\n");
- return;
- }
- knot_dname_t *chopped = knot_dname_left_chop(node->owner);
- knot_node_t *wildcard_parent;
- if (!nsec3) {
- wildcard_parent =
- knot_zone_contents_get_node(zone, chopped);
- } else {
- wildcard_parent =
- knot_zone_contents_get_nsec3_node(zone, chopped);
+ if ((node = create_node(contents, current_rrset,
+ node_add_func)) == NULL) {
+ dbg_zp("zp: process_rr: Cannot "
+ "create new node.\n");
+ char *zone_name = knot_dname_to_str(contents->apex->owner);
+ char *name = knot_dname_to_str(current_rrset->owner);
+ log_zone_warning("Zone %s: Cannot create new "
+ "node owned by %s, skipping.\n",
+ zone_name, name);
+ free(name);
+ free(zone_name);
+ return;
+ }
}
-
- /* Directly discard. */
- knot_dname_free(&chopped);
-
- assert(wildcard_parent); /* it *has* to be there */
-
- knot_node_set_wildcard_child(wildcard_parent, node);
-}
-
-/*!
- * \brief Checks if magic string at the beginning of the file is the same
- * as defined.
- *
- * \param f File to read magic string from.
- * \param MAGIC Magic string.
- * \param MAGIC_LENGTH Length of magic string.
- *
- * \retval 1 if magic is the same.
- * \retval 0 otherwise.
- */
-static int knot_check_magic(FILE *f, const uint8_t* MAGIC, uint MAGIC_LENGTH)
-{
- uint8_t tmp_magic[MAGIC_LENGTH];
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- fread_wrapper = fread_safe_from_file;
-
- if (!fread_wrapper(&tmp_magic, sizeof(uint8_t), MAGIC_LENGTH, f)) {
- return 0;
- }
-
- for (int i = 0; i < MAGIC_LENGTH; i++) {
- if (tmp_magic[i] != MAGIC[i]) {
- return 0;
+ if (current_rrset->type != KNOT_RRTYPE_RRSIG) {
+ /*
+ * If there's already an RRSet of this type in a node, check
+ * that TTLs are the same, if not, give warning a change TTL.
+ */
+ const knot_rrset_t *rrset_in_node =
+ knot_node_rrset(node, current_rrset->type);
+ if (rrset_in_node &&
+ current_rrset->ttl != rrset_in_node->ttl) {
+ log_zone_warning("TTL does not match TTL of its RRSet."
+ "Changing to %"PRIu32"\n",
+ rrset_in_node->ttl);
+ /* Actual change will happen in merge. */
}
}
-
- return 1;
-}
-
-static unsigned long calculate_crc(FILE *f)
-{
- crc_t crc = crc_init();
- /* Get file size. */
- fseek(f, 0L, SEEK_END);
- size_t file_size = ftell(f);
- fseek(f, 0L, SEEK_SET);
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- fread_wrapper = fread_safe_from_file;
-
- const size_t chunk_size = 4096;
- /* read chunks of 4 kB */
- size_t read_bytes = 0;
- /* Prealocate chunk */
- unsigned char *chunk = malloc(sizeof(unsigned char) * chunk_size);
- CHECK_ALLOC_LOG(chunk, 0);
- while ((file_size - read_bytes) > chunk_size) {
- if (!fread_wrapper(chunk,
- sizeof(unsigned char), chunk_size, f)) {
- dbg_zload("zload: calculate_crc: Failed to read "
- "data chunk.\n");
- free(chunk);
- return 0;
- }
- crc = crc_update(crc, chunk,
- sizeof(unsigned char) * chunk_size);
- read_bytes += chunk_size;
+ ret = knot_zone_contents_add_rrset(contents, current_rrset,
+ &node,
+ KNOT_RRSET_DUPL_MERGE);
+ if (ret < 0) {
+ dbg_zp("zp: process_rr: Cannot "
+ "add RRSets.\n");
+ /*!< \todo mixed error codes, has to be changed. */
+ parser->ret = ret;
+ return;
+ } else if (ret > 0) {
+ knot_rrset_deep_free(&current_rrset, 1, 0);
+ }
+ assert(parser->current_zone && node);
+ /* Do mandatory semantic checks. */
+ int sem_fatal_error = 0;
+ ret = sem_check_node_plain(parser->current_zone, node, -1,
+ parser->err_handler, 1,
+ &sem_fatal_error);
+ if (ret != KNOT_EOK) {
+ log_zone_error("Semantic check failed to run (%s)\n",
+ knot_strerror(ret));
+ parser->ret = ret;
+ return;
}
-
- /* Read the rest of the file */
- if (!fread_wrapper(chunk, sizeof(unsigned char), file_size - read_bytes,
- f)) {
- dbg_zload("zload: calculate_crc: Failed to read "
- "data remainder.\n");
- free(chunk);
- return 0;
+ if (sem_fatal_error) {
+ log_zone_error("Semantic check found fatal error "
+ "on line=%"PRIu64"\n",
+ scanner->line_counter);
+ parser->ret = KNOT_EMALF;
+ return;
}
-
- crc = crc_update(crc, chunk,
- sizeof(unsigned char) * (file_size - read_bytes));
- free(chunk);
-
- fseek(f, 0L, SEEK_SET);
- return (unsigned long)crc_finalize(crc);
+
+ parser->last_node = node;
+
+ dbg_zp_verb("zp: process_rr: RRSet %p processed successfully.\n",
+ parser->current_rrset);
+ parser->ret = KNOT_EOK;
}
-int knot_zload_open(zloader_t **dst, const char *filename)
+int knot_zload_open(zloader_t **dst, const char *source, const char *origin,
+ int semantic_checks)
{
- char crc_buf[65];
-
- if (!dst || !filename) {
+ if (!dst || !source || !origin) {
dbg_zload("zload: open: Bad arguments.\n");
return KNOT_EINVAL;
}
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- fread_wrapper = fread_safe_from_file;
-
- *dst = 0;
-
- /* Open file for binary read. */
- FILE *f = fopen(filename, "rb");
- if (knot_unlikely(!f)) {
- int reason = errno;
- dbg_zload("knot_zload_open: failed to open '%s'\n",
- filename);
- switch (reason) {
- case EACCES: return KNOT_EACCES; break;
- case ENOENT: return KNOT_ENOENT; break;
- case ENOMEM: return KNOT_ENOMEM; break;
- default: break;
- }
-
- return KNOT_EFEWDATA; // No such file or directory (POSIX.1)
- }
+ *dst = NULL;
- /* Calculate file size. */
- fseek(f, 0L, SEEK_END);
- size_t file_size = ftell(f);
- fseek(f, 0L, SEEK_SET);
- if (file_size < MAGIC_LENGTH) {
- fclose(f);
- return KNOT_EFEWDATA;
- }
-
- /* Calculate CRC and compare with filename.crc file */
- unsigned long crc_calculated = calculate_crc(f);
-
- /* Read CRC from filename.crc file */
- char *crc_path =
- malloc(sizeof(char) *
- (strlen(filename) + 4 /* strlen(".crc") */ + 1));
- if (knot_unlikely(!crc_path)) {
- fclose(f);
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
- }
- memcpy(crc_path, filename, strlen(filename));
- memcpy(crc_path + strlen(filename), ".crc", 4);
- crc_path[strlen(filename) + 4] = '\0';
-
- int f_crc = open(crc_path, O_RDONLY);
- if (f_crc == -1) {
- /* FIXME: Print strerror_r(errno) in dbg message */
- dbg_zload("knot_zload_open: failed to open '%s'\n",
- crc_path);
- free(crc_path);
- fclose(f);
- return KNOT_ECRC;
- }
-
- ssize_t crc_read_bytes = 0;
- crc_read_bytes = read(f_crc, crc_buf, 64);
- if (crc_read_bytes == -1) {
- /* FIXME: Print strerror_r(errno) in dbg message */
- dbg_zload("knot_zload_open: could not read "
- "CRC from file '%s'\n",
- crc_path);
- free(crc_path);
- close(f_crc);
- fclose(f);
- return KNOT_ECRC;
+ /* Check zone file. */
+ struct stat st;
+ if (stat(source, &st) < 0) {
+ return knot_map_errno(errno);
}
- crc_buf[crc_read_bytes] = '\0';
-
- unsigned long crc_from_file = 0;
- errno = 0;
- crc_from_file = strtoul(crc_buf, (char **) NULL, 10);
- if (errno != 0) {
- /* FIXME: Print strerror_r(errno) in dbg message */
- dbg_zload("knot_zload_open: could not convert "
- "CRC from file '%s'\n",
- crc_path);
- close(f_crc);
- fclose(f);
- free(crc_path);
- return KNOT_ERROR;
- }
-
- /* Free some value and close the CRC file */
- free(crc_path);
- close(f_crc);
- /* Check magic sequence. */
- static const uint8_t MAGIC[MAGIC_LENGTH] = MAGIC_BYTES;
- if (!knot_check_magic(f, MAGIC, MAGIC_LENGTH)) {
- fclose(f);
- dbg_zload("knot_zload_open: magic bytes "
- "in don't match '%*s' "
- "(%s)\n",
- (int)MAGIC_LENGTH, (const char*)MAGIC, filename);
- return KNOT_EMALF; // Illegal byte sequence (POSIX.1, C99)
- }
-
- /* Compare calculated and read CRCs. */
- if (crc_from_file != crc_calculated) {
- dbg_zload("knot_zload_open: CRC failed for "
- "file '%s'\n",
- filename);
- fclose(f);
- return KNOT_ECRC;
- }
-
- /* Read source file length. */
- uint32_t sflen = 0;
- if (!fread_wrapper(&sflen, 1, sizeof(uint32_t), f)) {
- dbg_zload("knot_zload_open: failed to read "
- "sfile length\n");
- fclose(f);
- return KNOT_ERROR;
- }
-
- /* Read source file. */
- char *sfile = malloc(sflen);
- if (!sfile) {
- dbg_zload("knot_zload_open: invalid sfile "
- "length %u\n", sflen);
- fclose(f);
+ /* Create context. */
+ parser_context_t *context = xmalloc(sizeof(parser_context_t));
+
+ /* Create trie for DNAME duplicits. */
+ context->lookup_tree = hattrie_create();
+ if (context->lookup_tree == NULL) {
+ free(context);
return KNOT_ENOMEM;
}
- if (!fread_wrapper(sfile, 1, sflen, f)) {
- dbg_zload("knot_zload_open: failed to read %uB "
- "source file\n",
- sflen);
- free(sfile);
- fclose(f);
+
+ context->origin_from_config =
+ knot_dname_new_from_str(origin, strlen(origin), NULL);
+ assert(context->origin_from_config);
+ knot_dname_to_lower(context->origin_from_config);
+ /* Add first DNAME to lookup tree. */
+ knot_zone_contents_insert_dname_into_table(&context->origin_from_config,
+ context->lookup_tree);
+ context->last_node = knot_node_new(context->origin_from_config,
+ NULL, 0);
+ knot_dname_release(context->origin_from_config);
+ knot_zone_t *zone = knot_zone_new(context->last_node);
+ context->current_zone = knot_zone_get_contents(zone);
+ context->node_rrsigs = NULL;
+ context->ret = KNOT_EOK;
+
+ /* Create file loader. */
+ file_loader_t *loader = file_loader_create(source, origin,
+ KNOT_CLASS_IN, 3600,
+ process_rr, process_error,
+ context);
+ if (loader == NULL) {
+ dbg_zload("Could not create file loader.\n");
+ hattrie_free(context->lookup_tree);
+ free(context);
return KNOT_ERROR;
}
-
+
/* Allocate new loader. */
- zloader_t *zl = malloc(sizeof(zloader_t));
- if (!zl) {
- free(sfile);
- fclose(f);
- return KNOT_ENOMEM;
- }
-
- dbg_zload("knot_zload_open: opened '%s' as fp %p "
- "(source is '%s')\n",
- filename, f, sfile);
- zl->filename = strdup(filename);
- zl->source = sfile;
- zl->fp = f;
+ zloader_t *zl = xmalloc(sizeof(zloader_t));
+
+ zl->source = strdup(source);
+ zl->origin = strdup(origin);
+ zl->file_loader = loader;
+ zl->context = context;
+ zl->semantic_checks = semantic_checks;
*dst = zl;
-
- return KNOT_EOK;
-}
-
-static void cleanup_id_array(knot_dname_t **id_array,
- const uint from, const uint to)
-{
- if (id_array == NULL) {
- dbg_zload("zload: cleanup_id_array: NULL arguments.\n");
- }
- for (uint i = from; i < to; i++) {
- if (id_array[i] != NULL) {
- knot_dname_release(id_array[i]);
- }
- }
-
- free(id_array);
-}
-
-static knot_dname_table_t *create_dname_table_from_array(
- knot_dname_t **array, uint max_id)
-{
- if (array == NULL) {
- /* should I set errno or what ... ? */
- dbg_zload("zload: create_dname_table: No array passed.\n");
- return NULL;
- }
-
- assert(array[0] == NULL);
-
- knot_dname_table_t *ret = knot_dname_table_new();
- CHECK_ALLOC_LOG(ret, NULL);
-
- /* Table will have max_id entries */
- for (uint i = 1; i < max_id; i++) {
- assert(array[i]);
- if (knot_dname_table_add_dname(ret,
- array[i]) != KNOT_EOK) {
-dbg_zload_exec_detail(
- char *name = knot_dname_to_str(array[i]);
- dbg_zload_detail("zload: create_dname_table: "
- "Could not add dname: %s.\n",
- name);
- free(name);
-);
- dbg_zload("zload: create_dname_table: "
- "Could not add dname.\n");
- knot_dname_table_deep_free(&ret);
- return NULL;
- }
- }
-
- dbg_zload("zload: create_dname_table: Table loaded.\n");
- return ret;
-}
-
-static knot_dname_t **create_dname_array(FILE *f, uint max_id)
-{
- if (f == NULL) {
- dbg_zload("zload: create_dname_array: Wrong arguments.\n");
- return NULL;
- }
-
- knot_dname_t **array =
- malloc(sizeof(knot_dname_t *) * ( max_id + 1));
- if (array == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
-
- memset(array, 0, sizeof(knot_dname_t *) * (max_id + 1));
-
- for (uint i = 0; i < max_id - 1; i++) {
- knot_dname_t *read_dname = read_dname_with_id(f, 1);
- if (read_dname == NULL) {
- dbg_zload("zload: create_dname_array: "
- "Cannot read dname.\n" );
- cleanup_id_array(array, 0, i);
- return NULL;
- }
-
- if (read_dname->id < max_id) {
- /* Create new node from dname. */
- read_dname->node = knot_node_new(read_dname, NULL, 0);
- if (read_dname->node == NULL) {
- dbg_zload("zload: create_dname_array: "
- "Cannot create new node "
- "from dname.\n");
- /* Release read dname. */
- knot_dname_release(read_dname);
- cleanup_id_array(array, 0, i);
- return NULL;
- }
-
- /* Store reference to dname in array. */
- array[read_dname->id] = read_dname;
- } else {
- /* Release read dname. */
- dbg_zload("zload: create_dname_array: "
- "dname id is out of range.\n");
- knot_dname_release(read_dname);
- cleanup_id_array(array, 0, i);
- return NULL;
- }
-
+ /* Log all information for now - possibly more config options. */
+ zl->err_handler = handler_new(1, 1, 1, 1, 1);
+ if (zl->err_handler == NULL) {
+ /* Not a reason to stop. */
+ log_zone_warning("Could not create semantic checks handler. "
+ "Semantic check skipped for zone %s\n",
+ origin);
}
- dbg_zload("zload: create_dname_array: Array created.\n");
- return array;
+ context->err_handler = zl->err_handler;
+
+ return KNOT_EOK;
}
knot_zone_t *knot_zload_load(zloader_t *loader)
@@ -1209,240 +660,72 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
dbg_zload("zload: load: NULL loader!\n");
return NULL;
}
-
- FILE *f = loader->fp;
-
- knot_node_t *tmp_node;
-
- uint32_t node_count;
- uint32_t nsec3_node_count;
- uint32_t auth_node_count;
- int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
- fread_wrapper = fread_safe_from_file;
-
- if (!fread_wrapper(&node_count, sizeof(node_count), 1, f)) {
- dbg_zload("zload: load: Cannot read node count!\n");
- return NULL;
+ parser_context_t *c = loader->context;
+ assert(c);
+ file_loader_process(loader->file_loader);
+ if (c->last_node && c->node_rrsigs) {
+ process_rrsigs_in_node(c, c->current_zone, c->last_node);
}
- if (!fread_wrapper(&nsec3_node_count, sizeof(nsec3_node_count), 1, f)) {
- dbg_zload("zload: load: Cannot read NSEC3 node count!\n");
- return NULL;
- }
- if (!fread_wrapper(&auth_node_count,
- sizeof(auth_node_count), 1, f)) {
- dbg_zload("zload: load: Cannot read authoritative "
- "node count!\n");
+ if (c->ret != KNOT_EOK) {
+ log_zone_error("Zone could not be loaded (%s).\n",
+ knot_strerror(c->ret));
+ rrset_list_delete(&c->node_rrsigs);
+ knot_zone_t *zone_to_free = c->current_zone->zone;
+ knot_zone_deep_free(&zone_to_free);
return NULL;
}
- dbg_zload_verb("zload: load: Authoritative nodes: %u.\n",
- auth_node_count);
- dbg_zload_verb("zload: load: :oading %u nodes.\n", node_count);
-
- uint32_t total_dnames = 0;
- /* First, read number of dnames in dname table. */
- if (!fread_wrapper(&total_dnames, sizeof(total_dnames), 1, f)) {
- return NULL;
- }
-
- dbg_zload_verb("zload: load: Total dname count: %d.\n", total_dnames);
-
- /* Create id array. */
- knot_dname_t **id_array = create_dname_array(f, total_dnames);
- if (id_array == NULL) {
- dbg_zload("zload: load: Cannot create ID array.\n");
+ if (loader->file_loader->scanner->error_counter > 0) {
+ log_zone_error("Zone could not be loaded due to %"PRIu64" errors"
+ " encountered.\n",
+ loader->file_loader->scanner->error_counter);
+ rrset_list_delete(&c->node_rrsigs);
+ knot_zone_t *zone_to_free = c->current_zone->zone;
+ knot_zone_deep_free(&zone_to_free);
return NULL;
}
-
- knot_dname_table_t *dname_table =
- create_dname_table_from_array(id_array, total_dnames);
- if (dname_table == NULL) {
- dbg_zload("zload: load: Cannot create ID array.\n");
- cleanup_id_array(id_array, 1, total_dnames);
- free(dname_table);
- return NULL;
- }
-
- knot_node_t *apex = knot_load_node(f, id_array);
-
- if (!apex) {
- dbg_zload("zone: Could not load apex node (in %s)\n",
- loader->filename);
- cleanup_id_array(id_array, 1,
- node_count + nsec3_node_count + 1);
- free(dname_table);
- return NULL;
- }
-
- dbg_zload_verb("zload: load: Apex node loaded: %p.\n", apex);
-
- knot_zone_t *zone = knot_zone_new(apex, auth_node_count, 0);
- if (zone == NULL) {
- cleanup_id_array(id_array, 1,
- node_count + nsec3_node_count + 1);
- dbg_zload("zload: load: Failed to create new "
- "zone from apex!\n");
- knot_node_free(&apex);
- free(dname_table);
+
+ if (knot_zone_contents_apex(c->current_zone) == NULL ||
+ knot_node_rrset(knot_zone_contents_apex(c->current_zone), KNOT_RRTYPE_SOA) == NULL) {
+ log_zone_error("No SOA record in the zone file.\n");
+ rrset_list_delete(&c->node_rrsigs);
+ knot_zone_t *zone_to_free = c->current_zone->zone;
+ knot_zone_deep_free(&zone_to_free);
return NULL;
}
-
- knot_zone_contents_t *contents = knot_zone_get_contents(zone);
- assert(contents);
-
- /* Assign dname table to the new zone. */
- contents->dname_table = dname_table;
-
- knot_node_set_previous(apex, NULL);
- knot_node_t *last_node = 0;
- last_node = apex;
-
- int ret = 0;
-
- for (uint i = 1; i < node_count; i++) {
- tmp_node = knot_load_node(f, id_array);
- if (tmp_node != NULL) {
- dbg_zload_detail("zload: load: Adding node owned by: "
- "%s\n.",
- knot_dname_to_str(tmp_node->owner));
- if ((ret = knot_zone_contents_add_node(contents,
- tmp_node,
- 0, 0, 0)) != 0) {
- cleanup_id_array(id_array, 1,
- node_count +
- nsec3_node_count + 1);
- knot_zone_deep_free(&zone, 0);
- dbg_zload("zload: load: Failed to add node "
- "to zone: %s.\n", knot_strerror(ret));
- return NULL;
- }
-
- if (knot_dname_is_wildcard(tmp_node->owner)) {
- find_and_set_wildcard_child(contents,
- tmp_node, 0);
- }
-
- knot_node_set_previous(tmp_node, last_node);
-
- if (tmp_node->rrset_count &&
- (knot_node_is_deleg_point(tmp_node) ||
- !knot_node_is_non_auth(tmp_node))) {
- last_node = tmp_node;
- }
-
- } else {
- dbg_zload("zload: load: Node error (in %s).\n",
- loader->filename);
- knot_zone_deep_free(&zone, 0);
- cleanup_id_array(id_array, node_count + 1,
- nsec3_node_count + 1);
- return NULL;
- }
- }
-
- assert(knot_node_previous(knot_zone_contents_apex(contents)) == NULL);
-
- knot_node_set_previous(knot_zone_contents_get_apex(contents),
- last_node);
-
- dbg_zload_detail("zload: load: Loading %u nsec3 nodes\n",
- nsec3_node_count);
-
- knot_node_t *nsec3_first = NULL;
-
- if (nsec3_node_count > 0) {
- nsec3_first = knot_load_node(f, id_array);
-
- assert(nsec3_first != NULL);
-
- if ((ret = knot_zone_contents_add_nsec3_node(contents,
- nsec3_first,
- 0, 0, 0)) != 0) {
- dbg_zload("zload: load: "
- "cannot add first nsec3 node, "
- "exiting: %s.\n", knot_strerror(ret));
- knot_zone_deep_free(&zone, 0);
- cleanup_id_array(id_array, node_count + 1,
- nsec3_node_count + 1);
- return NULL;
- }
-
- knot_node_set_previous(nsec3_first, NULL);
- last_node = nsec3_first;
- }
-
- for (uint i = 1; i < nsec3_node_count; i++) {
- tmp_node = knot_load_node(f, id_array);
-
- if (tmp_node != NULL) {
- if ((ret = knot_zone_contents_add_nsec3_node(contents,
- tmp_node, 0, 0, 0)) != 0) {
- dbg_zload("zload: load: Cannot add "
- "NSEC3 node: %s.\n",
- knot_strerror(ret));
- knot_zone_deep_free(&zone, 0);
- cleanup_id_array(id_array, node_count + 1,
- nsec3_node_count + 1);
- return NULL;
- }
-
- knot_node_set_previous(tmp_node, last_node);
-
- last_node = tmp_node;
- } else {
- fprintf(stderr, "zone: Node error (in %s).\n",
- loader->filename);
- knot_zone_deep_free(&zone, 0);
- cleanup_id_array(id_array, node_count + 1,
- nsec3_node_count + 1);
- return NULL;
- }
- }
-
- if (nsec3_node_count) {
- assert(knot_node_previous(nsec3_first) == NULL);
- knot_node_set_previous(nsec3_first, last_node);
- }
-
- /* ID array is now useless */
- for (uint i = 1; i < total_dnames; i++) {
- /* Added to table, may discard now. */
- knot_dname_release(id_array[i]);
- }
- free(id_array);
-
- dbg_zload("zload: load: Zone loaded, returning: %p,\n", zone);
- return zone;
-}
-
-int knot_zload_needs_update(zloader_t *loader)
-{
- if (!loader) {
- return 1;
- }
- /* Check if the source still exists. */
- struct stat st_src;
- if (stat(loader->source, &st_src) != 0) {
- return 1;
- }
-
- /* Check if the compiled file still exists. */
- struct stat st_bin;
- if (stat(loader->filename, &st_bin) != 0) {
- return 1;
- }
+ knot_node_t *first_nsec3_node = NULL;
+ knot_node_t *last_nsec3_node = NULL;
+ rrset_list_delete(&c->node_rrsigs);
+ knot_zone_contents_adjust(c->current_zone, &first_nsec3_node,
+ &last_nsec3_node, 0);
-
- /* Compare the mtime of the source and file. */
- /*! \todo Inspect types on Linux. */
- if (timet_cmp(st_bin.st_mtime, st_src.st_mtime) < 0) {
- return 1;
+ if (loader->semantic_checks) {
+ int check_level = 1;
+ const knot_rrset_t *soa_rr =
+ knot_node_rrset(knot_zone_contents_apex(c->current_zone),
+ KNOT_RRTYPE_SOA);
+ assert(soa_rr); // In this point, SOA has to exist
+ const knot_rrset_t *nsec3param_rr =
+ knot_node_rrset(knot_zone_contents_apex(c->current_zone),
+ KNOT_RRTYPE_NSEC3PARAM);
+ if (soa_rr->rrsigs && nsec3param_rr == NULL) {
+ /* Set check level to DNSSEC. */
+ check_level = 2;
+ } else if (soa_rr->rrsigs && nsec3param_rr) {
+ check_level = 3;
+ }
+ zone_do_sem_checks(c->current_zone, check_level,
+ loader->err_handler, first_nsec3_node,
+ last_nsec3_node);
+ char *zname = knot_dname_to_str(knot_rrset_owner(soa_rr));
+ log_zone_info("Semantic checks completed for zone=%s\n", zname);
+ free(zname);
}
-
- return 0;
+
+ return c->current_zone->zone;
}
void knot_zload_close(zloader_t *loader)
@@ -1450,37 +733,14 @@ void knot_zload_close(zloader_t *loader)
if (!loader) {
return;
}
+
+ hattrie_free(loader->context->lookup_tree);
+
+ file_loader_free(loader->file_loader);
- free(loader->filename);
free(loader->source);
- fclose(loader->fp);
+ free(loader->origin);
+ free(loader->context);
+ free(loader->err_handler);
free(loader);
}
-
-int knot_zload_rrset_deserialize(knot_rrset_t **rrset,
- uint8_t *stream, size_t *size)
-{
- if (stream == NULL || size == 0) {
- dbg_zload("zload: rrset_deserialize: Bad arguments.\n");
- return KNOT_EINVAL;
- }
-
- load_stream_t data;
- data.stream = stream;
- data.stream_remaining = *size;
- data.stream_size = *size;
-
- knot_rrset_t *ret = knot_load_rrset(&data, NULL, 0);
- if (ret == NULL) {
- dbg_zload("zload: rrset_deserialize: Cannot load RRSet.\n");
- return KNOT_EMALF;
- }
-
- *size = data.stream_remaining;
- *rrset = ret;
-
- dbg_zload_detail("zload: rrset_deserialize: RRSet deserialized "
- "successfully.\n");
- return KNOT_EOK;
-}
-
diff --git a/src/knot/zone/zone-load.h b/src/knot/zone/zone-load.h
index 837d5f2..71284a2 100644
--- a/src/knot/zone/zone-load.h
+++ b/src/knot/zone/zone-load.h
@@ -16,11 +16,11 @@
/*!
* \file zone-load.h
*
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
* \author Jan Kadlec <jan.kadlec@nic.cz>
*
- * \brief Loader of previously parsed zone
+ * \brief Zone loading
*
- * \addtogroup zone-load-dump
* @{
*/
@@ -30,15 +30,45 @@
#include <stdio.h>
#include "libknot/zone/zone.h"
+#include "knot/zone/semantic-check.h"
+#include "zscanner/file_loader.h"
+
+/* TODO this structure is highly redundant, remove. Maybe use oh-so-great BIRD lists. */
+/*!
+ * \brief One-purpose linked list holding pointers to RRSets.
+ */
+struct rrset_list {
+ knot_rrset_t *data; /*!< List data. */
+ struct rrset_list *next; /*!< Next node. */
+};
+
+typedef struct rrset_list rrset_list_t;
+
+
+struct parser_context {
+ rrset_list_t *node_rrsigs;
+ knot_zone_contents_t *current_zone;
+ knot_rrset_t *current_rrset;
+ knot_dname_t *origin_from_config;
+ knot_node_t *last_node;
+ err_handler_t *err_handler;
+ hattrie_t *lookup_tree;
+ int ret;
+};
+
+typedef struct parser_context parser_context_t;
/*!
* \brief Zone loader structure.
*/
typedef struct zloader_t
{
- char *filename; /*!< Compiled zone filename. */
char *source; /*!< Zone source file. */
- FILE *fp; /*!< Open filepointer to compiled zone. */
+ char *origin; /*!< Zone's origin string. */
+ int semantic_checks; /*!< Wanted level of semantic checks. */
+ err_handler_t *err_handler; /*!< Semantic checks error handler. */
+ file_loader_t *file_loader; /*!< Scanner's file loader. */
+ parser_context_t *context; /*!< Loader context. */
} zloader_t;
@@ -51,7 +81,8 @@ typedef struct zloader_t
* \retval Initialized loader on success.
* \retval NULL on error.
*/
-int knot_zload_open(zloader_t **loader, const char *filename);
+int knot_zload_open(zloader_t **loader, const char *source, const char *origin,
+ int semantic_checks);
/*!
* \brief Loads zone from a compiled and serialized zone file.
@@ -64,40 +95,13 @@ int knot_zload_open(zloader_t **loader, const char *filename);
knot_zone_t *knot_zload_load(zloader_t *loader);
/*!
- * \brief Checks whether the compiled zone needs a recompilation.
- *
- * \param loader Zone loader instance.
- *
- * \retval 1 is if needs to be recompiled.
- * \retval 0 if it is up to date.
- */
-int knot_zload_needs_update(zloader_t *loader);
-
-
-/*!
* \brief Free zone loader.
*
* \param loader Zone loader instance.
*/
void knot_zload_close(zloader_t *loader);
-/*!
- * \brief Loads RRSet serialized by knot_zdump_rrset_serialize().
- *
- * \param stream Stream containing serialized RRSet.
- * \param size Size of stream. This variable will contain remaining length of
- * stream, once the function has ended.
- * \param rrset Place for created RRSet.
- *
- * \note If RRSet contains RRSIGs, their owners are not copies, but only links
- * to the owner of RRSet. All RDATA dnames are copied.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_EBADAG on wrong arguments.
- * \retval KNOT_EMALF when stream is malformed.
- */
-int knot_zload_rrset_deserialize(knot_rrset_t **rrset,
- uint8_t *stream, size_t *size);
+void process_error(const scanner_t *scanner);
#endif /* _KNOTD_ZONELOAD_H_ */
diff --git a/src/tests/libknot/libknot/zonedb_tests.c b/src/libknot/binary.c
index 7b45587..aba3560 100644
--- a/src/tests/libknot/libknot/zonedb_tests.c
+++ b/src/libknot/binary.c
@@ -14,31 +14,43 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "tests/libknot/libknot/zonedb_tests.h"
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include "binary.h"
+#include "common/base64.h"
+#include "common/errcode.h"
-static int zonedb_tests_count(int argc, char *argv[]);
-static int zonedb_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api zonedb_tests_api = {
- "Zone database", //! Unit name
- &zonedb_tests_count, //! Count scheduled tests
- &zonedb_tests_run //! Run scheduled tests
-};
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int zonedb_tests_count(int argc, char *argv[])
+int knot_binary_from_base64(const char *base64, knot_binary_t *binary)
{
- return 0;
+ if (!binary)
+ return KNOT_EINVAL;
+
+ uint8_t *data;
+ int32_t size;
+
+ size = base64_decode_alloc((uint8_t *)base64, strlen(base64), &data);
+ if (size < 0) {
+ return size;
+ }
+
+ binary->data = data;
+ binary->size = size;
+
+ return KNOT_EOK;
}
-/*! Run all scheduled tests for given parameters.
- */
-static int zonedb_tests_run(int argc, char *argv[])
+int knot_binary_free(knot_binary_t *binary)
{
- return 0;
+ if (!binary)
+ return KNOT_EINVAL;
+
+ if (binary->data) {
+ free(binary->data);
+ binary->data = NULL;
+ binary->size = 0;
+ }
+
+ return KNOT_EOK;
}
diff --git a/src/libknot/binary.h b/src/libknot/binary.h
new file mode 100644
index 0000000..34d4c19
--- /dev/null
+++ b/src/libknot/binary.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2011 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 includes.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief Structures for binary data handling.
+ *
+ * \addtogroup libknot
+ * @{
+ */
+
+#ifndef _KNOT_BINARY_H_
+#define _KNOT_BINARY_H_
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+
+struct knot_binary {
+ uint8_t *data;
+ size_t size;
+};
+
+typedef struct knot_binary knot_binary_t;
+
+/*!
+ * \brief Initialize knot_binary_t structure from Base64 encoded string.
+ *
+ * \param base64 Base64 encoded input data.
+ * \param binary Pointer to structure to write the result into.
+ * \return Error code, KNOT_EOK in case of success.
+ */
+int knot_binary_from_base64(const char *base64, knot_binary_t *binary);
+
+/*!
+ * \brief Free content of knot_binary_t structure.
+ *
+ * \param binary Pointer to the structure.
+ * \return Error code, KNOT_EOK in case of success.
+ */
+int knot_binary_free(knot_binary_t *binary);
+
+#endif // _KNOT_BINARY_H
+
+/*! @} */
diff --git a/src/libknot/common.h b/src/libknot/common.h
index 0bff97e..75acc7b 100644
--- a/src/libknot/common.h
+++ b/src/libknot/common.h
@@ -1,5 +1,5 @@
/*!
- * \file common.h
+ * \file libknot/common.h
*
* \author Lubos Slovak <lubos.slovak@nic.cz>
*
@@ -24,12 +24,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <config.h>
#include "common/errcode.h"
-
-#ifdef HAVE_LIBLDNS
-#define TEST_WITH_LDNS
-#endif
+#include "common/mempattern.h"
#ifndef _KNOT_COMMON_H_
#define _KNOT_COMMON_H_
@@ -42,28 +38,17 @@ typedef unsigned int uint; /*!< \brief Unsigned. */
#define UINT_DEFINED
#endif
-/*! \brief If defined, zone structures will use hash table for lookup. */
-#define USE_HASH_TABLE
-
/*! \brief Eliminate compiler warning with unused parameters. */
#define UNUSED(param) (void)(param)
+#ifndef MIN
/*! \brief Type-safe minimum macro. */
#define MIN(a, b) \
- ({ typeof (a) _a = (a); typeof (b) _b = (b); _a < _b ? _a : _b; })
+ ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a < _b ? _a : _b; })
/*! \brief Type-safe maximum macro. */
#define MAX(a, b) \
- ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })
-
-/* Optimisation macros. */
-#ifndef knot_likely
-/*! \brief Optimize for x to be true value. */
-#define knot_likely(x) __builtin_expect((x),1)
-#endif
-#ifndef knot_unlikely
-/*! \brief Optimize for x to be false value. */
-#define knot_unlikely(x) __builtin_expect((x),0)
+ ({ __typeof__ (a) _a = (a); __typeof__ (b) _b = (b); _a > _b ? _a : _b; })
#endif
/* Optimisation macros. */
@@ -78,8 +63,9 @@ typedef unsigned int uint; /*!< \brief Unsigned. */
/*! \todo Refactor theese. We should have an allocator function handling this.*/
#ifndef ERR_ALLOC_FAILED
-#define ERR_ALLOC_FAILED fprintf(stderr, "Allocation failed at %s:%d (%s ver.%s)\n", \
- __FILE__, __LINE__, KNOT_NAME, KNOT_VER)
+#define ERR_ALLOC_FAILED fprintf(stderr, \
+ "Allocation failed at %s:%d (%s ver.%s)\n", \
+ __FILE__, __LINE__, KNOT_NAME, KNOT_VER)
#endif
#ifndef CHECK_ALLOC_LOG
diff --git a/src/libknot/consts.c b/src/libknot/consts.c
new file mode 100644
index 0000000..5471d76
--- /dev/null
+++ b/src/libknot/consts.c
@@ -0,0 +1,108 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <libknot/consts.h>
+
+knot_lookup_table_t knot_opcode_names[] = {
+ { KNOT_OPCODE_QUERY, "QUERY" },
+ { KNOT_OPCODE_IQUERY, "IQUERY" },
+ { KNOT_OPCODE_STATUS, "STATUS" },
+ { KNOT_OPCODE_NOTIFY, "NOTIFY" },
+ { KNOT_OPCODE_UPDATE, "UPDATE" },
+ { 0, NULL }
+};
+
+knot_lookup_table_t knot_rcode_names[] = {
+ { KNOT_RCODE_NOERROR, "NOERROR" },
+ { KNOT_RCODE_FORMERR, "FORMERR" },
+ { KNOT_RCODE_SERVFAIL, "SERVFAIL" },
+ { KNOT_RCODE_NXDOMAIN, "NXDOMAIN" },
+ { KNOT_RCODE_NOTIMPL, "NOTIMPL" },
+ { KNOT_RCODE_REFUSED, "REFUSED" },
+ { KNOT_RCODE_YXDOMAIN, "YXDOMAIN" },
+ { KNOT_RCODE_YXRRSET, "YXRRSET" },
+ { KNOT_RCODE_NXRRSET, "NXRRSET" },
+ { KNOT_RCODE_NOTAUTH, "NOTAUTH" },
+ { KNOT_RCODE_NOTZONE, "NOTZONE" },
+ { KNOT_RCODE_BADSIG, "BADSIG" },
+ { KNOT_RCODE_BADKEY, "BADKEY" },
+ { KNOT_RCODE_BADTIME, "BADTIME" },
+ { KNOT_RCODE_BADMODE, "BADMODE" },
+ { KNOT_RCODE_BADNAME, "BADNAME" },
+ { KNOT_RCODE_BADALG, "BADALG" },
+ { KNOT_RCODE_BADTRUNC, "BADTRUNC" },
+ { 0, NULL }
+};
+
+knot_lookup_table_t knot_tsig_alg_names[] = {
+ { KNOT_TSIG_ALG_HMAC_MD5, "hmac-md5" },
+ { KNOT_TSIG_ALG_HMAC_SHA1, "hmac-sha1" },
+ { KNOT_TSIG_ALG_HMAC_SHA224, "hmac-sha224" },
+ { KNOT_TSIG_ALG_HMAC_SHA256, "hmac-sha256" },
+ { KNOT_TSIG_ALG_HMAC_SHA384, "hmac-sha384" },
+ { KNOT_TSIG_ALG_HMAC_SHA512, "hmac-sha512" },
+ { KNOT_TSIG_ALG_NULL, NULL }
+};
+
+knot_lookup_table_t knot_tsig_alg_domain_names[] = {
+ { KNOT_TSIG_ALG_GSS_TSIG, "gss-tsig." },
+ { KNOT_TSIG_ALG_HMAC_MD5, "hmac-md5.sig-alg.reg.int." },
+ { KNOT_TSIG_ALG_HMAC_SHA1, "hmac-sha1." },
+ { KNOT_TSIG_ALG_HMAC_SHA224, "hmac-sha224." },
+ { KNOT_TSIG_ALG_HMAC_SHA256, "hmac-sha256." },
+ { KNOT_TSIG_ALG_HMAC_SHA384, "hmac-sha384." },
+ { KNOT_TSIG_ALG_HMAC_SHA512, "hmac-sha512." },
+ { KNOT_TSIG_ALG_NULL, NULL }
+};
+
+size_t knot_tsig_digest_length(const uint8_t algorithm)
+{
+ switch (algorithm) {
+ case KNOT_TSIG_ALG_GSS_TSIG:
+ return KNOT_TSIG_ALG_DIG_LENGTH_GSS_TSIG;
+ case KNOT_TSIG_ALG_HMAC_MD5:
+ return KNOT_TSIG_ALG_DIG_LENGTH_HMAC_MD5;
+ case KNOT_TSIG_ALG_HMAC_SHA1:
+ return KNOT_TSIG_ALG_DIG_LENGTH_SHA1;
+ case KNOT_TSIG_ALG_HMAC_SHA224:
+ return KNOT_TSIG_ALG_DIG_LENGTH_SHA224;
+ case KNOT_TSIG_ALG_HMAC_SHA256:
+ return KNOT_TSIG_ALG_DIG_LENGTH_SHA256;
+ case KNOT_TSIG_ALG_HMAC_SHA384:
+ return KNOT_TSIG_ALG_DIG_LENGTH_SHA384;
+ case KNOT_TSIG_ALG_HMAC_SHA512:
+ return KNOT_TSIG_ALG_DIG_LENGTH_SHA512;
+ default:
+ return 0;
+ }
+}
+
+size_t knot_ds_digest_length(const uint8_t algorithm)
+{
+ switch (algorithm) {
+ case KNOT_DS_ALG_SHA1:
+ return KNOT_DS_DIGEST_LEN_SHA1;
+ case KNOT_DS_ALG_SHA256:
+ return KNOT_DS_DIGEST_LEN_SHA256;
+ case KNOT_DS_ALG_GOST:
+ return KNOT_DS_DIGEST_LEN_GOST;
+ case KNOT_DS_ALG_SHA384:
+ return KNOT_DS_DIGEST_LEN_SHA384;
+ default:
+ return 0;
+ }
+}
diff --git a/src/libknot/consts.h b/src/libknot/consts.h
index 3431bc3..e2b3a82 100644
--- a/src/libknot/consts.h
+++ b/src/libknot/consts.h
@@ -28,27 +28,64 @@
#define _KNOT_CONSTS_H_
#include <stdint.h>
-#include "util/descriptor.h"
-
-/*
- * OPCODEs
- */
-typedef enum knot_opcode {
- KNOT_OPCODE_QUERY = 0, /* a standard query (QUERY) */
- KNOT_OPCODE_IQUERY = 1, /* an inverse query (IQUERY) */
- KNOT_OPCODE_STATUS = 2, /* a server status request (STATUS) */
- KNOT_OPCODE_NOTIFY = 4, /* NOTIFY */
- KNOT_OPCODE_UPDATE = 5, /* Dynamic update */
- KNOT_OPCODE_OFFSET = 14
+
+#include "libknot/util/utils.h"
+
+/*!
+ * \brief Basic limits for domain names (RFC 1035).
+ */
+typedef enum {
+ KNOT_MAX_DNAME_LENGTH = 255, /*!< 1-byte maximum. */
+ KNOT_MAX_DNAME_LABELS = 127 /*!< 1-char labels. */
+} knot_const_t;
+
+/*!
+ * \brief DNS operation codes (OPCODEs).
+ *
+ * http://www.iana.org/assignments/dns-parameters/dns-parameters.xml
+ */
+typedef enum {
+ KNOT_OPCODE_QUERY = 0, /*!< Standard query. */
+ KNOT_OPCODE_IQUERY = 1, /*!< Inverse query. */
+ KNOT_OPCODE_STATUS = 2, /*!< Server status request. */
+ KNOT_OPCODE_NOTIFY = 4, /*!< Notify message. */
+ KNOT_OPCODE_UPDATE = 5 /*!< Dynamic update. */
} knot_opcode_t;
/*!
- * \brief Query types (internal use only).
+ * \brief DNS reply codes (RCODEs).
+ *
+ * http://www.iana.org/assignments/dns-parameters/dns-parameters.xml
+ */
+typedef enum {
+ KNOT_RCODE_NOERROR = 0, /*!< No error. */
+ KNOT_RCODE_FORMERR = 1, /*!< Format error. */
+ KNOT_RCODE_SERVFAIL = 2, /*!< Server failure. */
+ KNOT_RCODE_NXDOMAIN = 3, /*!< Non-existend domain. */
+ KNOT_RCODE_NOTIMPL = 4, /*!< Not implemented. */
+ KNOT_RCODE_REFUSED = 5, /*!< Refused. */
+ KNOT_RCODE_YXDOMAIN = 6, /*!< Name should not exist. */
+ KNOT_RCODE_YXRRSET = 7, /*!< RR set should not exist. */
+ KNOT_RCODE_NXRRSET = 8, /*!< RR set does not exist. */
+ KNOT_RCODE_NOTAUTH = 9, /*!< Server not authoritative. */
+ KNOT_RCODE_NOTZONE = 10, /*!< Name is not inside zone. */
+ KNOT_RCODE_BADSIG = 16, /*!< TSIG signature failed. */
+ KNOT_RCODE_BADKEY = 17, /*!< Key is not supported. */
+ KNOT_RCODE_BADTIME = 18, /*!< Signature out of time window. */
+ KNOT_RCODE_BADMODE = 19, /*!< Bad TKEY mode. */
+ KNOT_RCODE_BADNAME = 20, /*!< Duplicate key name. */
+ KNOT_RCODE_BADALG = 21, /*!< Algorithm not supported. */
+ KNOT_RCODE_BADTRUNC = 22 /*!< Bad truncation. */
+} knot_rcode_t;
+
+/*!
+ * \brief DNS query types (internal use only).
*
* This type encompasses the different query types distinguished by both the
* OPCODE and the QTYPE.
*/
-typedef enum knot_packet_type {
+typedef enum {
+ KNOT_QUERY_INVALID, /*!< Invalid query. */
KNOT_QUERY_NORMAL, /*!< Normal query. */
KNOT_QUERY_AXFR, /*!< Request for AXFR transfer. */
KNOT_QUERY_IXFR, /*!< Request for IXFR transfer. */
@@ -61,48 +98,117 @@ typedef enum knot_packet_type {
KNOT_RESPONSE_UPDATE /*!< Dynamic update response. */
} knot_packet_type_t;
-/*
- * RCODEs
- */
-typedef enum knot_rcode {
- KNOT_RCODE_NOERROR = 0, /* No error condition */
- KNOT_RCODE_FORMERR = 1, /* Format error */
- KNOT_RCODE_SERVFAIL = 2, /* Server failure */
- KNOT_RCODE_NXDOMAIN = 3, /* Name Error */
- KNOT_RCODE_NOTIMPL = 4, /* Not implemented */
- KNOT_RCODE_REFUSED = 5, /* Refused */
- KNOT_RCODE_YXDOMAIN = 6, /* name should not exist */
- KNOT_RCODE_YXRRSET = 7, /* rrset should not exist */
- KNOT_RCODE_NXRRSET = 8, /* rrset does not exist */
- KNOT_RCODE_NOTAUTH = 9, /* server not authoritative */
- KNOT_RCODE_NOTZONE = 10, /* name not inside zone */
-} knot_rcode_t;
+/*!
+ * \brief TSIG algorithm numbers.
+ *
+ * These constants were taken from the Bind file key format (dnssec-keygen).
+ */
+typedef enum {
+ KNOT_TSIG_ALG_NULL = 0,
+ KNOT_TSIG_ALG_GSS_TSIG = 128,
+ KNOT_TSIG_ALG_HMAC_MD5 = 157,
+ KNOT_TSIG_ALG_HMAC_SHA1 = 161,
+ KNOT_TSIG_ALG_HMAC_SHA224 = 162,
+ KNOT_TSIG_ALG_HMAC_SHA256 = 163,
+ KNOT_TSIG_ALG_HMAC_SHA384 = 164,
+ KNOT_TSIG_ALG_HMAC_SHA512 = 165
+} knot_tsig_algorithm_t;
-typedef enum knot_tsig_rcode {
- KNOT_TSIG_RCODE_BADSIG = 16,
- KNOT_TSIG_RCODE_BADKEY = 17,
- KNOT_TSIG_RCODE_BADTIME = 18
-} knot_tsig_rcode_t;
-
-/*
- * CLASSes
- */
-//typedef enum knot_class {
-// KNOT_CLASS_IN = 1, /* Class IN */
-// KNOT_CLASS_CS = 2, /* Class CS */
-// KNOT_CLASS_CH = 3, /* Class CHAOS */
-// KNOT_CLASS_HS = 4, /* Class HS */
-// KNOT_CLASS_NONE = 254, /* Class NONE rfc2136 */
-// KNOT_CLASS_ANY = 255 /* Class ANY */
-//} knot_class_t;
-
-/*
- * Other
- */
-typedef enum knot_const {
- KNOT_MAX_DNAME_LENGTH = 255,
- KNOT_MAX_DNAME_LABELS = 127 // 1-char labels
-} knot_const_t;
+/*!
+ * \brief Lengths of TSIG algorithm digests.
+ */
+typedef enum {
+ KNOT_TSIG_ALG_DIG_LENGTH_GSS_TSIG = 0,
+ KNOT_TSIG_ALG_DIG_LENGTH_HMAC_MD5 = 16,
+ KNOT_TSIG_ALG_DIG_LENGTH_SHA1 = 20,
+ KNOT_TSIG_ALG_DIG_LENGTH_SHA224 = 28,
+ KNOT_TSIG_ALG_DIG_LENGTH_SHA256 = 32,
+ KNOT_TSIG_ALG_DIG_LENGTH_SHA384 = 48,
+ KNOT_TSIG_ALG_DIG_LENGTH_SHA512 = 64
+} knot_tsig_algorithm_digest_length_t;
+
+/*!
+ * \brief DNSSEC algorithm numbers.
+ *
+ * http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml
+ */
+typedef enum {
+ KNOT_DNSSEC_ALG_RSAMD5 = 1,
+ KNOT_DNSSEC_ALG_DH = 2,
+ KNOT_DNSSEC_ALG_DSA = 3,
+
+ KNOT_DNSSEC_ALG_RSASHA1 = 5,
+ KNOT_DNSSEC_ALG_DSA_NSEC3_SHA1 = 6,
+ KNOT_DNSSEC_ALG_RSASHA1_NSEC3_SHA1 = 7,
+ KNOT_DNSSEC_ALG_RSASHA256 = 8,
+
+ KNOT_DNSSEC_ALG_RSASHA512 = 10,
+
+ KNOT_DNSSEC_ALG_ECC_GOST = 12,
+ KNOT_DNSSEC_ALG_ECDSAP256SHA256 = 13,
+ KNOT_DNSSEC_ALG_ECDSAP384SHA384 = 14
+} knot_dnssec_algorithm_t;
+
+/*!
+ * \brief DS digest lengths.
+ */
+enum knot_ds_algorithm_len
+{
+ KNOT_DS_DIGEST_LEN_SHA1 = 20, /*!< RFC 3658 */
+ KNOT_DS_DIGEST_LEN_SHA256 = 32, /*!< RFC 4509 */
+ KNOT_DS_DIGEST_LEN_GOST = 32, /*!< RFC 5933 */
+ KNOT_DS_DIGEST_LEN_SHA384 = 48 /*!< RFC 6605 */
+};
+
+/*!
+ * \brief Constants for DNSSEC algorithm types.
+ *
+ * Source: http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xml
+ */
+typedef enum {
+ KNOT_DS_ALG_SHA1 = 1,
+ KNOT_DS_ALG_SHA256 = 2,
+ KNOT_DS_ALG_GOST = 3,
+ KNOT_DS_ALG_SHA384 = 4
+} knot_ds_algorithm_t;
+
+/*!
+ * \brief DNS operation code names.
+ */
+extern knot_lookup_table_t knot_opcode_names[];
+
+/*!
+ * \brief DNS reply code names.
+ */
+extern knot_lookup_table_t knot_rcode_names[];
+
+/*!
+ * \brief TSIG key algorithm names.
+ */
+extern knot_lookup_table_t knot_tsig_alg_names[];
+
+/*!
+ * \brief TSIG key algorithm names in a domain form.
+ */
+extern knot_lookup_table_t knot_tsig_alg_domain_names[];
+
+/*!
+ * \brief Returns length of TSIG digest for given algorithm.
+ *
+ * \param algorithm Algorithm code to be used.
+ *
+ * \retval Digest length for given algorithm.
+ */
+size_t knot_tsig_digest_length(const uint8_t algorithm);
+
+/*!
+ * \brief Returns length of DS digest for given algorithm.
+ *
+ * \param algorithm Algorithm code to be used.
+ *
+ * \retval Digest length for given algorithm.
+ */
+size_t knot_ds_digest_length(const uint8_t algorithm);
#endif /* _KNOT_CONSTS_H_ */
diff --git a/src/libknot/dname.c b/src/libknot/dname.c
index 5c7e961..754efe4 100644
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -20,8 +20,10 @@
#include <assert.h>
#include <string.h>
#include <ctype.h> // tolower()
+#include <inttypes.h>
#include "common.h"
+#include "common/mempattern.h"
#include "dname.h"
#include "consts.h"
#include "util/tolower.h"
@@ -178,7 +180,7 @@ static int knot_dname_str_to_wire(const char *name, uint size,
while (ch - (const uint8_t *)name < size) {
assert(w - wire - 1 == ch - (const uint8_t *)name);
-
+
if (*ch == '.') {
/* Zero-length label inside a dname - invalid. */
if (label_length == 0) {
@@ -285,7 +287,7 @@ static int knot_dname_find_labels(knot_dname_t *dname, int alloc)
if (pos - name > size || *pos != '\0' ) {
dbg_dname("Wrong wire format of domain name!\n");
- dbg_dname("Position: %d, character: %d, expected size: %d\n",
+ dbg_dname("Position: %"PRIuPTR", character: %d, expected size: %d\n",
pos - name, *pos, size);
return -1;
}
@@ -363,13 +365,6 @@ dbg_dname_exec_verb(
return 0;
}
-/*! \brief Destructor for reference counter. */
-static void knot_dname_dtor(struct ref_t *p)
-{
- knot_dname_t *dname = (knot_dname_t *)p;
- knot_dname_free(&dname);
-}
-
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -377,18 +372,13 @@ static void knot_dname_dtor(struct ref_t *p)
knot_dname_t *knot_dname_new()
{
knot_dname_t *dname = knot_dname_alloc();
+
dname->name = NULL;
- dname->size = 0;
- dname->node = NULL;
dname->labels = NULL;
- dname->label_count = -1;
- dname->id = 0;
-
- /* Initialize reference counting. */
- ref_init(&dname->ref, knot_dname_dtor);
-
- /* Set reference counter to 1, caller should release it after use. */
- knot_dname_retain(dname);
+ dname->node = NULL;
+ dname->count = 1;
+ dname->size = 0;
+ dname->label_count = 0;
return dname;
}
@@ -434,7 +424,23 @@ dbg_dname_exec_verb(
assert(dname->name != NULL);
dname->node = node;
- dname->id = 0;
+ return dname;
+}
+
+/*----------------------------------------------------------------------------*/
+
+knot_dname_t *knot_dname_new_from_nonfqdn_str(const char *name, uint size,
+ struct knot_node *node)
+{
+ knot_dname_t *dname = NULL;
+
+ if (name[size - 1] != '.') {
+ char *fqdn = strcdup(name, ".");
+ dname = knot_dname_new_from_str(fqdn, size + 1, node);
+ free(fqdn);
+ } else {
+ dname = knot_dname_new_from_str(name, size, node);
+ }
return dname;
}
@@ -473,8 +479,6 @@ knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, uint size,
}
dname->node = node;
- dname->id = 0;
-
return dname;
}
@@ -581,23 +585,6 @@ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire,
/*----------------------------------------------------------------------------*/
-int knot_dname_from_wire(const uint8_t *name, uint size,
- struct knot_node *node, knot_dname_t *target)
-{
- if (name == NULL || target == NULL) {
- return KNOT_EINVAL;
- }
-
- memcpy(target->name, name, size);
- target->size = size;
- target->node = node;
- target->id = 0;
-
- return knot_dname_find_labels(target, 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
knot_dname_t *knot_dname_deep_copy(const knot_dname_t *dname)
{
//return knot_dname_new_from_wire(dname->name, dname->size, dname->node);
@@ -643,42 +630,73 @@ char *knot_dname_to_str(const knot_dname_t *dname)
return 0;
}
- char *name;
-
- // root => special treatment
- if (dname->size == 1) {
- assert(dname->name[0] == 0);
- name = (char *)malloc(2 * sizeof(char));
- name[0] = '.';
- name[1] = '\0';
- return name;
- }
-
- name = (char *)malloc(dname->size * sizeof(char));
+ // Allocate space for dname string + 1 char termination.
+ size_t alloc_size = dname->size + 1;
+ char *name = malloc(alloc_size);
if (name == NULL) {
return NULL;
}
- uint8_t *w = dname->name;
- char *ch = name;
- int i = 0;
+ uint8_t label_len = 0;
+ size_t str_len = 0;
+
+ for (uint i = 0; i < dname->size; i++) {
+ uint8_t c = dname->name[i];
+
+ // Read next label size.
+ if (label_len == 0) {
+ label_len = c;
+
+ // Write label separation.
+ if (str_len > 0 || dname->size == 1) {
+ name[str_len++] = '.';
+ }
+
+ continue;
+ }
+
+ if (isalnum(c) != 0 || c == '-' || c == '_' || c == '*' ||
+ c == '/') {
+ name[str_len++] = c;
+ } else if (ispunct(c) != 0) {
+ // Increase output size for \x format.
+ alloc_size += 1;
+ char *extended = realloc(name, alloc_size);
+ if (extended == NULL) {
+ free(name);
+ return NULL;
+ }
+ name = extended;
+
+ // Write encoded character.
+ name[str_len++] = '\\';
+ name[str_len++] = c;
+ } else {
+ // Increase output size for \DDD format.
+ alloc_size += 3;
+ char *extended = realloc(name, alloc_size);
+ if (extended == NULL) {
+ free(name);
+ return NULL;
+ }
+ name = extended;
- do {
- assert(*w != 0);
- int label_size = *(w++);
- // copy the label
- memcpy(ch, w, label_size);
- i += label_size;
- ch += label_size;
- w += label_size;
- if (w - dname->name < dname->size) { // another label following
- *(ch++) = '.';
- ++i;
+ // Write encoded character.
+ int ret = snprintf(name + str_len, alloc_size - str_len,
+ "\\%03u", c);
+ if (ret <= 0 || ret >= alloc_size - str_len) {
+ free(name);
+ return NULL;
+ }
+
+ str_len += ret;
}
- } while (i < dname->size - 1);
- *ch = 0;
- assert(ch - name == dname->size - 1);
+ label_len--;
+ }
+
+ // String_termination.
+ name[str_len] = 0;
return name;
}
@@ -690,7 +708,7 @@ int knot_dname_to_lower(knot_dname_t *dname)
if (dname == NULL) {
return KNOT_EINVAL;
}
-
+
for (int i = 0; i < dname->size; ++i) {
dname->name[i] = knot_tolower(dname->name[i]);
}
@@ -699,13 +717,13 @@ int knot_dname_to_lower(knot_dname_t *dname)
/*----------------------------------------------------------------------------*/
-int knot_dname_to_lower_copy(const knot_dname_t *dname, char *name,
+int knot_dname_to_lower_copy(const knot_dname_t *dname, char *name,
size_t size)
{
if (dname == NULL || name == NULL || size < dname->size) {
return KNOT_EINVAL;
}
-
+
for (int i = 0; i < dname->size; ++i) {
name[i] = knot_tolower(dname->name[i]);
}
@@ -728,13 +746,6 @@ uint knot_dname_size(const knot_dname_t *dname)
/*----------------------------------------------------------------------------*/
-unsigned int knot_dname_id(const knot_dname_t *dname)
-{
- return dname->id;
-}
-
-/*----------------------------------------------------------------------------*/
-
uint8_t knot_dname_size_part(const knot_dname_t *dname, int labels)
{
assert(labels < dname->label_count);
@@ -782,7 +793,7 @@ dbg_dname_exec_detail(
: -1);
}
);
-
+
if (node && knot_node_zone(node)
&& knot_zone_contents(knot_node_zone(node))
&& knot_zone_contents_gen_is_new(knot_zone_contents(
@@ -841,28 +852,28 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname)
(knot_dname_is_fqdn(dname)))) {
return NULL;
}
-
+
knot_dname_t *parent = knot_dname_new();
if (parent == NULL) {
return NULL;
}
-
+
// last label, the result should be root domain
if (dname->label_count == 1) {
dbg_dname_verb("Chopping last label.\n");
parent->label_count = 0;
-
+
parent->name = (uint8_t *)malloc(1);
if (parent->name == NULL) {
ERR_ALLOC_FAILED;
knot_dname_free(&parent);
return NULL;
}
-
+
*parent->name = 0;
-
+
parent->size = 1;
-
+
return parent;
}
@@ -883,7 +894,7 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname)
}
memcpy(parent->name, &dname->name[dname->name[0] + 1], parent->size);
-
+
short first_label_length = dname->labels[1];
@@ -1076,13 +1087,9 @@ void knot_dname_free(knot_dname_t **dname)
return;
}
- if ((*dname)->name != NULL) {
- free((*dname)->name);
- }
+ free((*dname)->name);
- if((*dname)->labels != NULL) {
- free((*dname)->labels);
- }
+ free((*dname)->labels);
// slab_free(*dname);
@@ -1104,6 +1111,17 @@ int knot_dname_compare_cs(const knot_dname_t *d1, const knot_dname_t *d2)
return knot_dname_cmp(d1, d2, 1);
}
+int knot_dname_compare_non_canon(const knot_dname_t *d1, const knot_dname_t *d2)
+{
+ int ret = memcmp(d1->name, d2->name,
+ d1->size > d2->size ? d2->size : d1->size);
+ if (d1->size != d2->size && ret == 0) {
+ return d1->size < d2->size ? -1 : 1;
+ } else {
+ return ret;
+ }
+}
+
/*----------------------------------------------------------------------------*/
knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2)
@@ -1157,17 +1175,3 @@ knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2)
return d1;
}
-
-void knot_dname_set_id(knot_dname_t *dname, unsigned int id)
-{
- dname->id = id;
-}
-
-unsigned int knot_dname_get_id(const knot_dname_t *dname)
-{
- if (dname != NULL) {
- return dname->id;
- } else {
- return 0; /* 0 should never be used and is reserved for err. */
- }
-}
diff --git a/src/libknot/dname.h b/src/libknot/dname.h
index 6f649ce..a872a4d 100644
--- a/src/libknot/dname.h
+++ b/src/libknot/dname.h
@@ -30,7 +30,6 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
-#include "common/ref.h"
struct knot_node;
@@ -43,19 +42,12 @@ struct knot_node;
* \todo Consider restricting to FQDN only (see knot_dname_new_from_str()).
*/
struct knot_dname {
- ref_t ref; /*!< Reference counting. */
- uint8_t *name; /*!< Wire format of the domain name. */
- uint8_t *labels;
- struct knot_node *node; /*!< Zone node the domain name belongs to. */
- unsigned int id; /*!< ID of domain name used in zone dumping. */
-
- /*!
- * \brief Size of the domain name in octets.
- * \todo Is this needed? Every dname should end with \0 or pointer.
- */
- unsigned int size;
-
- unsigned short label_count;
+ uint8_t *name; /*!< Wire format of the domain name. */
+ uint8_t *labels; /*!< Array of labels positions in name. */
+ struct knot_node *node; /*!< Zone node the domain name belongs to. */
+ uint32_t count; /*!< Reference counter. */
+ uint8_t size; /*!< Length of the domain name. */
+ uint8_t label_count; /*!< Number of labels. */
};
typedef struct knot_dname knot_dname_t;
@@ -96,6 +88,20 @@ knot_dname_t *knot_dname_new_from_str(const char *name, unsigned int size,
struct knot_node *node);
/*!
+ * \brief Creates a dname structure from domain name possibly given in
+ * non-presentation format.
+ *
+ * Works the same as knot_dname_new_from_str but makes sure, that the name
+ * is terminated with a dot.
+ *
+ * \see knot_dname_new_from_str
+ *
+ */
+knot_dname_t *knot_dname_new_from_nonfqdn_str(const char *name,
+ unsigned int size,
+ struct knot_node *node);
+
+/*!
* \brief Creates a dname structure from domain name given in wire format.
*
* \note The name is copied into the structure.
@@ -142,32 +148,6 @@ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire,
knot_dname_t *dname);
/*!
- * \brief Initializes domain name by the name given in wire format.
- *
- * \note The name is copied into the structure.
- * \note If there is any name in the structure, it will be replaced.
- * \note If the given name is not a FQDN, the result will be neither.
- *
- * \param name Domain name in wire format.
- * \param size Size of the domain name in octets.
- * \param node Zone node the domain name belongs to. Set to NULL if not
- * applicable.
- * \param target Domain name structure to initialize.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_ENOMEM if allocation of labels info failed.
- * \retval KNOT_EINVAL if name or target is null.
- *
- * \todo This function does not check if the given data is in correct wire
- * format at all. It thus creates a invalid domain name, which if passed
- * e.g. to knot_dname_to_str() may result in crash. Decide whether it
- * is OK to retain this and check the data in other functions before
- * calling this one, or if it should verify the given data.
- */
-int knot_dname_from_wire(const uint8_t *name, unsigned int size,
- struct knot_node *node, knot_dname_t *target);
-
-/*!
* \brief Duplicates the given domain name.
*
* \note Copied dname referense count is reset to 1, caller is responsible
@@ -193,7 +173,7 @@ char *knot_dname_to_str(const knot_dname_t *dname);
int knot_dname_to_lower(knot_dname_t *dname);
-int knot_dname_to_lower_copy(const knot_dname_t *dname, char *name,
+int knot_dname_to_lower_copy(const knot_dname_t *dname, char *name,
size_t size);
/*!
@@ -214,8 +194,6 @@ const uint8_t *knot_dname_name(const knot_dname_t *dname);
*/
unsigned int knot_dname_size(const knot_dname_t *dname);
-unsigned int knot_dname_id(const knot_dname_t *dname);
-
/*!
* \brief Returns size of a part of domain name.
*
@@ -377,6 +355,8 @@ int knot_dname_compare(const knot_dname_t *d1, const knot_dname_t *d2);
* \retval 0 if the domain names are identical.
*/
int knot_dname_compare_cs(const knot_dname_t *d1, const knot_dname_t *d2);
+int knot_dname_compare_non_canon(const knot_dname_t *d1,
+ const knot_dname_t *d2);
/*!
* \brief Concatenates two domain names.
@@ -391,10 +371,6 @@ int knot_dname_compare_cs(const knot_dname_t *d1, const knot_dname_t *d2);
*/
knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2);
-void knot_dname_set_id(knot_dname_t *dname, unsigned int id);
-
-unsigned int knot_dname_get_id(const knot_dname_t *dname);
-
/*!
* \brief Increment reference counter for dname.
*
@@ -404,16 +380,10 @@ unsigned int knot_dname_get_id(const knot_dname_t *dname);
*/
static inline void knot_dname_retain(knot_dname_t *dname) {
if (dname) {
- ref_retain(&dname->ref);
+ __sync_add_and_fetch(&dname->count, 1);
}
}
-/*#define knot_dname_retain(d) \
- knot_dname_retain_((d));\
- if ((d))\
- fprintf(stderr, "dname_retain: %s() at %s:%d, %p refcount=%zu\n",\
- __func__, __FILE__, __LINE__, d, (d)->ref.count) */
-
/*!
* \brief Decrement reference counter for dname.
*
@@ -421,16 +391,12 @@ static inline void knot_dname_retain(knot_dname_t *dname) {
*/
static inline void knot_dname_release(knot_dname_t *dname) {
if (dname) {
- ref_release(&dname->ref);
+ if (__sync_sub_and_fetch(&dname->count, 1) == 0) {
+ knot_dname_free(&dname);
+ }
}
}
-/*#define knot_dname_release(d) \
- if ((d))\
- fprintf(stderr, "dname_release: %s() at %s:%d, %p refcount=%zu\n",\
- __func__, __FILE__, __LINE__, d, (d)->ref.count-1);\
- knot_dname_release_((d)) */
-
#endif /* _KNOT_DNAME_H_ */
/*! @} */
diff --git a/src/libknot/edns.c b/src/libknot/edns.c
index a71c4eb..b020992 100644
--- a/src/libknot/edns.c
+++ b/src/libknot/edns.c
@@ -14,13 +14,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include "edns.h"
#include "common.h"
-#include "util/descriptor.h"
+#include "common/descriptor.h"
#include "util/debug.h"
/*! \brief Various EDNS constatns. */
@@ -62,7 +63,7 @@ int knot_edns_new_from_wire(knot_opt_rr_t *opt_rr, const uint8_t *wire,
return KNOT_EINVAL;
}
- if (max_size < KNOT_EDNS_MIN_SIZE) {
+ if ((int)max_size < KNOT_EDNS_MIN_SIZE) {
dbg_edns("Not enough data to parse OPT RR header.\n");
return KNOT_EFEWDATA;
}
@@ -164,18 +165,13 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
int rc = 0;
dbg_edns_verb("Parsing options.\n");
- const knot_rdata_t *rdata = knot_rrset_rdata(rrset);
-
- // in OPT RR, all RDATA are in one RDATA item stored as BINARY data,
- // i.e. preceded by their length
- if (rdata != NULL) {
- assert(knot_rdata_item_count(rdata) == 1);
- uint16_t size = knot_rdata_item(rdata, 0)->raw_data[0];
- const uint8_t *raw = (const uint8_t *)
- knot_rdata_item(rdata, 0)->raw_data;
- int pos = 2;
+ uint8_t *raw = knot_rrset_get_rdata(rrset, 0);
+ uint16_t size = rrset_rdata_item_size(rrset, 0);
+
+ if (raw != NULL) {
+ size_t pos = 0;
assert(size > 0);
- while (pos - 2 < size) {
+ while (pos < size) {
// ensure there is enough data to parse the OPTION CODE
// and OPTION LENGTH
if (size - pos + 2 < 4) {
@@ -187,10 +183,10 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
// there should be enough data for parsing the OPTION
// data
- if (size - pos - 2 < opt_size) {
+ if (size - pos < opt_size) {
dbg_edns("Not enough data to parse options: "
- "size - pos - 2=%d, opt_size=%d\n",
- size - pos - 2, opt_size);
+ "size - pos=%zu, opt_size=%d\n",
+ size - pos, opt_size);
return KNOT_EMALF;
}
rc = knot_edns_add_option(opt_rr, opt_code, opt_size,
@@ -202,8 +198,8 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
pos += 4 + opt_size;
}
}
-
-
+
+
dbg_edns_verb("EDNS created.\n");
return KNOT_EOK;
@@ -359,9 +355,9 @@ short knot_edns_to_wire(const knot_opt_rr_t *opt_rr, uint8_t *wire,
return KNOT_EINVAL;
}
- assert(KNOT_EDNS_MIN_SIZE <= max_size);
+ assert(KNOT_EDNS_MIN_SIZE <= (int)max_size);
- if (max_size < opt_rr->size) {
+ if ((int)max_size < opt_rr->size) {
dbg_edns("Not enough place for OPT RR wire format.\n");
return KNOT_ESPACE;
}
@@ -428,9 +424,7 @@ void knot_edns_free_options(knot_opt_rr_t *opt_rr)
/* Free the option data, if any. */
for (int i = 0; i < opt_rr->option_count; i++) {
knot_opt_option_t *option = &(opt_rr->options[i]);
- if (option->data != NULL) {
- free(option->data);
- }
+ free(option->data);
}
free(opt_rr->options);
}
diff --git a/src/libknot/hash/cuckoo-hash-table.c b/src/libknot/hash/cuckoo-hash-table.c
deleted file mode 100644
index a2a6d3f..0000000
--- a/src/libknot/hash/cuckoo-hash-table.c
+++ /dev/null
@@ -1,1765 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h> /* defines uint32_t etc */
-#include <assert.h>
-#include <pthread.h>
-#include <math.h>
-
-#include <urcu.h>
-
-#include "util/utils.h"
-#include "common.h"
-#include "util/debug.h"
-#include "hash/cuckoo-hash-table.h"
-#include "hash/hash-functions.h"
-
-/*----------------------------------------------------------------------------*/
-/* Macros and inline functions */
-/*----------------------------------------------------------------------------*/
-
-/*!
- * \brief Default size table holding information about used hash table cells
- * when hashing.
- */
-#define RELOCATIONS_DEFAULT 200
-
-/*!
- * \brief Maximum size table holding information about used hash table cells
- * when hashing (just for debug issues).
- */
-#define RELOCATIONS_MAX 1000
-
-/*!
- * \brief Macro for hashing the given key using the universal system.
- *
- * \param system Universal system to use for the hashing.
- * \param key Key to hash.
- * \param length Size of the key in bytes.
- * \param exp Exponent of the hash table size (the size is a power of 2).
- * \param table Hash table index.
- * \param gen Universal system generation.
- *
- * \return Hashed key.
- */
-#define HASH(system, key, length, exp, gen, table) \
- us_hash(system, fnv_32_buf(key, length, FNV1_32_INIT), exp, table, gen)
-
-/*!
- * \brief Approximate ratio of hash table size to number of hashed items when 2
- * tables are used.
- */
-static const float SIZE_RATIO_2 = 2;
-
-/*!
- * \brief Approximate ratio of hash table size to number of hashed items when 3
- * tables are used.
- */
-static const float SIZE_RATIO_3 = 1.15;
-
-/*!
- * \brief Approximate ratio of hash table size to number of hashed items when 4
- * tables are used.
- */
-static const float SIZE_RATIO_4 = 1.08;
-
-/*----------------------------------------------------------------------------*/
-
-/*! \brief Flag marking the generation of hash table or its item to be 1. */
-static const uint8_t FLAG_GENERATION1 = 0x1; // 00000001
-/*! \brief Flag marking the generation of hash table or its item to be 2. */
-static const uint8_t FLAG_GENERATION2 = 0x2; // 00000010
-/*! \brief Flag marking both generations. */
-static const uint8_t FLAG_GENERATION_BOTH = 0x3; // 00000011
-
-/*! \brief Flag used to mark the table when it's being rehashed. */
-static const uint8_t FLAG_REHASH = 0x4; // 00000100
-
-/*----------------------------------------------------------------------------*/
-/*! \brief Clears the table / item flags. */
-static inline void CLEAR_FLAGS(uint8_t *flags)
-{
- if (flags) {
- *flags = (uint8_t)0x0;
- }
-}
-
-/*! \brief Returns the generation stored in the flags. */
-static inline uint8_t GET_GENERATION(uint8_t flags)
-{
- return (flags & FLAG_GENERATION_BOTH);
-}
-
-/*! \brief Checks if the generation stored in both flags are the same. */
-static inline int EQUAL_GENERATIONS(uint8_t flags1, uint8_t flags2)
-{
- return (GET_GENERATION(flags1) == GET_GENERATION(flags2));
-}
-
-/*! \brief Checks if the generation stored in the flags is 1. */
-static inline int IS_GENERATION1(uint8_t flags)
-{
- return ((flags & FLAG_GENERATION1) != 0);
-}
-
-/*! \brief Sets the generation stored in the flags to 1. */
-static inline void SET_GENERATION1(uint8_t *flags)
-{
- if (flags) {
- *flags = ((*flags) & ~FLAG_GENERATION2) | FLAG_GENERATION1;
- }
-}
-
-/*! \brief Checks if the generation stored in the flags is 2. */
-static inline int IS_GENERATION2(uint8_t flags)
-{
- return ((flags & FLAG_GENERATION2) != 0);
-}
-
-/*! \brief Sets the generation stored in the flags to 2. */
-static inline void SET_GENERATION2(uint8_t *flags)
-{
- if (flags) {
- *flags = ((*flags) & ~FLAG_GENERATION1) | FLAG_GENERATION2;
- }
-}
-
-/*! \brief Sets the generation stored in the flags to the given generation. */
-static inline void SET_GENERATION(uint8_t *flags, uint8_t generation)
-{
- if (flags) {
- *flags = ((*flags) & ~FLAG_GENERATION_BOTH) | generation;
- }
-}
-
-/*! \brief Sets the generation stored in the flags to the next one (cyclic). */
-static inline uint8_t SET_NEXT_GENERATION(uint8_t *flags)
-{
- if (flags) {
- return ((*flags) ^= FLAG_GENERATION_BOTH);
- }
- return 0;
-}
-
-/*! \brief Returns the next generation to the one stored in flags (cyclic). */
-static inline uint8_t NEXT_GENERATION(uint8_t flags)
-{
- return ((flags & FLAG_GENERATION_BOTH) ^ FLAG_GENERATION_BOTH);
-}
-
-/*! \brief Sets the rehashing flag to the flags. */
-static inline void SET_REHASHING_ON(uint8_t *flags)
-{
- if (flags) {
- *flags = (*flags | FLAG_REHASH);
- }
-}
-
-/*! \brief Removes the rehashing flag from the flags. */
-static inline void SET_REHASHING_OFF(uint8_t *flags)
-{
- if (flags) {
- *flags = (*flags & ~FLAG_REHASH);
- }
-}
-
-/*! \brief Checks if the rehashing flag is set in the flags. */
-static inline int IS_REHASHING(uint8_t flags)
-{
- return ((flags & FLAG_REHASH) != 0);
-}
-
-/*----------------------------------------------------------------------------*/
-/* Private functions */
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Returns the exponent of the nearest larger power of two.
- */
-static uint get_larger_exp(uint n)
-{
- uint res = 0;
- while (hashsize(++res) < n) {}
-
- return res;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Counts the ideal table count and the exponent of those tables' sizes.
- *
- * Only 3 or 4 hash tables are considered. The setup in which less items are
- * wasted is recommended.
- *
- * \param items Number of items to hash.
- * \param table_count Recommended number of tables will be saved here.
- *
- * \return Exponent of the tables' sizes.
- */
-static uint get_table_exp_and_count(uint items, uint *table_count)
-{
- // considering only 3 or 4 tables
- int exp3 = get_larger_exp((items * SIZE_RATIO_3) / 3);
- int exp4 = get_larger_exp(items * SIZE_RATIO_4) - 2;
-
- if (exp4 < 0) {
- exp4 = 1;
- }
-
- dbg_ck("Determining ideal table size...\n");
- dbg_ck("\tNumber of items: %u\n", items);
- dbg_ck("\tThree tables: size of one table: %u, total size: %u\n",
- hashsize(exp3), 3 * hashsize(exp3));
- dbg_ck("\tFour tables: size of one table: %u, total size: %u\n",
- hashsize(exp4), 4 * hashsize(exp4));
-
- // we need exponent at least 1 (this is quite ugly..)
- if (exp3 == 0) {
- exp3 = 1;
- }
- if (exp4 == 0) {
- exp4 = 1;
- }
-
- if (exp3 >= 32 || exp4 >= 32) {
- return 0;
- }
-
- if (((hashsize(exp3) * 3) - (items)) < ((hashsize(exp4) * 4) - items)) {
- *table_count = 3;
- return exp3;
- } else {
- *table_count = 4;
- return exp4;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Counts the maximum effective item count based on size of the tables.
- *
- * For 3 tables, the effective utilization should be around 91%.
- * For 4 tables it is 97%.
- *
- * See Fotakis, Dimitris, et al. - Space Efficient Hash Tables with Worst Case
- * Constant Access Time. CiteSeerX. 2003
- * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.5337
- */
-static uint get_max_table_items(uint table_count, int table_exponent)
-{
- assert(table_count == 3 || table_count == 4);
-
- float coef;
-
- if (table_count == 3) {
- coef = 0.91;
- } else {
- coef = 0.97;
- }
-
- return (uint)floor((table_count * hashsize(table_exponent)) * coef);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int ck_is_full(const ck_hash_table_t *table)
-{
- return (table->items >= get_max_table_items(table->table_count,
- table->table_size_exp));
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int ck_stash_is_full(const ck_hash_table_t *table)
-{
- return (table->items_in_stash >= STASH_SIZE_MAX);
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Clears the given item by assigning a NULL pointer to it.
- */
-static inline void ck_clear_item(ck_hash_table_item_t **item)
-{
- dbg_stash("[EMPTY STASH] [CREATE] setting item %p (%p) to NULL.\n",
- item, *item);
- *item = NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Insert given contents to the hash table item.
- */
-static void ck_fill_item(const char *key, size_t key_length, void *value,
- uint generation, ck_hash_table_item_t *item)
-{
- // must allocate new space for key and value, otherwise it will be lost!
- item->key = key;
- item->key_length = key_length;
- item->value = value;
- CLEAR_FLAGS(&item->timestamp);
- item->timestamp = generation;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Swaps two hash table items.
- */
-static inline void ck_swap_items(ck_hash_table_item_t **item1,
- ck_hash_table_item_t **item2)
-{
- ck_hash_table_item_t *tmp = *item1;
- *item1 = *item2;
- *item2 = tmp;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Sets the \a item pointer to the \a to pointer.
- */
-static inline void ck_put_item(ck_hash_table_item_t **to,
- ck_hash_table_item_t *item)
-{
- if (item == NULL) {
- dbg_stash("[EMPTY STASH] [CREATE] Putting NULL to item %p.\n",
- to);
- }
- *to = item;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Compares the key of item with the given key.
- *
- * \param item Item to compare with.
- * \param key Key to compare.
- * \param length Size of the key in bytes.
- *
- * \return <> 0 if the keys match.
- * \return 0 if they don't.
- */
-static inline uint ck_items_match(const ck_hash_table_item_t *item,
- const char *key, size_t length)
-{
- assert(item != NULL);
-
- return (length == item->key_length
- && (strncmp(item->key, key, length) == 0));
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Switches the given table number to a randomly chosen other table
- * number.
- */
-static inline void ck_next_table(uint *table, uint table_count)
-{
- uint next;
- while ((*table) == (next = knot_quick_rand() % table_count)) {}
- *table = next;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tries to find the given key in the hash table's stash.
- *
- * \param table Hash table to search in.
- * \param key Key to find.
- * \param length Size of the key in bytes.
- *
- * \return Hash table item matching the key or NULL if not found in the stash.
- */
-static ck_hash_table_item_t **ck_find_in_stash(const ck_hash_table_t *table,
- const char *key, uint length)
-{
- ck_stash_item_t *item = table->stash;
- while (item != NULL) {
- /*! \todo Can the item be NULL?
- * Sometimes it crashed on assert in ck_items_match(),
- * But I'm not sure if this may happen or if the
- * semantics of the stash are that all items must be
- * non-NULL.
- */
- if (item->item && ck_items_match(item->item, key, length)) {
- dbg_ck_detail("Comparing item in stash (key: %.*s (size"
- " %zu)) with searched item (key %.*s (size %u)).\n",
- (int)item->item->key_length, item->item->key,
- item->item->key_length, (int)length, key, length);
- return &item->item;
- } else if (item->item == NULL) {
- dbg_stash("[EMPTY STASH] [FIND] STASH ITEM IS EMPTY: "
- "%p (%p)\n", item, item->item);
- }
- item = item->next;
- }
-
- return NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tries to find item with given key using hash functions from the given
- * generation.
- *
- * \param table Hash table to search in.
- * \param key Key to find.
- * \param length Size of the key in bytes.
- * \param generation Generation of items (table) to use. Items having other
- * generation are ignored.
- */
-static ck_hash_table_item_t **ck_find_gen(const ck_hash_table_t *table,
- const char *key,
- size_t length, uint8_t generation)
-{
- uint32_t hash;
- dbg_ck_verb("Finding item in generation: %u\n", generation);
-
- // check hash tables
- for (uint t = 0; t < table->table_count; ++t) {
- hash = HASH(&table->hash_system, key, length,
- table->table_size_exp, generation, t);
-
- dbg_ck_detail("Hash: %u, key: %.*s\n", hash, (int)length, key);
- dbg_ck_detail("Table %d, hash: %u, item: %p\n", t + 1, hash,
- table->tables[t][hash]);
- if (table->tables[t][hash] != NULL) {
- dbg_ck_detail("Table %u, key: %.*s, value: %p, key "
- "length: %zu\n",
- t + 1, (int)table->tables[t][hash]->key_length,
- table->tables[t][hash]->key,
- table->tables[t][hash]->value,
- table->tables[t][hash]->key_length);
- }
-
- if (table->tables[t][hash] &&
- ck_items_match(table->tables[t][hash], key, length)) {
- // found
- return &table->tables[t][hash];
- }
- }
-
- // try to find in stash
- dbg_ck_verb("Searching in stash...\n");
-
- ck_hash_table_item_t **found =
- ck_find_in_stash(table, key, length);
-
- dbg_ck_verb("Found pointer: %p\n", found);
- if (found != NULL) {
- dbg_ck_verb("Stash, key: %.*s, value: %p, key length: %zu\n",
- (int)(*found)->key_length, (*found)->key,
- (*found)->value, (*found)->key_length);
- }
-
- // ck_find_in_buffer returns NULL if not found, otherwise pointer to
- // item
- return found;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Finds item with given key and returns non-constant pointer to pointer
- * to the appropriate hash table item.
- *
- * \param table Hash table to search in.
- * \param key Key to find.
- * \param length Size of the key in bytes.
- */
-static ck_hash_table_item_t **ck_find_item_nc(const ck_hash_table_t *table,
- const char *key, size_t length)
-{
- // get the generation of the table so that we use the same value
- uint8_t generation = table->generation;
-
- // find item using the table generation's hash functions
- ck_hash_table_item_t **found = ck_find_gen(table, key, length,
- GET_GENERATION(generation));
- // if rehashing is in progress, try the next generation's functions
- if (!found && IS_REHASHING(generation)) {
- found = ck_find_gen(table, key, length,
- NEXT_GENERATION(generation));
- }
-
- return found;
-}
-
-/*----------------------------------------------------------------------------*/
-/* Lightweight dynamic array for keeping track of used items. */
-/*----------------------------------------------------------------------------*/
-
-typedef struct ck_used {
- uint32_t *items;
- uint array_count;
- size_t *counts;
- size_t allocated;
-} ck_used_t;
-
-/*----------------------------------------------------------------------------*/
-
-static int ck_used_create(ck_used_t *used, uint table_count)
-{
- // all tables in one array
- used->items = malloc(table_count * RELOCATIONS_DEFAULT
- * sizeof(uint32_t));
- if (used->items == NULL) {
- return -1;
- }
-
- used->counts = malloc(table_count * sizeof(size_t));
- if (used->counts == NULL) {
- free(used->items);
- return -1;
- }
-
- used->array_count = table_count;
- used->allocated = RELOCATIONS_DEFAULT;
-
- for (int i = 0; i < table_count; ++i) {
- used->counts[i] = 0;
- }
-
- memset(used->items, 0,
- used->array_count * used->allocated * sizeof(uint32_t));
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void ck_used_free(ck_used_t *used)
-{
- free(used->items);
- free(used->counts);
- used->allocated = 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int ck_used_add(ck_used_t *used, uint table_nr, uint32_t to_add)
-{
- dbg_ck_hash_verb("1) Table nr: %u, count: %zu, allocated: %zu\n",
- table_nr, used->counts[table_nr], used->allocated);
-
- if (used->counts[table_nr] == used->allocated) {
- dbg_ck_hash_verb("Reallocating...\n");
- size_t allocated_new = used->allocated * 2;
- uint32_t *items_new = malloc(used->array_count * allocated_new
- * sizeof(uint32_t));
- if (items_new == NULL) {
- return -1;
- }
-
- memcpy(items_new, used->items,
- used->allocated * used->array_count);
-
- uint32_t *old_items = used->items;
-
- used->items = items_new;
- used->allocated = allocated_new;
-
- free(old_items);
- }
-
- dbg_ck_hash_verb("2) Table nr: %u, count: %zu, allocated: %zu\n",
- table_nr, used->counts[table_nr], used->allocated);
-
- assert(used->counts[table_nr] < used->allocated);
- used->items[table_nr * used->allocated + used->counts[table_nr]]
- = to_add;
- ++used->counts[table_nr];
-
- dbg_ck_hash_verb("3)Table nr: %u, count: %zu, allocated: %zu\n",
- table_nr, used->counts[table_nr], used->allocated);
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Checks if the hash was already used twice.
- *
- * If yes, it means we entered a loop in the hashing process, so we must stop.
- * Otherwise it remembers that we used the hash.
- *
- * \note According to Kirsch, et al. a check that at most one hash was used
- * twice should be sufficient. We will retain our version for now.
- *
- * \param used Array of used table indices (hashes).
- * \param hash Hash to check.
- *
- * \retval -1 if the hash was already used twice.
- * \retval -2 if an error occured.
- * \retval 0 if the hash was not used twice yet.
- */
-static int ck_check_used_twice(ck_used_t *used, uint table_nr,
- uint32_t hash)
-{
- uint i = 0, found = 0;
-
- while (i < used->counts[table_nr] && found < 2) {
- if (used->items[table_nr * used->allocated + i] == hash) {
- ++found;
- }
- ++i;
- }
-
- if (found == 2) {
- dbg_ck_hash("Hashing entered infinite loop.\n");
- return -1;
- } else {
- return ck_used_add(used, table_nr, hash);
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Hashes the given item using the given generation.
- *
- * \param table Hash table where to put the item.
- * \param to_hash In: Item to hash. Out: NULL if successful, item that failed
- * to hash if not.
- * \param free Free place where to put the last moved item when the hasing
- * is unsuccessful.
- * \param generation Generation of items (table) to be used for hashing.
- *
- * \retval 0 if successful and no loop occured.
- * \retval 1 if a loop occured and the item was inserted to the \a free place.
- * \retval < 0 if an error occured.
- */
-static int ck_hash_item(ck_hash_table_t *table, ck_hash_table_item_t **to_hash,
- ck_hash_table_item_t **free, uint8_t generation)
-{
-// da_array_t used[table->table_count];
-// for (uint i = 0; i < table->table_count; ++i) {
-// da_initialize(&used[i], RELOCATIONS_DEFAULT, sizeof(uint));
-// }
- ck_used_t used;
- int ret = ck_used_create(&used, table->table_count);
- if (ret != 0) {
- return -1;
- }
-
- // hash until empty cell is encountered or until loop appears
-
- dbg_ck_hash_verb("Hashing key: %.*s of size %zu.\n",
- (int)(*to_hash)->key_length, (*to_hash)->key,
- (*to_hash)->key_length);
-
- uint next_table = 0;
-
- uint32_t hash = HASH(&table->hash_system, (*to_hash)->key,
- (*to_hash)->key_length, table->table_size_exp,
- generation, next_table);
-
- dbg_ck_hash_detail("New hash: %u.\n", hash);
- assert(hash < hashsize(table->table_size_exp));
-
- ret = ck_used_add(&used, next_table, hash);
- if (ret != 0) {
- return -2;
- }
-
- ck_hash_table_item_t **next = &table->tables[next_table][hash];
- dbg_ck_hash_detail("Item to be moved: %p, place in table: %p\n",
- *next, next);
- ck_hash_table_item_t **moving = to_hash;
-
- int loop = 0;
-
- while (*next != NULL) {
- dbg_ck_hash_detail("Swapping items: To hash: %p, Moving: %p\n",
- to_hash, moving);
- ck_swap_items(to_hash, moving); // first time it's unnecessary
-
- // set the generation of the inserted item to the next
- SET_GENERATION(&(*moving)->timestamp, generation);
-
- moving = next;
-
- dbg_ck_hash_detail("Moving item from table %u, key: %.*s, hash "
- "%u \n", next_table + 1,
- (int)(*moving)->key_length,
- (*moving)->key, hash);
-
- // if rehashing and the 'next' item is from the old generation,
- // start from table 1
- if (generation != table->generation &&
- EQUAL_GENERATIONS((*next)->timestamp, table->generation)) {
- next_table = 0;
- } else {
- ck_next_table(&next_table, table->table_count);
- }
-
- hash = HASH(&table->hash_system, (*next)->key,
- (*next)->key_length, table->table_size_exp,
- generation, next_table);
-
- next = &table->tables[next_table][hash];
-
- dbg_ck_hash_detail("To table %u, hash %u, item: %p, place: %p"
- "\n", next_table + 1, hash, *next, next);
-
- if ((*next) != NULL) {
- dbg_ck_hash_detail("Table %u, hash: %u, key: %.*s\n",
- next_table + 1, hash,
- (int)(*next)->key_length, (*next)->key);
- }
-
- // check if this cell wasn't already used in this item's hashing
- if (ck_check_used_twice(&used, next_table, hash) != 0) {
- next = free;
- loop = -1;
- break;
- }
- }
-
- dbg_ck_hash_detail("Putting pointer %p (*moving) to item %p (next).\n",
- *moving, next);
-
- ck_put_item(next, *moving);
- // set the new generation for the inserted item
- SET_GENERATION(&(*next)->timestamp, generation);
- dbg_ck_hash_detail("Putting pointer %p (*old) to item %p (moving).\n",
- *to_hash, moving);
-
- ck_put_item(moving, *to_hash);
-
- // set the new generation for the inserted item
- SET_GENERATION(&(*moving)->timestamp, generation);
- *to_hash = NULL;
-
- ck_used_free(&used);
-
- return loop;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void ck_rollback_rehash(ck_hash_table_t *table)
-{
- // set old generation in tables
- for (int i = 0; i < hashsize(table->table_size_exp); ++i) {
- // no need for locking - timestamp is not used in lookup
- // and two paralel insertions (and thus rehashings) are
- // impossible
- for (uint t = 0; t < table->table_count; ++t) {
- if (table->tables[t][i] != NULL) {
- SET_GENERATION(&table->tables[t][i]->timestamp,
- table->generation);
- }
- }
- }
-
- // set old generation in stash
- ck_stash_item_t *item = table->stash;
- while (item != NULL) {
- assert(item->item != NULL);
- SET_GENERATION(&item->item->timestamp, table->generation);
- }
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Adds the given item to the hash table's stash.
- *
- * \param table Hash table to add the item to.
- * \param item Item to add.
- *
- * \retval 0 if successful.
- * \retval -1 if an error occured.
- */
-int ck_add_to_stash(ck_hash_table_t *table, ck_hash_table_item_t *item)
-{
- if (item == NULL) {
- dbg_stash("[EMPTY STASH] [CREATE] ADDING NULL ITEM TO STASH\n");
- }
-
- ck_stash_item_t *new_item
- = (ck_stash_item_t *)malloc(sizeof(ck_stash_item_t));
- if (new_item == NULL) {
- ERR_ALLOC_FAILED;
- return -1;
- }
-
- new_item->item = item;
- new_item->next = table->stash;
- table->stash = new_item;
-
- dbg_ck_hash_verb("First item in stash (now inserted): key: %.*s (size"
- " %zu), value: %p\n", (int)table->stash->item->key_length,
- table->stash->item->key, table->stash->item->key_length,
- table->stash->item->value);
-
- // increase count of items in stash
- ++table->items_in_stash;
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int ck_new_table(ck_hash_table_item_t ***table, int exp)
-{
- *table = (ck_hash_table_item_t **)
- malloc(hashsize(exp) * sizeof(ck_hash_table_item_t *));
- if (*table == NULL) {
- ERR_ALLOC_FAILED;
- return -1;
- }
-
- // set to 0
- memset(*table, 0, hashsize(exp) * sizeof(ck_hash_table_item_t *));
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-/* Public functions */
-/*----------------------------------------------------------------------------*/
-
-ck_hash_table_t *ck_create_table(uint items)
-{
- ck_hash_table_t *table =
- (ck_hash_table_t *)malloc(sizeof(ck_hash_table_t));
-
- if (table == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
-
- memset(table, 0, sizeof(ck_hash_table_t));
-
- // determine ideal size of one table in powers of 2 and save the
- // exponent
- table->table_size_exp = get_table_exp_and_count(items,
- &table->table_count);
- assert(table->table_size_exp <= 32);
-
- if (table->table_size_exp == 0) {
- dbg_ck("Failed to count exponent of the hash table.\n");
- free(table);
- return NULL;
- }
-
- dbg_ck("Creating hash table for %u items.\n", items);
- dbg_ck("Exponent: %u, number of tables: %u\n ",
- table->table_size_exp, table->table_count);
- dbg_ck("Table size: %u items, each %zu bytes, total %zu bytes\n",
- hashsize(table->table_size_exp),
- sizeof(ck_hash_table_item_t *),
- hashsize(table->table_size_exp)
- * sizeof(ck_hash_table_item_t *));
-
- // create tables
- for (uint t = 0; t < table->table_count; ++t) {
- dbg_ck("Creating table %u...\n", t);
- if (ck_new_table(&table->tables[t], table->table_size_exp)
- != 0) {
- for (uint i = 0; i < t; ++i) {
- free(table->tables[i]);
- }
- free(table);
- return NULL;
- }
- }
-
- assert(table->stash == NULL);
- assert(table->hashed == NULL);
- assert(table->items == 0);
- assert(table->items_in_stash == 0);
- assert(table->table_count == MAX_TABLES
- || table->tables[table->table_count] == NULL);
-
- // initialize rehash/insert mutex
- pthread_mutex_init(&table->mtx_table, NULL);
-
- // set the generation to 1 and initialize the universal system
- CLEAR_FLAGS(&table->generation);
- SET_GENERATION1(&table->generation);
-
- us_initialize(&table->hash_system);
-
- return table;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ck_destroy_table(ck_hash_table_t **table, void (*dtor_value)(void *value),
- int delete_key)
-{
- assert(table);
- assert(*table);
- pthread_mutex_lock(&(*table)->mtx_table);
-
- // destroy items in tables
- for (uint i = 0; i < hashsize((*table)->table_size_exp); ++i) {
- for (uint t = 0; t < (*table)->table_count; ++t) {
- if ((*table)->tables[t][i] != NULL) {
- if (dtor_value) {
- dtor_value(
- (*table)->tables[t][i]->value);
- }
- if (delete_key != 0) {
- free(
- (void *)(*table)->tables[t][i]->key);
- }
- free((void *)(*table)->tables[t][i]);
- }
- }
- }
-
- // destroy items in stash
- ck_stash_item_t *item = (*table)->stash;
- while (item != NULL) {
- // disconnect the item
- (*table)->stash = item->next;
-
- /*! \todo Check item semantics. (#1688) */
- if (item->item != NULL) {
- if (dtor_value) {
- dtor_value(item->item->value);
- }
- if (delete_key) {
- free((void *)item->item->key);
- }
-
- free((void *)item->item);
- }
-
- free(item);
- item = (*table)->stash;
- }
-
- // deallocate tables
- for (uint t = 0; t < (*table)->table_count; ++t) {
- free((*table)->tables[t]);
- }
-
- pthread_mutex_unlock(&(*table)->mtx_table);
- // destroy mutex, assuming that here noone will lock the mutex again
- pthread_mutex_destroy(&(*table)->mtx_table);
-
- free(*table);
- (*table) = NULL;
-}
-
-void ck_table_free(ck_hash_table_t **table)
-{
- if (table == NULL || *table == NULL) {
- return;
- }
-
- pthread_mutex_lock(&(*table)->mtx_table);
-
- ck_stash_item_t *item = (*table)->stash;
- while (item != NULL) {
- // disconnect the item
- (*table)->stash = item->next;
- free(item);
- item = (*table)->stash;
- }
-
- // deallocate tables
- for (uint t = 0; t < (*table)->table_count; ++t) {
- free((*table)->tables[t]);
- }
-
- pthread_mutex_unlock(&(*table)->mtx_table);
- pthread_mutex_destroy(&(*table)->mtx_table);
-
- free(*table);
- (*table) = NULL;
-}
-
-int ck_resize_table(ck_hash_table_t *table)
-{
- dbg_ck("Resizing hash table.\n");
-
- /*
- * Easiest is just to increment the exponent, resulting in doubling
- * the table sizes. This is not very memory-effective, but should do
- * the job.
- */
-
- if (table->table_size_exp == 31) {
- dbg_ck("Hash tables achieved max size (exponent 31).\n");
- return -1;
- }
-
- ck_hash_table_item_t **tables_new[MAX_TABLES];
- ck_hash_table_item_t **tables_old[MAX_TABLES];
- int exp_new = table->table_size_exp + 1;
-
- dbg_ck_verb("New tables exponent: %d\n", exp_new);
-
- for (int t = 0; t < table->table_count; ++t) {
- if (ck_new_table(&tables_new[t], exp_new) != 0) {
- dbg_ck("Failed to create new table.\n");
- for (int i = 0; i < t; ++i) {
- free(tables_new[i]);
- }
- return -1;
- }
- }
-
- dbg_ck("Created new tables, copying data to them.\n");
-
- for (int t = 0; t < table->table_count; ++t) {
- size_t old_size = hashsize(table->table_size_exp)
- * sizeof(ck_hash_table_item_t *);
-
- // copy the old table items
- dbg_ck_verb("Copying to: %p, from %p, size: %zu\n",
- tables_new[t], table->tables[t], old_size);
- memcpy(tables_new[t], table->tables[t], old_size);
- // set the rest to 0
- dbg_ck_verb("Setting to 0 from %p, size %zu\n",
- tables_new[t] + hashsize(table->table_size_exp),
- (hashsize(exp_new) * sizeof(ck_hash_table_item_t *))
- - old_size);
- memset(tables_new[t] + hashsize(table->table_size_exp), 0,
- (hashsize(exp_new) * sizeof(ck_hash_table_item_t *))
- - old_size);
- }
-
- dbg_ck("Done, switching the tables and running rehash.\n");
-
-
- memcpy(tables_old, table->tables,
- MAX_TABLES * sizeof(ck_hash_table_item_t **));
- memcpy(table->tables, tables_new,
- MAX_TABLES * sizeof(ck_hash_table_item_t **));
-
- table->table_size_exp = exp_new;
-
- // delete the old tables
- for (int t = 0; t < table->table_count; ++t) {
- free(tables_old[t]);
- }
-
- return ck_rehash(table);
-}
-
-int ck_insert_item(ck_hash_table_t *table, const char *key,
- size_t length, void *value)
-{
- // lock mutex to avoid write conflicts
- pthread_mutex_lock(&table->mtx_table);
-
- assert(value != NULL);
-
- dbg_ck_hash("Inserting item with key: %.*s.\n", (int)length, key);
- dbg_ck_hash_hex(key, length);
- dbg_ck_hash("\n");
-
- // create item structure and fill in the given data, key won't be copied
- ck_hash_table_item_t *new_item =
- (ck_hash_table_item_t *)malloc((sizeof(ck_hash_table_item_t)));
- ck_fill_item(key, length, value, GET_GENERATION(table->generation),
- new_item);
-
- // check if the table is not full; if yes, resize and rehash!
- if (ck_is_full(table)) {
- dbg_ck("Table is full, resize needed.\n");
- if (ck_resize_table(table) != 0) {
- dbg_ck("Failed to resize hash table!\n");
- free(new_item);
- pthread_mutex_unlock(&table->mtx_table);
- return -1;
- }
- }
-
- ck_hash_table_item_t *free_place = NULL;
- if (ck_hash_item(table, &new_item, &free_place,
- table->generation) != 0) {
-
- dbg_ck("Adding item with key %.*s to stash.\n",
- (int)free_place->key_length, free_place->key);
-
- // maybe some limit on the stash and rehash if full
- if (ck_add_to_stash(table, free_place) != 0) {
- dbg_ck_hash("Could not add item to stash!!\n");
- assert(0);
- }
-
- if (ck_stash_is_full(table)) {
- dbg_ck("Stash is full, resize needed.\n");
- if (ck_resize_table(table) != 0) {
- dbg_ck("Failed to resize hash table!\n");
- /*! \todo Shouldn't 'new_item' be freed? */
- pthread_mutex_unlock(&table->mtx_table);
- return -1;
- }
- }
- }
-
- ++table->items;
- pthread_mutex_unlock(&table->mtx_table);
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-const ck_hash_table_item_t *ck_find_item(const ck_hash_table_t *table,
- const char *key, size_t length)
-{
- dbg_ck("ck_find_item(), key: %.*s, size: %zu\n",
- (int)length, key, length);
-
- ck_hash_table_item_t **found = ck_find_item_nc(table, key, length);
-
- return (found == NULL) ? NULL : rcu_dereference(*found);
-}
-
-/*----------------------------------------------------------------------------*/
-
-int ck_update_item(const ck_hash_table_t *table, const char *key, size_t length,
- void *new_value, void (*dtor_value)(void *value))
-{
- rcu_read_lock(); // is needed?
-
- assert(new_value != NULL);
-
- ck_hash_table_item_t **item = ck_find_item_nc(table, key, length);
-
- if (item == NULL || (*item) == NULL) {
- rcu_read_unlock();
- return -1;
- }
-
- void *old = rcu_xchg_pointer(&(*item)->value, new_value);
- rcu_read_unlock();
-
- synchronize_rcu();
- if (dtor_value) {
- dtor_value(old);
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int ck_delete_item(const ck_hash_table_t *table, const char *key, size_t length,
- void (*dtor_value)(void *value), int delete_key)
-{
- rcu_read_lock(); // is needed?
- ck_hash_table_item_t **place = ck_find_item_nc(table, key, length);
-
- if (place == NULL) {
- rcu_read_unlock();
- return -1;
- }
-
- ck_hash_table_item_t *item = *place;
-
- assert(item != NULL);
-
- ck_put_item(place, NULL);
- rcu_read_unlock();
-
- synchronize_rcu();
- if (dtor_value) {
- dtor_value(item->value);
- }
- item->value = NULL;
- if (delete_key != 0) {
- free((void *)item->key);
- }
- free(item);
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-ck_hash_table_item_t *ck_remove_item(ck_hash_table_t *table, const char *key,
- size_t length)
-{
- ck_hash_table_item_t **place = ck_find_item_nc(table, key, length);
- if (place == NULL) {
- return NULL;
- }
-
- ck_hash_table_item_t *item = *place;
- *place = NULL;
- return item;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int ck_shallow_copy(const ck_hash_table_t *from, ck_hash_table_t **to)
-{
- dbg_ck("ck_shallow_copy()\n");
-
- if (from == NULL || to == NULL) {
- return -1;
- }
-
- *to = (ck_hash_table_t *)malloc(sizeof(ck_hash_table_t));
-
- if (*to == NULL) {
- ERR_ALLOC_FAILED;
- return -2;
- }
- memset(*to, 0, sizeof(ck_hash_table_t));
-
- // copy table count and table size exponent
- (*to)->table_size_exp = from->table_size_exp;
- (*to)->table_count = from->table_count;
- assert((*to)->table_size_exp <= 32);
-
- dbg_ck("Creating hash table for %u items.\n", from->table_count);
- dbg_ck("Exponent: %u, number of tables: %u\n ",
- (*to)->table_size_exp, (*to)->table_count);
- dbg_ck("Table size: %u items, each %zu bytes, total %zu bytes\n",
- hashsize((*to)->table_size_exp),
- sizeof(ck_hash_table_item_t *),
- hashsize((*to)->table_size_exp)
- * sizeof(ck_hash_table_item_t *));
-
- // create tables
- for (uint t = 0; t < (*to)->table_count; ++t) {
- dbg_ck("Creating table %u...\n", t);
- (*to)->tables[t] = (ck_hash_table_item_t **)malloc(
- hashsize((*to)->table_size_exp)
- * sizeof(ck_hash_table_item_t *));
- if ((*to)->tables[t] == NULL) {
- ERR_ALLOC_FAILED;
- for (uint i = 0; i < t; ++i) {
- free((*to)->tables[i]);
- }
- free(*to);
- return -2;
- }
-
- // copy the table
- memcpy((*to)->tables[t], from->tables[t],
- hashsize((*to)->table_size_exp)
- * sizeof(ck_hash_table_item_t *));
- }
-
- // copy the stash - we must explicitly copy each stash item, but do not
- // copy the ck_hash_table_item_t within them.
- ck_stash_item_t *si = from->stash;
- ck_stash_item_t *last = NULL;
- dbg_ck_verb("Copying hash table stash.\n");
- while (si != NULL) {
- ck_stash_item_t *si_new = (ck_stash_item_t *)
- malloc(sizeof(ck_stash_item_t));
- if (si_new == NULL) {
- ERR_ALLOC_FAILED;
- // delete tables
- for (uint i = 0; i < (*to)->table_count; ++i) {
- free((*to)->tables[i]);
- }
- // delete created stash items
- si_new = (*to)->stash;
- while (si_new != NULL) {
- ck_stash_item_t *prev = si_new;
- si_new = si_new->next;
- free(prev);
- }
- free(*to);
- return -2;
- }
-
- dbg_ck_detail("Copying stash item: %p with item %p, key: %.*s"
- "\n", si, si->item, (int)si->item->key_length,
- si->item->key);
-
- si_new->item = si->item;
- si_new->next = NULL;
- if (last == NULL) {
- (*to)->stash = si_new;
- } else {
- last->next = si_new;
- }
- last = si_new;
- si = si->next;
-
-dbg_ck_exec_detail(
- dbg_ck_detail("Old stash item: %p with item %p, \n", si,
- ((si == NULL) ? NULL : si->item));
- if (si != NULL) {
- dbg_ck_detail("key: %.*s\n", (int)si->item->key_length,
- si->item->key);
- }
- dbg_ck_detail("New stash item: %p with item %p, ", si_new,
- si_new->item);
- dbg_ck_detail("key: %.*s\n", (int)si_new->item->key_length,
- si_new->item->key);
-);
- }
-
- // there should be no item being hashed right now
- /*! \todo This operation should not be done while inserting / rehashing.
- */
- assert(from->hashed == NULL);
- (*to)->hashed = NULL;
-
- // initialize rehash/insert mutex
- pthread_mutex_init(&(*to)->mtx_table, NULL);
-
- // copy the generation
- (*to)->generation = from->generation;
-
- // copy the hash functions
- memcpy(&(*to)->hash_system, &from->hash_system, sizeof(us_system_t));
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int ck_copy_items(ck_hash_table_item_t **from,
- ck_hash_table_item_t **to, uint32_t count)
-{
- assert(from != NULL);
- assert(to != NULL);
-
- for (int i = 0; i < count; ++i) {
- if (from[i] != NULL) {
- to[i] = (ck_hash_table_item_t *)
- malloc(sizeof(ck_hash_table_item_t));
-
- if (to[i] == NULL) {
- return -2;
- }
-
- memcpy(to[i], from[i], sizeof(ck_hash_table_item_t));
- } else {
- to[i] = NULL;
- }
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ck_deep_copy_cleanup(ck_hash_table_t *table, int table_count)
-{
- // free tables with their items
- for (int t = 0; t < table_count; ++t) {
- for (int i = 0; i < hashsize(table->table_size_exp); ++i) {
- free(table->tables[t][i]);
- }
- free(table->tables[t]);
- }
-
- // free stash items with hash table items in them
- ck_stash_item_t *si = table->stash;
- ck_stash_item_t *to_free;
- while (si != NULL) {
- to_free = si;
- si = si->next;
- free(to_free->item);
- free(to_free);
- }
-
- free(table);
-}
-
-/*----------------------------------------------------------------------------*/
-
-int ck_deep_copy(ck_hash_table_t *from, ck_hash_table_t **to)
-{
- dbg_ck("ck_deep_copy()\n");
-
- if (from == NULL || to == NULL) {
- return -1;
- }
-
- *to = (ck_hash_table_t *)malloc(sizeof(ck_hash_table_t));
-
- if (*to == NULL) {
- ERR_ALLOC_FAILED;
- return -2;
- }
- memset(*to, 0, sizeof(ck_hash_table_t));
-
- // copy table count and table size exponent
- (*to)->table_size_exp = from->table_size_exp;
- (*to)->table_count = from->table_count;
- assert((*to)->table_size_exp <= 32);
-
- dbg_ck("Creating hash table for %u items.\n", from->table_count);
- dbg_ck("Exponent: %u, number of tables: %u\n ",
- (*to)->table_size_exp, (*to)->table_count);
- dbg_ck("Table size: %u items, each %zu bytes, total %zu bytes\n",
- hashsize((*to)->table_size_exp),
- sizeof(ck_hash_table_item_t *),
- hashsize((*to)->table_size_exp)
- * sizeof(ck_hash_table_item_t *));
-
- // create tables
- for (uint t = 0; t < (*to)->table_count; ++t) {
- dbg_ck("Creating table %u...\n", t);
- (*to)->tables[t] = (ck_hash_table_item_t **)malloc(
- hashsize((*to)->table_size_exp)
- * sizeof(ck_hash_table_item_t *));
- if ((*to)->tables[t] == NULL) {
- ERR_ALLOC_FAILED;
- for (uint i = 0; i < t; ++i) {
- free((*to)->tables[i]);
- }
- free(*to);
- return -2;
- }
-
- // copy the table with all hash table items
- dbg_ck("Copying table %u...\n", t);
- int ret = ck_copy_items(from->tables[t], (*to)->tables[t],
- hashsize((*to)->table_size_exp));
- if (ret != 0) {
- dbg_ck("Failed!\n");
- // free all tables created until now
- ck_deep_copy_cleanup(*to, t);
- return ret;
- }
- }
-
- // copy the stash - we must explicitly copy each stash item,
- // together with the hash table item stored in it
- ck_stash_item_t *si = from->stash;
- ck_stash_item_t **pos = &(*to)->stash;
- dbg_ck_verb("Copying hash table stash.\n");
- while (si != NULL) {
- ck_stash_item_t *si_new = (ck_stash_item_t *)
- malloc(sizeof(ck_stash_item_t));
- if (si_new == NULL) {
- ERR_ALLOC_FAILED;
- ck_deep_copy_cleanup(*to, (*to)->table_count);
- return -2;
- }
-
- dbg_ck_detail("Copying stash item: %p with item %p.\n", si,
- si->item);
-
- if (si->item == NULL) {
- dbg_stash("[EMPTY STASH] [FIND] STASH ITEM IS EMPTY: "
- "%p (%p)\n", si, si->item);
- si_new->item = NULL;
- si_new->next = NULL;
- } else {
- si_new->item = (ck_hash_table_item_t *)
- malloc(sizeof(ck_hash_table_item_t));
-
- if (si_new->item == NULL) {
- ERR_ALLOC_FAILED;
- free(si_new);
- ck_deep_copy_cleanup(*to, (*to)->table_count);
- return -2;
- }
-
- memcpy(si_new->item, si->item,
- sizeof(ck_hash_table_item_t));
- si_new->next = NULL;
- }
-
- *pos = si_new;
- pos = &si_new->next;
- si = si->next;
-
-dbg_ck_exec_detail(
- dbg_ck_detail("Old stash item: %p with item %p, \n", si,
- ((si == NULL) ? NULL : si->item));
- if (si != NULL && si->item != NULL) {
- dbg_ck_detail("key: %.*s\n", (int)si->item->key_length,
- si->item->key);
- }
- dbg_ck_detail("New stash item: %p with item %p, ", si_new,
- (si_new) ? si_new->item : NULL);
-
- assert(si_new != NULL);
- if (si_new->item != NULL) {
- dbg_ck_detail("key: %.*s\n", (int)si_new->item->key_length,
- si_new->item->key);
- }
-);
- }
-
- *pos = NULL;
-
- // there should be no item being hashed right now
- /*! \todo This operation should not be done while inserting / rehashing.
- */
- assert(from->hashed == NULL);
- (*to)->hashed = NULL;
-
- // initialize rehash/insert mutex
- pthread_mutex_init(&(*to)->mtx_table, NULL);
-
- // copy the generation
- (*to)->generation = from->generation;
-
- // copy the hash functions
- memcpy(&(*to)->hash_system, &from->hash_system, sizeof(us_system_t));
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int ck_apply(ck_hash_table_t *table,
- void (*function)(ck_hash_table_item_t *item, void *data),
- void *data)
-{
- if (table == NULL || function == NULL) {
- return -1;
- }
-
- /*! \todo Ensure that no insertion nor rehash is made during applying.*/
-
- // apply the function to all items in all tables
- for (int t = 0; t < table->table_count; ++t) {
- for (int i = 0; i < hashsize(table->table_size_exp); ++i) {
- function(table->tables[t][i], data);
- }
- }
-
- // apply the function to the stash items
- ck_stash_item_t *si = table->stash;
- while (si != NULL) {
- function(si->item, data);
- si = si->next;
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int ck_rehash(ck_hash_table_t *table)
-{
- dbg_ck_hash("Rehashing items in table.\n");
- if (!table) {
- return -1;
- }
- SET_REHASHING_ON(&table->generation);
-
- ck_stash_item_t *free_stash_items = NULL;
-
- do {
- // 1) Rehash items from stash
- dbg_ck_hash_verb("Rehashing items from stash.\n");
- ck_stash_item_t *item = table->stash;
- ck_stash_item_t **item_place = &table->stash;
- // terminate when at the end; this way the newly added items
- // (added to the beginning) will be properly ignored
- while (item != NULL) {
- dbg_ck_hash_detail("Rehashing item with "
- "key (length %zu): %.*s, generation: %hu, "
- "table generation: %hu.\n", item->item->key_length,
- (int)item->item->key_length, item->item->key,
- GET_GENERATION(
- item->item->timestamp),
- GET_GENERATION(table->generation));
-
- // put the hashed item to the prepared space
- table->hashed = item->item;
- item->item = NULL;
- // we may use the place in the stash item as the free
- // place for rehashing
- if (ck_hash_item(table, &table->hashed, &item->item,
- NEXT_GENERATION(table->generation)) != 0) {
- // the free place was used
- assert(item->item != NULL);
- // we may leave the item there (in the stash)
- assert(EQUAL_GENERATIONS(item->item->timestamp,
- NEXT_GENERATION(table->generation)));
- //assert(item->item == table->hashed);
-
- item_place = &item->next;
- item = item->next;
- } else {
- // the free place should be free
- assert(item->item == NULL);
- // and the item should be hashed too
-// assert(table->hashed == NULL);
- dbg_stash("[EMPTY STASH] [CREATE] Created empty"
- " item: %p (%p)\n", item, item->item);
-
- // fix the pointer from the previous hash item
- *item_place = item->next;
- // and do not change the item place pointer
-
- // put the stash item into list of free stash
- // items
- item->next = free_stash_items;
- free_stash_items = item;
-
- item = *item_place;
- }
- }
-
- // 2) Rehash items from tables
-
- // in case of failure, save the item in a temp variable
- // which will be put to the stash
- ck_hash_table_item_t *free = NULL;
- assert(table->hashed == NULL);
-
- for (uint t = 0; t < table->table_count; ++t) {
- uint rehashed = 0;
-
- dbg_ck_hash_verb("Rehashing table %d.\n", t);
-
- while (rehashed < hashsize(table->table_size_exp)) {
-
- // if item's generation is the new generation,
- // skip
- if (table->tables[t][rehashed] == NULL
- || !(EQUAL_GENERATIONS(
- table->tables[t][rehashed]->timestamp,
- table->generation))) {
- dbg_ck_hash_detail("Skipping item.\n");
- ++rehashed;
- continue;
- }
-
- dbg_ck_hash_detail("Rehashing item with hash %u"
- ", key (length %zu): %.*s, generation: %hu, "
- "table generation: %hu.\n", rehashed,
- table->tables[t][rehashed]->key_length,
- (int)(table->tables[t][rehashed]->key_length),
- table->tables[t][rehashed]->key,
- GET_GENERATION(
- table->tables[t][rehashed]->timestamp),
- GET_GENERATION(table->generation));
-
- // otherwise copy the item for rehashing
- ck_put_item(&table->hashed, table->tables[t][rehashed]);
- // clear the place so that this item will not
- // get rehashed again
- ck_clear_item(&table->tables[t][rehashed]);
-
- dbg_ck_hash_detail("Table generation: %hu, next"
- " generation: %hu.\n",
- GET_GENERATION(table->generation),
- NEXT_GENERATION(table->generation));
-
- if (ck_hash_item(table, &table->hashed, &free,
- NEXT_GENERATION(table->generation)) != 0) {
- // loop occured
- dbg_ck_hash("Hashing entered a loop."
- "\n");
- dbg_ck_hash_verb("Item with key %.*s "
- "inserted into the free slot.\n",
- free->key_length, free->key);
-
- //assert(old == free);
-
- // put the item into the stash, but
- // try the free stash items first
- if (free_stash_items != NULL) {
- // take first
- ck_stash_item_t *item =
- free_stash_items;
- free_stash_items = item->next;
-
- if (free == NULL) {
- dbg_stash("[EMPTY STASH] "
- "[CREATE] STORING NULL"
- " in the stash\n");
- }
-
- item->item = free;
- item->next = table->stash;
- table->stash = item;
- } else {
- if (ck_add_to_stash(table, free)
- != 0) {
- ck_rollback_rehash(
- table);
- }
- }
-
- free = NULL;
- table->hashed = NULL;
- }
- ++rehashed;
- }
- }
-
- dbg_ck_hash("Old table generation: %u\n",
- GET_GENERATION(table->generation));
- // rehashing completed, switch generation of the table
- SET_NEXT_GENERATION(&table->generation);
- dbg_ck_hash("New table generation: %u\n",
- GET_GENERATION(table->generation));
- // generate new hash functions for the old generation
- dbg_ck_hash("Generating coeficients for generation: %u\n",
- NEXT_GENERATION(table->generation));
- us_next(&table->hash_system,
- NEXT_GENERATION(table->generation));
-
- } while (false /*! \todo Add proper condition!! */);
-
- SET_REHASHING_OFF(&table->generation);
-
- assert(table->hashed == NULL);
-
-
- while (free_stash_items != NULL) {
- ck_stash_item_t *item = free_stash_items;
- free_stash_items = item->next;
- assert(item->item == NULL);
- free(item);
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void ck_dump_table(const ck_hash_table_t *table)
-{
-#ifdef CUCKOO_DEBUG
- uint i = 0;
- dbg_ck("----------------------------------------------\n");
- dbg_ck("Hash table dump:\n\n");
- dbg_ck("Size of each table: %u\n\n", hashsize(table->table_size_exp));
-
- for (uint t = 0; t < table->table_count; ++t) {
- dbg_ck("Table %d:\n", t + 1);
-
- for (i = 0; i < hashsize(table->table_size_exp); i++) {
- dbg_ck("Hash: %u, Key: %.*s, Value: %p.\n", i,
- (int)(table->tables[t])[i]->key_length,
- (table->tables[t])[i]->key,
- (table->tables[t])[i]->value);
- }
- }
-
- dbg_ck("Stash:\n");
- ck_stash_item_t *item = table->stash;
- while (item != NULL) {
- dbg_ck("Hash: %u, Key: %.*s, Value: %p.\n", i,
- (int)item->item->key_length, item->item->key,
- item->item->value);
- item = item->next;
- }
-
- dbg_ck("\n");
-#endif
-}
diff --git a/src/libknot/hash/cuckoo-hash-table.h b/src/libknot/hash/cuckoo-hash-table.h
deleted file mode 100644
index c0fe9cc..0000000
--- a/src/libknot/hash/cuckoo-hash-table.h
+++ /dev/null
@@ -1,334 +0,0 @@
-/*!
- * \file cuckoo-hash-table.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Implementation of Cuckoo hashing scheme.
- *
- * Uses d-ary Cuckoo hashing with stash.
- *
- * \todo Maybe provide some way to resize the whole table if the number of items
- * grows too much.
- * \todo Check size of integers, the table size may be larger than unsigned int.
- * \todo Maybe do not return ck_hash_table_item from ck_find_item(), but only
- * its value.
- * \todo When hashing an item, only the first table is tried for this item.
- * We may try all tables. (But it is not neccessary.)
- *
- * \addtogroup hashing
- * @{
- */
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOT_CUCKOO_HASH_TABLE_H_
-#define _KNOT_CUCKOO_HASH_TABLE_H_
-
-#include <stdint.h> /* uint32_t */
-#include <stdlib.h> /* size_t */
-#include <pthread.h>
-
-#include "hash/universal-system.h"
-
-/*----------------------------------------------------------------------------*/
-
-/*! \brief Macro for getting one hash table size. */
-#define hashsize(n) ((uint32_t)1 << (n))
-
-/*!
- * \brief Max number of hash tables - must be the same as number of the hash
- * functions in each generation of the universal system.
- */
-#define MAX_TABLES US_FNC_COUNT
-
-/*! \brief Default stash size. */
-static const uint STASH_SIZE = 10;
-
-/*! \brief Maximum stash size. When achieved, rehashing is needed. */
-static const uint STASH_SIZE_MAX = 30;
-
-/*----------------------------------------------------------------------------*/
-/* Public structures */
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Structure for storing the hashed data.
- */
-struct ck_hash_table_item {
- const char *key; /*!< Key of the item, used for hashing. */
-
- size_t key_length; /*!< Length of the key in octets. */
-
- void *value; /*!< The actual item stored in the table. */
-
- /*!
- * \brief Flags. Currently used for keeping the generation of the item,
- * i.e. the generation of the functions used for hashing this
- * item.
- *
- * Form: 000000xy;
- * xy - generation; may be 01 (1) or 10 (2).
- */
- uint8_t timestamp;
-};
-
-typedef struct ck_hash_table_item ck_hash_table_item_t;
-
-struct ck_stash_item {
- ck_hash_table_item_t *item;
- struct ck_stash_item *next;
-};
-
-typedef struct ck_stash_item ck_stash_item_t;
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Hash table structure which uses cuckoo hashing.
- *
- * Keys are expected to be strings of characters (char *), not necesarily
- * null-terminated. It uses the Fowler/Noll/Vo (FNV) hash function to
- * obtain a 32bit unsigned integer from the character data and a function
- * randomly chosen from an universal system (see universal-system.h) to obtain
- * the final hash. The FNV hash was taken from
- * http://home.comcast.net/~bretm/hash/6.html and the universal system is
- * constructed according to Katajainen J., Lykke M., Experiments with universal
- * hashing (obtained from
- * http://www.diku.dk/OLD/publikationer/tekniske.rapporter/rapporter/96-08.pdf).
- *
- * The table uses either 3-ary or 4-ary cuckoo hashing (and thus 3 or 4 tables)
- * with stash, according to the number of items provided to ck_create_table()
- * function. The number of table pointers is however set to be the larger value
- * (4) always, so the \a tables array may be statically allocated. Size of one
- * table is always a power of 2 (due to the character of the hash function).
- * The stash has a default size STASH_SIZE, but can be resized if needed.
- * However, the resizing is only done in rehashing process, if the items do not
- * fit into the table and the original stash.
- *
- * Rehashing is done when the stash gets full (actually, last item is always
- * free and is used in the rehashing process as a temporary variable).
- */
-struct ck_hash_table {
- uint table_count; /*!< Actual number of hash tables used. */
-
- /*!
- * \brief Exponent of one table's size (2^table_size_exp is table size).
- */
- int table_size_exp;
-
- ck_hash_table_item_t **tables[MAX_TABLES]; /*!< Array of hash tables. */
-
- //da_array_t stash; /*!< Stash implemented as a dynamic array. */
- ck_stash_item_t *stash;
-
- /*! \brief Temporary storage for item being hashed. */
- ck_hash_table_item_t *hashed;
-
- /*! \brief Mutex for avoiding multiple insertions / rehashes at once. */
- pthread_mutex_t mtx_table;
-
- /*!
- * \brief Flags used for determining which hash functions are currently
- * used
- *
- * Form: 00000xyz.
- * x - rehash flag (1 if rehashing is in progress)
- * yz - generation (may be 10 = 2, or 01 = 1)
- *
- * There are always two sets of hash functions available via the
- * us_hash() function (see universal-hashing.h). Normally all items in
- * the table are hashed using one set of functions. However, during
- * rehash, the other set is used for rehashing. In this case the rehash
- * flag (x) is set, so the lookup function (ck_find_item()) tries to use
- * both sets of functions when searching for item.
- */
- uint8_t generation;
-
- us_system_t hash_system; /*!< Universal system of hash functions. */
-
- size_t items;
- size_t items_in_stash;
-};
-
-typedef struct ck_hash_table ck_hash_table_t;
-
-/*----------------------------------------------------------------------------*/
-/* API functions */
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Creates and initializes the hash table structure.
- *
- * All hash tables are allocated and their items initialized to 0 (NULL).
- * A stash of default size is also created. The \a generation flags are set to
- * 0.
- *
- * \param items Number of items to be hashed to the table. This number
- * determines the size of the hash table that will be created.
- *
- *
- * \return Pointer to the initialized hash table.
- */
-ck_hash_table_t *ck_create_table(uint items);
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Destroys the whole hash table together with the saved values.
- *
- * \param table Pointer to pointer to the hash table.
- * \param dtor_value Destructor function for the values that are be stored in
- * the hash table. Set to NULL if you do not want the values
- * to be deleted.
- * \param delete_key Set to 0 if you do not want the function to delete the
- * key of the item (e.g. when used elsewhere). Set to any
- * other value otherwise.
- *
- * \note Make sure the table and its items are not used anymore when calling
- * this function.
- */
-void ck_destroy_table(ck_hash_table_t **table,
- void (*dtor_value)(void *value), int delete_key);
-
-/*!
- * \brief Destroys the table structures, but does not remove the individual
- * hash table items.
- */
-void ck_table_free(ck_hash_table_t **table);
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Inserts item into the hash table.
- *
- * Insertion starts always by trying to hash the item into the first table. The
- * possible displaced item is then hashed into randomly chosen other table,
- * etc., until a free place is found or a loop occured. A loop occurs when one
- * position in one table is tried more than twice.
- *
- * \param table Hash table the item should be inserted into.
- * \param key Item's key. It can be any string of octets. The key is not copied
- * by the function.
- * \param length Length of the key in bytes (octets).
- * \param value Pointer to the actual item to be inserted into the hash table.
- *
- * \note This function does not copy the key.
- * \note This function may trigger rehash of the whole table in case the stash
- * gets full.
- *
- * \retval 0 No error.
- * \retval -1 Insertion failed. This may occur only when the rehashing fails.
- * In this case it is necessary to somehow manually force another
- * rehash as no other rehash would be possible.
- */
-int ck_insert_item(ck_hash_table_t *table, const char *key, size_t length,
- void *value);
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Finds item in table.
- *
- * \param table Hash table to search in.
- * \param key Key of the item. It can be an arbitrary string of octets.
- * \param length Length of the key in bytes (octets).
- *
- * \return Pointer to the item if found. NULL otherwise.
- */
-const ck_hash_table_item_t *ck_find_item(const ck_hash_table_t *table,
- const char *key, size_t length);
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Updates item with the given key by replacing its value.
- *
- * The update process is synchronized using RCU mechanism, so the old item's
- * value will not be deleted while some thread is using it.
- *
- * \param table Hash table where to search for the item.
- * \param key Key of the item to be updated. It can be an arbitrary string of
- * octets.
- * \param length Length of the key in bytes (octets).
- * \param new_value New value for the item with key \a key.
- * \param dtor_value Destructor function for the values that are be stored in
- * the hash table. Set to NULL if you do not want the values
- * to be deleted.
- *
- * \retval 0 If successful.
- * \retval -1 If the item was not found in the table. No changes are made.
- */
-int ck_update_item(const ck_hash_table_t *table, const char *key, size_t length,
- void *new_value, void (*dtor_value)(void *value));
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Removes item with the given key from table.
- *
- * The deletion process is synchronized using RCU mechanism, so the old item
- * will not be deleted while some thread is using it.
- *
- * \param table Hash table where to search for the item.
- * \param key Key of the item to be removed. It can be an arbitrary string of
- * octets.
- * \param length Length of the key in bytes (octets).
- * \param dtor_value Destructor function for the values that are be stored in
- * the hash table. Set to NULL if you do not want the values
- * to be deleted.
- * \param delete_key Set to 0 if you do not want the function to delete the
- * key of the item (e.g. when used elsewhere). Set to any
- * other value otherwise.
- *
- * \retval 0 If successful.
- * \retval -1 If the item was not found in the table.
- */
-int ck_delete_item(const ck_hash_table_t *table, const char *key, size_t length,
- void (*dtor_value)(void *value), int delete_key);
-
-ck_hash_table_item_t *ck_remove_item(ck_hash_table_t *table, const char *key,
- size_t length);
-
-/*!
- * \brief Creates a shallow copy of the cuckoo hash table.
- *
- * This function creates just the ck_hash_table_t structure and its tables and
- * stash. It does not copy individual ck_hash_table_item_t structures.
- *
- * \param from Table to copy.
- * \param to The new copy will be stored here.
- *
- * \retval 0 if successful.
- * \retval
- */
-int ck_shallow_copy(const ck_hash_table_t *from, ck_hash_table_t **to);
-
-int ck_deep_copy(ck_hash_table_t *from, ck_hash_table_t **to);
-
-int ck_apply(ck_hash_table_t *table,
- void (*function)(ck_hash_table_item_t *item, void *data),
- void *data);
-
-/*----------------------------------------------------------------------------*/
-
-int ck_rehash(ck_hash_table_t *table);
-
-// for testing purposes only
-int ck_resize_table(ck_hash_table_t *table);
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Dumps the whole hash table to the standard output.
- */
-void ck_dump_table(const ck_hash_table_t *table);
-
-/*----------------------------------------------------------------------------*/
-
-#endif /* _KNOT_CUCKOO_HASH_TABLE_H_ */
-
-/*! @} */
diff --git a/src/libknot/hash/hash-functions.c b/src/libknot/hash/hash-functions.c
deleted file mode 100644
index a33dd6b..0000000
--- a/src/libknot/hash/hash-functions.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-#include "hash-functions.h"
-
-/*--------------------------------- FNV HASH ---------------------------------*/
-
-unsigned long int fnv_hash(const char *data, int size, int bits)
-{
- int shift, i;
- unsigned long int mask;
- unsigned long int hash = 2166136261;
-
- if (bits == -1) {
- shift = 0;
- mask = 0xFFFFFFFF;
- } else {
- shift = 32 - bits;
- mask = (1U << shift) - 1U;
- }
-
- for (i = 0; i < size; i++) {
- hash = (hash * 16777619) ^ data[i];
- }
-
- if (shift == 0) {
- return hash;
- }
-
- return (hash ^(hash >> shift)) & mask;
-}
-
-/*------------------------------- JENKINS HASH -------------------------------*/
-
-/* The mixing step */
-/*
-#define mix(a,b,c) \
- { \
- a=a-b; a=a-c; a=a^(c>>13); \
- b=b-c; b=b-a; b=b^(a<<8); \
- c=c-a; c=c-b; c=c^(b>>13); \
- a=a-b; a=a-c; a=a^(c>>12); \
- b=b-c; b=b-a; b=b^(a<<16); \
- c=c-a; c=c-b; c=c^(b>>5); \
- a=a-b; a=a-c; a=a^(c>>3); \
- b=b-c; b=b-a; b=b^(a<<10); \
- c=c-a; c=c-b; c=c^(b>>15); \
- }
-*/
-
-///* The whole new hash function */
-//u4 jhash(register u1 *k, u4 length, u4 initval)
-//{
-// register u4 a, b, c; /* the internal state */
-// u4 len; /* how many key bytes still need mixing */
-
-// /* Set up the internal state */
-// len = length;
-// a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
-// c = initval; /* variable initialization of internal state */
-
-// /*---------------------------------------- handle most of the key */
-// while (len >= 12) {
-// a = a + (k[0] + ((u4)k[1] << 8)
-// + ((u4)k[2] << 16) + ((u4)k[3] << 24));
-// b = b + (k[4] + ((u4)k[5] << 8)
-// + ((u4)k[6] << 16) + ((u4)k[7] << 24));
-// c = c + (k[8] + ((u4)k[9] << 8)
-// + ((u4)k[10] << 16) + ((u4)k[11] << 24));
-// mix(a, b, c);
-// k = k + 12;
-// len = len - 12;
-// }
-
-// /*------------------------------------- handle the last 11 bytes */
-// c = c + length;
-// switch (len) { /* all the case statements fall through */
-// case 11:
-// c = c + ((u4)k[10] << 24);
-// case 10:
-// c = c + ((u4)k[9] << 16);
-// case 9 :
-// c = c + ((u4)k[8] << 8);
-// /* the first byte of c is reserved for the length */
-// case 8 :
-// b = b + ((u4)k[7] << 24);
-// case 7 :
-// b = b + ((u4)k[6] << 16);
-// case 6 :
-// b = b + ((u4)k[5] << 8);
-// case 5 :
-// b = b + k[4];
-// case 4 :
-// a = a + ((u4)k[3] << 24);
-// case 3 :
-// a = a + ((u4)k[2] << 16);
-// case 2 :
-// a = a + ((u4)k[1] << 8);
-// case 1 :
-// a = a + k[0];
-// /* case 0: nothing left to add */
-// }
-// mix(a, b, c);
-// /*-------------------------------------------- report the result */
-// return c;
-//}
-
-
-
-#define hashsize(n) ((ub4)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-
-/*
---------------------------------------------------------------------
-mix -- mix 3 32-bit values reversibly.
-For every delta with one or two bits set, and the deltas of all three
- high bits or all three low bits, whether the original value of a,b,c
- is almost all zero or is uniformly distributed,
-* If mix() is run forward or backward, at least 32 bits in a,b,c
- have at least 1/4 probability of changing.
-* If mix() is run forward, every bit of c will change between 1/3 and
- 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.)
-mix() was built out of 36 single-cycle latency instructions in a
- structure that could supported 2x parallelism, like so:
- a -= b;
- a -= c; x = (c>>13);
- b -= c; a ^= x;
- b -= a; x = (a<<8);
- c -= a; b ^= x;
- c -= b; x = (b>>13);
- ...
- Unfortunately, superscalar Pentiums and Sparcs can't take advantage
- of that parallelism. They've also turned some of those single-cycle
- latency instructions into multi-cycle latency instructions. Still,
- this is the fastest good hash I could find. There were about 2^^68
- to choose from. I only looked at a billion or so.
---------------------------------------------------------------------
-*/
-#define mix(a,b,c) \
-{ \
- 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); \
-}
-
-/*
---------------------------------------------------------------------
-hash() -- hash a variable-length key into a 32-bit value
- k : the key (the unaligned variable-length array of bytes)
- len : the length of the key, counting by bytes
- initval : can be any 4-byte value
-Returns a 32-bit value. Every bit of the key affects every bit of
-the return value. Every 1-bit and 2-bit delta achieves avalanche.
-About 6*len+35 instructions.
-
-The best hash table sizes are powers of 2. There is no need to do
-mod a prime (mod is sooo slow!). If you need less than 32 bits,
-use a bitmask. For example, if you need only 10 bits, do
- h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-
-If you are hashing n strings (ub1 **)k, do it like this:
- for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
-
-By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
-code any way you wish, private, educational, or commercial. It's free.
-
-See http://burtleburtle.net/bob/hash/evahash.html
-Use for hash table lookup, or anything where one collision in 2^^32 is
-acceptable. Do NOT use for cryptographic purposes.
---------------------------------------------------------------------
-*/
-
-ub4 jhash(k, length, initval)
-register ub1 *k; /* the key */
-register ub4 length; /* the length of the key */
-register ub4 initval; /* the previous hash, or an arbitrary value */
-{
- register ub4 a,b,c,len;
-
- /* Set up the internal state */
- len = length;
- a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- c = initval; /* the previous hash value */
-
- /*---------------------------------------- handle most of the key */
- while (len >= 12)
- {
- a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
- b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
- c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
- mix(a,b,c);
- k += 12; len -= 12;
- }
-
- /*------------------------------------- handle the last 11 bytes */
- c += length;
- switch(len) /* all the case statements fall through */
- {
- case 11: c+=((ub4)k[10]<<24);
- case 10: c+=((ub4)k[9]<<16);
- case 9 : c+=((ub4)k[8]<<8);
- /* the first byte of c is reserved for the length */
- case 8 : b+=((ub4)k[7]<<24);
- case 7 : b+=((ub4)k[6]<<16);
- case 6 : b+=((ub4)k[5]<<8);
- case 5 : b+=k[4];
- case 4 : a+=((ub4)k[3]<<24);
- case 3 : a+=((ub4)k[2]<<16);
- case 2 : a+=((ub4)k[1]<<8);
- case 1 : a+=k[0];
- /* case 0: nothing left to add */
- }
- mix(a,b,c);
- /*-------------------------------------------- report the result */
- return c;
-}
-
-#undef hashsize
-#undef hashmask
-
diff --git a/src/libknot/hash/hash-functions.h b/src/libknot/hash/hash-functions.h
deleted file mode 100644
index f23730b..0000000
--- a/src/libknot/hash/hash-functions.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*!
- * \file hash-functions.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Various hash functions.
- *
- * All of the hash functions are downloaded from various sources.
- *
- * \todo Add references to sources.
- *
- * \addtogroup hashing
- * @{
- */
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOT_HASH_FUNCTIONS_H_
-#define _KNOT_HASH_FUNCTIONS_H_
-
-#include <stdint.h>
-#include <string.h>
-
-/*
- * Fowler / Noll / Vo Hash (FNV Hash)
- * http://www.isthe.com/chongo/tech/comp/fnv/
- *
- * This is an implementation of the algorithms posted above.
- * This file is placed in the public domain by Peter Wemm.
- *
- * $FreeBSD: src/sys/sys/fnv_hash.h,v 1.2.2.1 2001/03/21 10:50:59 peter Exp $
- */
-
-typedef uint32_t Fnv32_t;
-
-#define FNV1_32_INIT ((Fnv32_t) 33554467UL)
-
-#define FNV_32_PRIME ((Fnv32_t) 0x01000193UL)
-
-static __inline Fnv32_t
-fnv_32_buf(const void *buf, size_t len, Fnv32_t hval)
-{
- const uint8_t *s = (const uint8_t *)buf;
-
- while (len-- != 0) {
- hval *= FNV_32_PRIME;
- hval ^= *s++;
- }
- return hval;
-}
-
-/*!
- * \brief Jenkins hash function.
- *
- * Downloaded from http://burtleburtle.net/bob/hash/evahash.html
- *
- * \param k Data to hash
- * \param length Size of the data in bytes.
- * \param initval The previous hash or an arbitrary value.
- *
- * \return Hash of the data.
- *
- * \todo Add source.
- */
-typedef unsigned long int ub4; /* unsigned 4-byte quantities */
-typedef unsigned char ub1; /* unsigned 1-byte quantities */
-
-ub4 jhash(register ub1 *k, register ub4 length, register ub4 initval);
-
-#endif /* _KNOT_HASH_FUNCTIONS_H_ */
-
-/*! @} */
diff --git a/src/libknot/hash/universal-system.c b/src/libknot/hash/universal-system.c
deleted file mode 100644
index 096974c..0000000
--- a/src/libknot/hash/universal-system.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-#include <limits.h>
-#include <stdint.h>
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "universal-system.h"
-#include "common.h"
-#include "util/utils.h"
-
-/*----------------------------------------------------------------------------*/
-
-const uint MAX_UINT_EXP = 32;
-const unsigned long MAX_UINT_MY = UINT32_MAX; /* 4294967295 */
-
-/*----------------------------------------------------------------------------*/
-/* Private functions */
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Generates new set of coeficients.
- *
- * \param system Universal system to generate the coeficients for.
- * \param from First coeficient to be replaced.
- * \param to Up to this the coeficients will be replaced.
- */
-static void us_generate_coefs(us_system_t *system, uint from, uint to)
-{
- assert(system != NULL);
-
- for (uint i = from; i < to; ++i) {
- int used = 0;
-
- do {
- // generate random odd number
- system->coefs[i] = knot_quick_rand() % MAX_UINT_MY;
- if (system->coefs[i] % 2 == 0) {
- system->coefs[i] = (system->coefs[i] == 0)
- ? 1
- : system->coefs[i] - 1;
- }
- // check if this coeficient is already used
- uint j = from;
- while (used == 0 && j < i) {
- if (system->coefs[j++] == system->coefs[i]) {
- used = 1;
- }
- }
- // if already used, generate again
- } while (used != 0);
- }
-}
-
-/*----------------------------------------------------------------------------*/
-/* Public functions */
-/*----------------------------------------------------------------------------*/
-
-void us_initialize(us_system_t *system)
-{
- assert(system != NULL);
- assert(UINT_MAX == MAX_UINT_MY);
-
- // Initialize both generations of functions by generating random odd
- // numbers
- us_generate_coefs(system, 0, US_FNC_COUNT * GEN_COUNT);
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \note \a generation starts from 1
- */
-int us_next(us_system_t *system, uint generation)
-{
- assert(system != NULL);
- // generate new coeficients for the new generation
- us_generate_coefs(system, (generation - 1) * US_FNC_COUNT,
- generation * US_FNC_COUNT);
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-uint32_t us_hash(const us_system_t *system, uint32_t value, uint table_exp,
- uint fnc, uint generation)
-{
- /*
- * multiplication should overflow if larger than MAX_UINT
- * this is the same as (coef * value) mod MAX_UINT
- *
- * TODO: maybe we should not rely on this
- */
- assert(system != NULL);
- assert(table_exp <= 32);
- assert(fnc < US_FNC_COUNT);
- assert(generation <= GEN_COUNT);
-
- return ((system->coefs[((generation - 1) * US_FNC_COUNT) + fnc] * value)
- >> (MAX_UINT_EXP - table_exp));
-}
diff --git a/src/libknot/hash/universal-system.h b/src/libknot/hash/universal-system.h
deleted file mode 100644
index 25330de..0000000
--- a/src/libknot/hash/universal-system.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*!
- * \file universal-system.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * This file provides interface to a 2-universal system of hash functions that
- * hash from 32-bit unsigned integer to a 32-bit unsigned integer within a given
- * range. The range is always a power of two and is given by the exponent (see
- * function us_hash().
- *
- * Before using the system, it must be initialized by calling us_initialize().
- * The system stores 2 sets (generations), each of US_FNC_COUNT functions.
- * For generating a new set of coeficients (i.e. hash functions) use the
- * us_next() function.
- *
- * For hashing use the us_hash() function.
- *
- * \todo What if all numbers are tried and still need rehash?
- * (that means 2mld rehashes - we can probably live with that ;)
- * \todo Consider counting generations from 0, will be easier!
- * \todo Check out some better random number generator.
- *
- * \addtogroup hashing
- * @{
- */
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOT_UNIVERSAL_SYSTEM_H_
-#define _KNOT_UNIVERSAL_SYSTEM_H_
-
-#include <stdint.h>
-#include "common.h"
-
-
-enum { US_FNC_COUNT = 4 /*!< Number of functions for one generation. */ };
-
-enum { GEN_COUNT = 2 /*!< Number of generations. */ };
-
-/*----------------------------------------------------------------------------*/
-/*! \brief Analytically defined universal system of hashing functions. */
-struct us_system {
- /*! \brief Coeficients for the functions */
- uint coefs[US_FNC_COUNT * GEN_COUNT];
-};
-
-typedef struct us_system us_system_t;
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Initializes the universal system by generating coeficients for all
- * hash functions and all generations.
- *
- * \param system Universal system to be used.
- */
-void us_initialize(us_system_t *system);
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Generates new hash functions' coeficients for the given \a generation.
- *
- * \param system Universal system to be used.
- * \param generation Generation for which to generate the new coeficients.
- *
- * \return 0
- */
-int us_next(us_system_t *system, uint generation);
-
-/*----------------------------------------------------------------------------*/
-
-/*!
- * \brief Hashes the \a value using the given \a exponent and function.
- *
- * The actual formula of the hash is:
- * h = ((coef * value) mod 2^32) / 2^(32 - table_exp)
- * where \a coef is the proper coeficient.
- *
- * \param system Universal system to be used.
- * \param value Value to be hashed.
- * \param table_exp Determines the upper bound for the result - the hash will
- * be between 0 and 2^(32 - table_exp).
- * \param fnc Which function from the set should be used.
- * \param generation Which set (generation) of functions should be used.
- *
- * \todo Make inline?
- *
- * \return Hash value (32bit unsigned).
- */
-uint32_t us_hash(const us_system_t *system, uint32_t value, uint table_exp,
- uint fnc, uint generation);
-
-/*----------------------------------------------------------------------------*/
-
-#endif /* _KNOT_UNIVERSAL_SYSTEM_H_ */
-
-/*! @} */
diff --git a/src/libknot/libknot.h b/src/libknot/libknot.h
index 287233d..c6a8c15 100644
--- a/src/libknot/libknot.h
+++ b/src/libknot/libknot.h
@@ -28,17 +28,22 @@
#define _KNOT_LIBKNOT_H_
#include "consts.h"
-#include "util/descriptor.h"
#include "dname.h"
#include "edns.h"
-#include "zone/node.h"
#include "nsec3.h"
-#include "util/wire.h"
-#include "rdata.h"
+#include "packet/packet.h"
+#include "packet/query.h"
#include "packet/response.h"
#include "rrset.h"
+#include "rrset-dump.h"
+#include "sign/key.h"
+#include "sign/sig0.h"
+#include "tsig.h"
+#include "tsig-op.h"
#include "util/tolower.h"
#include "util/utils.h"
+#include "util/wire.h"
+#include "zone/node.h"
#include "zone/zone.h"
#include "zone/zonedb.h"
diff --git a/src/libknot/nameserver/chaos.c b/src/libknot/nameserver/chaos.c
new file mode 100644
index 0000000..e548482
--- /dev/null
+++ b/src/libknot/nameserver/chaos.c
@@ -0,0 +1,139 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <strings.h>
+
+#include "chaos.h"
+#include "common/descriptor.h"
+#include "packet/packet.h"
+#include "packet/response.h"
+
+/*!
+ * \brief Get a string result for a given TXT query.
+ */
+static const char *get_txt_response_string(const knot_nameserver_t *nameserver,
+ const knot_dname_t *qname)
+{
+ char *qname_str = knot_dname_to_str(qname);
+ const char *response = NULL;
+
+ if (strcasecmp("id.server.", qname_str) == 0) {
+ response = nameserver->identity;
+ } else if (strcasecmp("version.server.", qname_str) == 0) {
+ response = nameserver->version;
+ } else if (strcasecmp("hostname.server.", qname_str) == 0) {
+ response = nameserver->hostname;
+ }
+
+ free(qname_str);
+
+ return response;
+}
+
+/*!
+ * \brief Create TXT RR with a given string content.
+ *
+ * \param owner RR owner name.
+ * \param response String to be saved in RDATA. Truncated to 255 chars.
+ *
+ * \return Allocated RRset or NULL in case of error.
+ */
+static knot_rrset_t *create_txt_rrset(const knot_dname_t *owner,
+ const char *response)
+{
+ // truncate response to one TXT label
+ size_t response_len = strlen(response);
+ if (response_len > 255)
+ response_len = 255;
+
+ knot_dname_t *rowner = knot_dname_deep_copy(owner);
+ if (!rowner)
+ return NULL;
+
+ knot_rrset_t *rrset;
+ rrset = knot_rrset_new(rowner, KNOT_RRTYPE_TXT, KNOT_CLASS_CH, 0);
+ knot_dname_release(rowner);
+ if (!rrset)
+ return NULL;
+
+ uint8_t *rdata = knot_rrset_create_rdata(rrset, response_len + 1);
+ if (!rdata) {
+ knot_rrset_deep_free(&rrset, 1, 0);
+ return NULL;
+ }
+
+ rdata[0] = response_len;
+ memcpy(&rdata[1], response, response_len);
+
+ return rrset;
+}
+
+/*!
+ * \brief Create a response for a TXT CHAOS query.
+ *
+ * \param return KNOT_RCODE_NOERROR if the response was succesfully created,
+ * otherwise an RCODE representing the failure.
+ */
+static int answer_txt(knot_nameserver_t *nameserver, knot_packet_t *response,
+ uint8_t *response_wire, size_t *response_size)
+{
+ const knot_dname_t *qname = knot_packet_qname(response);
+ const char *response_str = get_txt_response_string(nameserver, qname);
+ if (response_str == NULL || response_str[0] == '\0')
+ return KNOT_RCODE_REFUSED;
+
+ knot_rrset_t *rrset = create_txt_rrset(qname, response_str);
+ if (!rrset)
+ return KNOT_RCODE_SERVFAIL;
+
+ int result = knot_response_add_rrset_answer(response, rrset, 1, 0, 0);
+ if (result != KNOT_EOK) {
+ knot_rrset_deep_free(&rrset, 1, 0);
+ return KNOT_RCODE_SERVFAIL;
+ }
+
+ result = ns_response_to_wire(response, response_wire, response_size);
+ if (result != KNOT_EOK) {
+ knot_rrset_deep_free(&rrset, 1, 0);
+ return KNOT_RCODE_SERVFAIL;
+ }
+
+ knot_rrset_deep_free(&rrset, 1, 0);
+ knot_response_set_rcode(response, KNOT_RCODE_NOERROR);
+
+ return KNOT_RCODE_NOERROR;
+}
+
+/*!
+ * \brief Create a response for a given query in the CHAOS class.
+ */
+int knot_ns_answer_chaos(knot_nameserver_t *nameserver, knot_packet_t *resp,
+ uint8_t *resp_wire, size_t *resp_size)
+{
+ int rcode = KNOT_RCODE_REFUSED;
+
+ if (knot_packet_qtype(resp) == KNOT_RRTYPE_TXT) {
+ rcode = answer_txt(nameserver, resp, resp_wire, resp_size);
+ }
+
+ if (rcode != KNOT_RCODE_NOERROR) {
+ knot_ns_error_response_full(nameserver, resp, rcode,
+ resp_wire, resp_size);
+ }
+
+ return KNOT_EOK;
+}
diff --git a/src/libknot/nameserver/chaos.h b/src/libknot/nameserver/chaos.h
new file mode 100644
index 0000000..3f75260
--- /dev/null
+++ b/src/libknot/nameserver/chaos.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 2011 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 chaos.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \addtogroup query_processing
+ * @{
+ */
+
+#ifndef _KNOT_CHAOS_H_
+#define _KNOT_CHAOS_H_
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "name-server.h"
+#include "packet/packet.h"
+
+/*!
+ * \brief Create a response for a given query in the CHAOS class.
+ *
+ * \param nameserver Name server structure.
+ * \param response Response structure with parsed query.
+ * \param response_wire Output for response in wire format.
+ * \param response_size IN: maximum acceptable size of input, OUT: real size.
+ *
+ * \return Always KNOT_EOK.
+ */
+int knot_ns_answer_chaos(knot_nameserver_t *nameserver, knot_packet_t *response,
+ uint8_t *response_wire, size_t *response_size);
+
+#endif // _KNOT_CHAOS_H_
+
+/*! @} */
diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c
index b81a2c0..4a95240 100644
--- a/src/libknot/nameserver/name-server.c
+++ b/src/libknot/nameserver/name-server.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdio.h>
#include <assert.h>
#include <sys/time.h>
@@ -24,11 +25,15 @@
#include "updates/xfr-in.h"
#include "libknot.h"
+#include "common/errcode.h"
+#include "common.h"
+#include "common/lists.h"
#include "util/debug.h"
#include "packet/packet.h"
#include "packet/response.h"
#include "packet/query.h"
#include "consts.h"
+#include "common/descriptor.h"
#include "updates/changesets.h"
#include "updates/ddns.h"
#include "tsig-op.h"
@@ -125,48 +130,18 @@ static const knot_zone_t *ns_get_zone_for_qname(knot_zonedb_t *zdb,
static knot_rrset_t *ns_synth_from_wildcard(
const knot_rrset_t *wildcard_rrset, const knot_dname_t *qname)
{
- dbg_ns_verb("Synthetizing RRSet from wildcard...\n");
-
- knot_dname_t *owner = knot_dname_deep_copy(qname);
-
- knot_rrset_t *synth_rrset = knot_rrset_new(
- owner, knot_rrset_type(wildcard_rrset),
- knot_rrset_class(wildcard_rrset),
- knot_rrset_ttl(wildcard_rrset));
-
- /* Release owner, as it's retained in rrset. */
- knot_dname_release(owner);
-
- if (synth_rrset == NULL) {
+ knot_rrset_t *rrset = NULL;
+ int ret = knot_rrset_deep_copy(wildcard_rrset, &rrset, 1);
+ if (ret != KNOT_EOK) {
+ dbg_ns("ns: ns_synth_from_wildcard: Could not copy RRSet.\n");
return NULL;
}
- dbg_ns_verb("Created RRSet header:\n");
- knot_rrset_dump(synth_rrset, 1);
-
- // copy all RDATA
- const knot_rdata_t *rdata = knot_rrset_rdata(wildcard_rrset);
- while (rdata != NULL) {
- // we could use the RDATA from the wildcard rrset
- // but there is no way to distinguish it when deleting
- // temporary RRSets
- knot_rdata_t *rdata_copy = knot_rdata_deep_copy(rdata,
- knot_rrset_type(synth_rrset), 0);
- if (rdata_copy == NULL) {
- knot_rrset_deep_free(&synth_rrset, 1, 1, 0);
- return NULL;
- }
-
- dbg_ns_verb("Copied RDATA:\n");
- knot_rdata_dump(rdata_copy,
- knot_rrset_type(synth_rrset), 1);
-
- int ret = knot_rrset_add_rdata(synth_rrset, rdata_copy);
- assert(ret == KNOT_EOK);
- rdata = knot_rrset_rdata_next(wildcard_rrset, rdata);
- }
+ knot_dname_t *dname_copy = knot_dname_deep_copy(qname);
+ knot_rrset_set_owner(rrset, dname_copy);
+ knot_dname_release(dname_copy);
- return synth_rrset;
+ return rrset;
}
/*----------------------------------------------------------------------------*/
@@ -199,13 +174,13 @@ static int ns_check_wildcard(const knot_dname_t *name, knot_packet_t *resp,
dbg_ns_exec_verb(
dbg_ns_verb("Synthetized RRSet:\n");
- knot_rrset_dump(synth_rrset, 1);
+ knot_rrset_dump(synth_rrset);
);
int ret = knot_packet_add_tmp_rrset(resp, synth_rrset);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add sythetized RRSet to tmp list.\n");
- knot_rrset_deep_free(&synth_rrset, 1, 1, 1);
+ knot_rrset_deep_free(&synth_rrset, 1, 1);
return ret;
}
*rrset = synth_rrset;
@@ -239,13 +214,12 @@ static int ns_add_rrsigs(knot_rrset_t *rrset, knot_packet_t *resp,
const knot_dname_t *name,
int (*add_rrset_to_resp)(knot_packet_t *,
knot_rrset_t *,
- int, int, int, int),
+ int, int, int),
int tc)
{
knot_rrset_t *rrsigs;
- dbg_ns_verb("Adding RRSIGs for RRSet, type: %s.\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ dbg_ns_verb("Adding RRSIGs for RRSet, type: %u.\n", knot_rrset_type(rrset));
assert(resp != NULL);
assert(add_rrset_to_resp != NULL);
@@ -266,12 +240,52 @@ static int ns_add_rrsigs(knot_rrset_t *rrset, knot_packet_t *resp,
return ret;
}
}
- return add_rrset_to_resp(resp, rrsigs, tc, 1, 0, 1);
+ return add_rrset_to_resp(resp, rrsigs, tc, 1, 1);
}
return KNOT_EOK;
}
+/* Wrapper functions for lists. */
+typedef struct chain_node {
+ node n;
+ const knot_node_t *kn_node;
+} chain_node_t;
+
+static int cname_chain_add(list *chain, const knot_node_t *kn_node)
+{
+ assert(chain != NULL);
+ chain_node_t *new_node = malloc(sizeof(chain_node_t));
+ CHECK_ALLOC_LOG(new_node, KNOT_ENOMEM);
+
+ new_node->kn_node = kn_node;
+ add_tail(chain, (node *)new_node);
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static int cname_chain_contains(const list *chain, const knot_node_t *kn_node)
+{
+ node *n = NULL;
+ WALK_LIST(n, *chain) {
+ chain_node_t *l_node = (chain_node_t *)n;
+ if (l_node->kn_node == kn_node) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void cname_chain_free(list *chain)
+{
+ WALK_LIST_FREE(*chain);
+}
+
/*----------------------------------------------------------------------------*/
/*!
* \brief Resolves CNAME chain starting in \a node, stores all the CNAMEs in the
@@ -290,23 +304,46 @@ static int ns_follow_cname(const knot_node_t **node,
knot_packet_t *resp,
int (*add_rrset_to_resp)(knot_packet_t *,
knot_rrset_t *,
- int, int, int, int),
+ int, int, int),
int tc)
{
dbg_ns_verb("Resolving CNAME chain...\n");
knot_rrset_t *cname_rrset;
int ret = 0;
+ int wc = 0;
+
+ /*
+ * If stop == 1, cycle was detected, but one last entry has to be put
+ * in the packet (because of wildcard).
+ * If stop == 2, we should quit right away.
+ */
+ int stop = 0;
+
+ list cname_chain;
+ init_list(&cname_chain);
while (*node != NULL
+ && stop != 2
&& (cname_rrset = knot_node_get_rrset(*node, KNOT_RRTYPE_CNAME))
!= NULL
- && (knot_rrset_rdata(cname_rrset) != NULL)) {
+ && (knot_rrset_rdata_rr_count(cname_rrset))) {
+ /*
+ * Store node to chain list to sort out duplicates and cycles.
+ * Even if we follow wildcard, the result is always the same.
+ * so duplicate check does not need synthesized DNAMEs.
+ */
+ if (cname_chain_add(&cname_chain, *node) != KNOT_EOK) {
+ dbg_ns("Failed to add node to CNAME chain\n");
+ cname_chain_free(&cname_chain);
+ return KNOT_ENOMEM;
+ }
+
/* put the CNAME record to answer, but replace the possible
wildcard name with qname */
assert(cname_rrset != NULL);
-
+
dbg_ns_detail("CNAME RRSet: %p, owner: %p\n", cname_rrset,
cname_rrset->owner);
@@ -314,12 +351,14 @@ static int ns_follow_cname(const knot_node_t **node,
// ignoring other than the first record
if (knot_dname_is_wildcard(knot_node_owner(*node))) {
+ wc = 1;
/* if wildcard node, we must copy the RRSet and
replace its owner */
rrset = ns_synth_from_wildcard(cname_rrset, *qname);
if (rrset == NULL) {
dbg_ns("Failed to synthetize RRSet from "
"wildcard RRSet followed from CNAME.\n");
+ cname_chain_free(&cname_chain);
return KNOT_ERROR; /*! \todo Better error. */
}
@@ -328,14 +367,16 @@ static int ns_follow_cname(const knot_node_t **node,
dbg_ns("Failed to add synthetized RRSet (CNAME "
"follow) to the tmp RRSets in response."
"\n");
- knot_rrset_deep_free(&rrset, 1, 1, 1);
+ knot_rrset_deep_free(&rrset, 1, 1);
+ cname_chain_free(&cname_chain);
return ret;
}
- ret = add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
+ ret = add_rrset_to_resp(resp, rrset, tc, 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add synthetized RRSet (CNAME "
"follow) to the response.\n");
+ cname_chain_free(&cname_chain);
return ret;
}
@@ -345,6 +386,7 @@ static int ns_follow_cname(const knot_node_t **node,
dbg_ns("Failed to add RRSIG for the synthetized"
"RRSet (CNAME follow) to the response."
"\n");
+ cname_chain_free(&cname_chain);
return ret;
}
@@ -353,14 +395,16 @@ static int ns_follow_cname(const knot_node_t **node,
if (ret != KNOT_EOK) {
dbg_ns("Failed to add wildcard node for later "
"processing.\n");
+ cname_chain_free(&cname_chain);
return ret;
}
} else {
- ret = add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
+ ret = add_rrset_to_resp(resp, rrset, tc, 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add followed RRSet into"
"the response.\n");
+ cname_chain_free(&cname_chain);
return ret;
}
@@ -370,13 +414,14 @@ static int ns_follow_cname(const knot_node_t **node,
if (ret != KNOT_EOK) {
dbg_ns("Failed to add RRSIG for followed RRSet "
"into the response.\n");
+ cname_chain_free(&cname_chain);
return ret;
}
}
-
+
dbg_ns_detail("Using RRSet: %p, owner: %p\n", rrset,
rrset->owner);
-
+
dbg_ns_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(rrset));
dbg_ns("CNAME record for owner %s put to response.\n", name);
@@ -384,8 +429,8 @@ dbg_ns_exec_verb(
);
// get the name from the CNAME RDATA
- const knot_dname_t *cname = knot_rdata_cname_name(
- knot_rrset_rdata(cname_rrset));
+ const knot_dname_t *cname =
+ knot_rrset_rdata_cname_name(cname_rrset);
dbg_ns_detail("CNAME name from RDATA: %p\n", cname);
// change the node to the node of that name
*node = knot_dname_node(cname);
@@ -393,8 +438,24 @@ dbg_ns_exec_verb(
// save the new name which should be used for replacing wildcard
*qname = cname;
+
+ // Decide if we stop or not
+ if (stop == 1) {
+ // Exit loop
+ stop = 2;
+ } else if (cname_chain_contains(&cname_chain, *node)) {
+ if (wc) {
+ // Do one more loop
+ stop = 1;
+ } else {
+ // No wc, exit right away
+ stop = 2;
+ }
+ }
}
+ cname_chain_free(&cname_chain);
+
return KNOT_EOK;
}
@@ -446,8 +507,7 @@ dbg_ns_exec_verb(
assert(rrsets[i] != NULL);
rrset = rrsets[i];
- dbg_ns_detail(" Type: %s\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ dbg_ns_detail(" Type: %u\n", knot_rrset_type(rrset));
ret = ns_check_wildcard(name, resp, &rrset);
if (ret != KNOT_EOK) {
@@ -456,7 +516,7 @@ dbg_ns_exec_verb(
}
ret = knot_response_add_rrset_answer(resp, rrset, 1,
- 0, 0, 1);
+ 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed add Answer RRSet: %s\n",
knot_strerror(ret));
@@ -477,9 +537,7 @@ dbg_ns_exec_verb(
++i;
}
- if (rrsets != NULL) {
- free(rrsets);
- }
+ free(rrsets);
break;
}
case KNOT_RRTYPE_RRSIG: {
@@ -507,7 +565,7 @@ dbg_ns_exec_verb(
}
ret = knot_response_add_rrset_answer(resp, rrset, 1,
- 0, 0, 1);
+ 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed add Answer RRSet: %s\n",
knot_strerror(ret));
@@ -524,10 +582,9 @@ dbg_ns_exec_verb(
int ret = 0;
knot_rrset_t *rrset = knot_node_get_rrset(node, type);
knot_rrset_t *rrset2 = rrset;
- if (rrset != NULL && knot_rrset_rdata(rrset) != NULL) {
- dbg_ns_verb("Found RRSet of type %s\n",
- knot_rrtype_to_string(type));
-
+ if (rrset != NULL && knot_rrset_rdata_rr_count(rrset)) {
+ dbg_ns_verb("Found RRSet of type %u\n", type);
+
ret = ns_check_wildcard(name, resp, &rrset2);
if (ret != KNOT_EOK) {
dbg_ns("Failed to process wildcard.\n");
@@ -535,7 +592,7 @@ dbg_ns_exec_verb(
}
ret = knot_response_add_rrset_answer(resp, rrset2, 1,
- 0, 0, 1);
+ 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed add Answer RRSet: %s\n",
knot_strerror(ret));
@@ -583,18 +640,16 @@ static int ns_put_additional_for_rrset(knot_packet_t *resp,
const knot_rrset_t *rrset)
{
const knot_node_t *node = NULL;
- const knot_rdata_t *rdata = NULL;
- const knot_dname_t *dname = NULL;
int ret = 0;
// for all RRs in the RRset
- rdata = knot_rrset_rdata(rrset);
- while (rdata != NULL) {
- dbg_ns_verb("Getting name from RDATA, type %s..\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
- dname = knot_rdata_get_name(rdata, knot_rrset_type(rrset));
-
+ /* TODO all dnames, or only the ones returned by rdata_get_name? */
+ for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rrset); i++) {
+ dbg_ns_verb("Getting name from RDATA, type %u..\n",
+ knot_rrset_type(rrset));
+ const knot_dname_t *dname = knot_rrset_rdata_name(rrset, i);
+ assert(dname);
dbg_ns_exec_detail(
char *name = knot_dname_to_str(dname);
dbg_ns_detail("Name: %s\n", name);
@@ -602,7 +657,7 @@ dbg_ns_exec_detail(
);
assert(dname != NULL);
node = knot_dname_node(dname);
-
+
dbg_ns_detail("Node saved in RDATA dname: %p\n", node);
if (node != NULL && node->owner != dname) {
// the stored node should be the wildcard covering the
@@ -648,7 +703,7 @@ dbg_ns_exec(
}
ret = knot_response_add_rrset_additional(
- resp, rrset_add2, 0, 1, 0, 1);
+ resp, rrset_add2, 0, 1, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add A RRSet to "
@@ -684,7 +739,7 @@ dbg_ns_exec(
}
ret = knot_response_add_rrset_additional(
- resp, rrset_add2, 0, 1, 0, 1);
+ resp, rrset_add2, 0, 1, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add AAAA RRSet to "
@@ -704,8 +759,6 @@ dbg_ns_exec(
}
assert(rrset != NULL);
- assert(rdata != NULL);
- rdata = knot_rrset_rdata_next(rrset, rdata);
}
return KNOT_EOK;
@@ -789,7 +842,7 @@ static int ns_put_authority_ns(const knot_zone_contents_t *zone,
if (ns_rrset != NULL) {
int ret = knot_response_add_rrset_authority(resp, ns_rrset, 0,
- 1, 0, 1);
+ 1, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add Authority NSs to response.\n");
@@ -830,10 +883,10 @@ static int ns_put_authority_soa(const knot_zone_contents_t *zone,
// if SOA's TTL is larger than MINIMUM, copy the RRSet and set
// MINIMUM as TTL
- uint32_t min = knot_rdata_soa_minimum(knot_rrset_rdata(soa_rrset));
+ uint32_t min = knot_rrset_rdata_soa_minimum(soa_rrset);
if (min < knot_rrset_ttl(soa_rrset)) {
knot_rrset_t *soa_copy = NULL;
- ret = knot_rrset_deep_copy(soa_rrset, &soa_copy, 0);
+ ret = knot_rrset_deep_copy(soa_rrset, &soa_copy, 1);
if (ret != KNOT_EOK) {
return ret;
@@ -846,14 +899,14 @@ static int ns_put_authority_soa(const knot_zone_contents_t *zone,
/* Need to add it as temporary, so it get's freed. */
ret = knot_packet_add_tmp_rrset(resp, soa_copy);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&soa_copy, 1, 1, 1);
+ knot_rrset_deep_free(&soa_copy, 1, 1);
return ret;
}
}
assert(soa_rrset != NULL);
- ret = knot_response_add_rrset_authority(resp, soa_rrset, 0, 0, 0, 1);
+ ret = knot_response_add_rrset_authority(resp, soa_rrset, 0, 0, 1);
if (ret != KNOT_EOK) {
return ret;
}
@@ -911,7 +964,7 @@ static knot_dname_t *ns_next_closer(const knot_dname_t *closest_encloser,
* \param resp Response where to add the RRSets.
*/
static int ns_put_nsec3_from_node(const knot_node_t *node,
- knot_packet_t *resp)
+ knot_packet_t *resp)
{
assert(DNSSEC_ENABLED
&& knot_query_dnssec_requested(knot_packet_query(resp)));
@@ -923,17 +976,15 @@ static int ns_put_nsec3_from_node(const knot_node_t *node,
// bad zone, ignore
return KNOT_EOK;
}
-
+
int res = KNOT_EOK;
- if (knot_rrset_rdata(rrset) != NULL) {
- res = knot_response_add_rrset_authority(resp, rrset, 1, 1, 0,
- 1);
+ if (knot_rrset_rdata_rr_count(rrset)) {
+ res = knot_response_add_rrset_authority(resp, rrset, 1, 1, 1);
}
// add RRSIG for the RRSet
if (res == KNOT_EOK && (rrset = knot_rrset_get_rrsigs(rrset)) != NULL
- && knot_rrset_rdata(rrset) != NULL) {
- res = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0,
- 1);
+ && knot_rrset_rdata_rr_count(rrset)) {
+ res = knot_response_add_rrset_authority(resp, rrset, 1, 0, 1);
}
/*! \note TC bit is already set, if something went wrong. */
@@ -973,7 +1024,7 @@ static int ns_put_covering_nsec3(const knot_zone_contents_t *zone,
// if run-time collision => SERVFAIL
return KNOT_EOK;
}
-
+
dbg_ns_exec_verb(
char *name = knot_dname_to_str(prev->owner);
dbg_ns_verb("Covering NSEC3 node: %s\n", name);
@@ -1079,21 +1130,20 @@ dbg_ns_exec_verb(
*/
if (next_closer == NULL) {
// create the "next closer" name by appending from qname
- next_closer = ns_next_closer(
+ knot_dname_t *new_next_closer = ns_next_closer(
knot_node_owner(*closest_encloser), qname);
- if (next_closer == NULL) {
+ if (new_next_closer == NULL) {
return NS_ERR_SERVFAIL;
}
dbg_ns_exec_verb(
- char *name = knot_dname_to_str(next_closer);
+ char *name = knot_dname_to_str(new_next_closer);
dbg_ns_verb("Next closer name: %s\n", name);
free(name);
);
- ret = ns_put_covering_nsec3(zone, next_closer, resp);
+ ret = ns_put_covering_nsec3(zone, new_next_closer, resp);
- // the cast is ugly, but no better way around it
- knot_dname_release((knot_dname_t *)next_closer);
+ knot_dname_release(new_next_closer);
} else {
ret = ns_put_covering_nsec3(zone, next_closer, resp);
}
@@ -1203,19 +1253,19 @@ static int ns_put_nsec_nsec3_nodata(const knot_zone_contents_t *zone,
if (nsec3_node != NULL
&& (rrset = knot_node_get_rrset(nsec3_node,
KNOT_RRTYPE_NSEC3)) != NULL
- && knot_rrset_rdata(rrset) != NULL) {
+ && knot_rrset_rdata_rr_count(rrset)) {
dbg_ns_detail("Putting the RRSet to Authority\n");
ret = knot_response_add_rrset_authority(resp, rrset, 1,
- 0, 0, 1);
+ 0, 1);
}
} else {
dbg_ns_verb("Adding NSEC for NODATA\n");
if ((rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NSEC))
- != NULL
- && knot_rrset_rdata(rrset) != NULL) {
+ != NULL
+ && knot_rrset_rdata_rr_count(rrset)) {
dbg_ns_detail("Putting the RRSet to Authority\n");
ret = knot_response_add_rrset_authority(resp, rrset, 1,
- 0, 0, 1);
+ 0, 1);
}
}
@@ -1226,7 +1276,7 @@ static int ns_put_nsec_nsec3_nodata(const knot_zone_contents_t *zone,
dbg_ns_detail("Putting RRSet's RRSIGs to Authority\n");
if (rrset != NULL && (rrset = knot_rrset_get_rrsigs(rrset)) != NULL) {
ret = knot_response_add_rrset_authority(resp, rrset, 1,
- 0, 0, 1);
+ 0, 1);
}
return ret;
@@ -1263,12 +1313,12 @@ static int ns_put_nsec_nxdomain(const knot_dname_t *qname,
/*! \todo Check version. */
previous = knot_zone_contents_find_previous(zone, qname);
assert(previous != NULL);
-
+
while (!knot_node_is_auth(previous)) {
previous = knot_node_previous(previous);
}
}
-
+
dbg_ns_exec_verb(
char *name = knot_dname_to_str(previous->owner);
dbg_ns_verb("Previous node: %s\n", name);
@@ -1281,10 +1331,10 @@ dbg_ns_exec_verb(
// no NSEC records
//return NS_ERR_SERVFAIL;
return KNOT_EOK;
-
+
}
- int ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ int ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add NSEC for NXDOMAIN to response: %s\n",
knot_strerror(ret));
@@ -1293,7 +1343,7 @@ dbg_ns_exec_verb(
rrset = knot_rrset_get_rrsigs(rrset);
assert(rrset != NULL);
- ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add RRSIGs for NSEC for NXDOMAIN to response:"
"%s\n", knot_strerror(ret));
@@ -1337,22 +1387,22 @@ dbg_ns_exec_verb(
if (prev_new != previous) {
rrset = knot_node_get_rrset(prev_new, KNOT_RRTYPE_NSEC);
- if (rrset == NULL || knot_rrset_rdata(rrset) == NULL) {
+ if (rrset == NULL || knot_rrset_rdata_rr_count(rrset) == 0) {
// bad zone, ignore
return KNOT_EOK;
}
- ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add second NSEC for NXDOMAIN to "
"response: %s\n", knot_strerror(ret));
return ret;
}
rrset = knot_rrset_get_rrsigs(rrset);
- if (rrset == NULL || knot_rrset_rdata(rrset) == NULL) {
+ if (rrset == NULL || knot_rrset_rdata_rr_count(rrset) == 0) {
// bad zone, ignore
return KNOT_EOK;
}
- ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to add RRSIGs for second NSEC for "
"NXDOMAIN to response: %s\n", knot_strerror(ret));
@@ -1468,7 +1518,7 @@ static int ns_put_nsec3_wildcard(const knot_zone_contents_t *zone,
if (!knot_zone_contents_nsec3_enabled(zone)) {
return KNOT_EOK;
}
-
+
/*
* NSEC3 that covers the "next closer" name.
*/
@@ -1516,10 +1566,10 @@ static int ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
&& knot_query_dnssec_requested(knot_packet_query(resp)));
// check if we have previous; if not, find one using the tree
- if (previous == NULL) {
+ if (previous == NULL) {
previous = knot_zone_contents_find_previous(zone, qname);
assert(previous != NULL);
-
+
while (!knot_node_is_auth(previous)) {
previous = knot_node_previous(previous);
}
@@ -1530,15 +1580,15 @@ static int ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
int ret = KNOT_EOK;
- if (rrset != NULL && knot_rrset_rdata(rrset) != NULL) {
+ if (rrset != NULL && knot_rrset_rdata_rr_count(rrset)) {
// NSEC proving that there is no node with the searched name
ret = knot_response_add_rrset_authority(resp, rrset, 1, 0,
- 0, 1);
+ 1);
if (ret == KNOT_EOK) {
rrset = knot_rrset_get_rrsigs(rrset);
assert(rrset != NULL);
ret = knot_response_add_rrset_authority(resp, rrset, 1,
- 0, 0, 1);
+ 0, 1);
}
}
@@ -1693,42 +1743,42 @@ static inline int ns_referral(const knot_node_t *node,
// Special handling of DS queries
if (qtype == KNOT_RRTYPE_DS) {
- knot_rrset_t *ds_rrset = knot_node_get_rrset(node,
+ knot_rrset_t *ds_rrset = knot_node_get_rrset(node,
KNOT_RRTYPE_DS);
-
+
if (ds_rrset) {
ret = knot_response_add_rrset_answer(resp, ds_rrset, 1,
- 0, 0, 1);
+ 0, 1);
if (ret == KNOT_EOK && DNSSEC_ENABLED
&& knot_query_dnssec_requested(
knot_packet_query(resp))) {
ret = ns_add_rrsigs(ds_rrset, resp, node->owner,
- knot_response_add_rrset_answer,
+ knot_response_add_rrset_authority,
1);
}
} else {
// normal NODATA response
/*! \todo Handle in some generic way. */
-
+
dbg_ns_verb("Adding NSEC/NSEC3 for NODATA.\n");
ret = ns_put_nsec_nsec3_nodata(zone, node, resp);
if (ret != KNOT_EOK) {
return ret;
}
-
+
ret = ns_put_authority_soa(zone, resp);
}
// This is an authoritative answer, set AA bit
knot_response_set_aa(resp);
-
+
return ret;
}
-
+
knot_rrset_t *rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NS);
assert(rrset != NULL);
-
- ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 1);
if (ret == KNOT_EOK) {
ret = ns_add_rrsigs(rrset, resp, node->owner,
knot_response_add_rrset_authority, 1);
@@ -1743,7 +1793,7 @@ static inline int ns_referral(const knot_node_t *node,
rrset = knot_node_get_rrset(node, KNOT_RRTYPE_DS);
if (rrset != NULL) {
ret = knot_response_add_rrset_authority(resp, rrset, 1,
- 0, 0, 1);
+ 0, 1);
if (ret == KNOT_EOK) {
ret = ns_add_rrsigs(rrset, resp, node->owner,
knot_response_add_rrset_authority, 1);
@@ -1774,11 +1824,11 @@ static inline int ns_referral(const knot_node_t *node,
if (nsec) {
/*! \todo Check return value? */
ret = knot_response_add_rrset_authority(
- resp, nsec, 1, 1, 0, 1);
+ resp, nsec, 1, 1, 1);
if (ret == KNOT_EOK &&
(nsec = knot_rrset_get_rrsigs(nsec)) != NULL) {
ret = knot_response_add_rrset_authority(
- resp, nsec, 1, 1, 0, 1);
+ resp, nsec, 1, 1, 1);
}
}
}
@@ -1911,39 +1961,37 @@ static knot_rrset_t *ns_cname_from_dname(const knot_rrset_t *dname_rrset,
knot_rrset_t *cname_rrset = knot_rrset_new(
owner, KNOT_RRTYPE_CNAME, KNOT_CLASS_IN, SYNTH_CNAME_TTL);
-
- /* Release owner, as it's retained in rrset. */
- knot_dname_release(owner);
-
if (cname_rrset == NULL) {
return NULL;
}
+ /* Release owner, as it's retained in rrset. */
+ knot_dname_release(owner);
+
// replace last labels of qname with DNAME
knot_dname_t *cname = knot_dname_replace_suffix(qname,
knot_dname_size(knot_rrset_owner(dname_rrset)),
- knot_rdata_get_item(knot_rrset_rdata(dname_rrset), 0)->dname);
+ knot_rrset_rdata_dname_target(dname_rrset));
+ if (cname == NULL) {
+ knot_rrset_free(&cname_rrset);
+ return NULL;
+ }
dbg_ns_exec(
char *name = knot_dname_to_str(cname);
dbg_ns_verb("CNAME canonical name: %s.\n", name);
free(name);
);
- knot_rdata_t *cname_rdata = knot_rdata_new();
- knot_rdata_item_t cname_rdata_item;
- cname_rdata_item.dname = cname;
- int ret = knot_rdata_set_items(cname_rdata, &cname_rdata_item, 1);
- if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&cname_rrset, 1, 1, 1);
- knot_rdata_deep_free(&cname_rdata, KNOT_RRTYPE_CNAME, 1);
+ uint8_t *cname_rdata = knot_rrset_create_rdata(cname_rrset,
+ sizeof(knot_dname_t *));
+ if (cname_rdata == NULL) {
+ dbg_ns("ns: cname_from_dname: Cannot cerate CNAME RDATA.\n");
+ knot_rrset_free(&cname_rrset);
+ knot_dname_release(cname);
return NULL;
}
- ret = knot_rrset_add_rdata(cname_rrset, cname_rdata);
- if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&cname_rrset, 1, 1, 1);
- knot_rdata_deep_free(&cname_rdata, KNOT_RRTYPE_CNAME, 1);
- return NULL;
- }
+ /* Store DNAME into RDATA. */
+ memcpy(cname_rdata, &cname, sizeof(knot_dname_t *));
return cname_rrset;
}
@@ -1959,14 +2007,13 @@ dbg_ns_exec(
* \retval <>0 if the created domain name would be too long.
* \retval 0 otherwise.
*/
-static int ns_dname_is_too_long(const knot_rrset_t *dname_rrset,
+static int ns_dname_is_too_long(const knot_rrset_t *rrset,
const knot_dname_t *qname)
{
// TODO: add function for getting DNAME target
if (knot_dname_label_count(qname)
- - knot_dname_label_count(knot_rrset_owner(dname_rrset))
- + knot_dname_label_count(knot_rdata_get_item(
- knot_rrset_rdata(dname_rrset), 0)->dname)
+ - knot_dname_label_count(knot_rrset_owner(rrset))
+ + knot_dname_label_count(knot_rrset_rdata_dname_target(rrset))
> KNOT_MAX_DNAME_LENGTH) {
return 1;
} else {
@@ -1999,7 +2046,7 @@ dbg_ns_exec_verb(
// TODO: check the number of RRs in the RRSet??
// put the DNAME RRSet into the answer
- int ret = knot_response_add_rrset_answer(resp, dname_rrset, 1, 0, 0, 1);
+ int ret = knot_response_add_rrset_answer(resp, dname_rrset, 1, 0, 1);
if (ret != KNOT_EOK) {
return ret;
}
@@ -2018,7 +2065,7 @@ dbg_ns_exec_verb(
// synthetize CNAME (no way to tell that client supports DNAME)
knot_rrset_t *synth_cname = ns_cname_from_dname(dname_rrset, *qname);
// add the synthetized RRSet to the Answer
- ret = knot_response_add_rrset_answer(resp, synth_cname, 1, 0, 0, 1);
+ ret = knot_response_add_rrset_answer(resp, synth_cname, 1, 0, 1);
if (ret != KNOT_EOK) {
return ret;
}
@@ -2032,8 +2079,7 @@ dbg_ns_exec_verb(
}
// get the next SNAME from the CNAME RDATA
- const knot_dname_t *cname = knot_rdata_cname_name(
- knot_rrset_rdata(synth_cname));
+ const knot_dname_t *cname = knot_rrset_rdata_cname_name(synth_cname);
dbg_ns_verb("CNAME name from RDATA: %p\n", cname);
// save the new name which should be used for replacing wildcard
@@ -2058,7 +2104,7 @@ static int ns_add_dnskey(const knot_node_t *apex, knot_packet_t *resp)
if (rrset != NULL) {
ret = knot_response_add_rrset_additional(resp, rrset, 0, 0,
- 0, 1);
+ 1);
if (ret == KNOT_EOK) {
ret = ns_add_rrsigs(rrset, resp, apex->owner,
knot_response_add_rrset_additional, 0);
@@ -2095,17 +2141,13 @@ static int ns_answer_from_zone(const knot_zone_contents_t *zone,
uint16_t qtype = knot_packet_qtype(resp);
search:
-#ifdef USE_HASH_TABLE
- find_ret = knot_zone_contents_find_dname_hash(zone, qname, &node,
- &closest_encloser);
-#else
find_ret = knot_zone_contents_find_dname(zone, qname, &node,
&closest_encloser, &previous);
- node = knot_node_current(node);
- closest_encloser = knot_node_current(closest_encloser);
- previous = knot_node_current(previous);
-#endif
- if (find_ret == KNOT_EINVAL) {
+// node = knot_node_current(node);
+// closest_encloser = knot_node_current(closest_encloser);
+// previous = knot_node_current(previous);
+ previous = NULL; // TODO REVIEW LS
+ if (find_ret == KNOT_EINVAL) {
return NS_ERR_SERVFAIL;
}
@@ -2215,7 +2257,7 @@ have_node:
&& qtype != KNOT_RRTYPE_CNAME && qtype != KNOT_RRTYPE_RRSIG) {
dbg_ns_exec(
char *name = knot_dname_to_str(node->owner);
- dbg_ns_verb("Node %s has CNAME record, resolving...\n", name);
+ dbg_ns("Node %s has CNAME record, resolving...\n", name);
free(name);
);
const knot_dname_t *act_name = qname;
@@ -2380,7 +2422,7 @@ int ns_response_to_wire(knot_packet_t *resp, uint8_t *wire,
} else {
dbg_ns("Using the same space or wire format.\n");
}
-
+
*wire_size = rsize;
return KNOT_EOK;
@@ -2407,7 +2449,7 @@ static int ns_error_response_to_wire(knot_packet_t *resp, uint8_t *wire,
* This is ideal, we just truncate the packet after the question.
*/
dbg_ns_verb("Creating error response.\n");
-
+
size_t rsize = knot_packet_question_size(knot_packet_query(resp));
dbg_ns_detail("Error response (~ query) size: %zu\n", rsize);
@@ -2421,7 +2463,7 @@ static int ns_error_response_to_wire(knot_packet_t *resp, uint8_t *wire,
}
assert(rwire != wire);
-
+
/*! \todo Why is this copied?? Why we cannot use resp->wireformat?? */
memcpy(wire, rwire, rsize);
@@ -2449,7 +2491,7 @@ typedef struct ns_axfr_params {
/*----------------------------------------------------------------------------*/
-int knot_ns_tsig_required(int packet_nr)
+int knot_ns_tsig_required(int packet_nr)
{
dbg_ns_verb("ns_tsig_required(%d): %d\n", packet_nr,
(packet_nr % KNOT_NS_TSIG_FREQ == 0));
@@ -2472,11 +2514,11 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
if (ns_response_to_wire(xfr->response, xfr->wire, &real_size) != 0) {
return NS_ERR_SERVFAIL;
}
-
+
int res = 0;
-
+
size_t digest_real_size = xfr->digest_max_size;
-
+
dbg_ns_detail("xfr->tsig_key=%p\n", xfr->tsig_key);
dbg_ns_detail("xfr->tsig_rcode=%d\n", xfr->tsig_rcode);
@@ -2498,8 +2540,8 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
xfr->digest, xfr->digest_size, xfr->digest,
digest_real_size, xfr->tsig_key);
res = knot_tsig_sign(xfr->wire, &real_size,
- xfr->wire_size, xfr->digest,
- xfr->digest_size, xfr->digest,
+ xfr->wire_size, xfr->digest,
+ xfr->digest_size, xfr->digest,
&digest_real_size,
xfr->tsig_key, xfr->tsig_rcode,
xfr->tsig_prev_time_signed);
@@ -2507,10 +2549,10 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
/* Add key, digest and digest length. */
dbg_ns_detail("Calling tsig_sign_next()\n");
res = knot_tsig_sign_next(xfr->wire, &real_size,
- xfr->wire_size,
+ xfr->wire_size,
xfr->digest,
xfr->digest_size,
- xfr->digest,
+ xfr->digest,
&digest_real_size,
xfr->tsig_key, xfr->tsig_data,
xfr->tsig_data_size);
@@ -2522,7 +2564,7 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
if (res != KNOT_EOK) {
return res;
}
-
+
assert(digest_real_size > 0);
// save the new previous digest size
xfr->digest_size = digest_real_size;
@@ -2533,7 +2575,7 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
} else if (xfr->tsig_rcode != 0) {
dbg_ns_verb("Adding TSIG without signing, TSIG RCODE: %d.\n",
xfr->tsig_rcode);
- assert(xfr->tsig_rcode != KNOT_TSIG_RCODE_BADTIME);
+ assert(xfr->tsig_rcode != KNOT_RCODE_BADTIME);
// add TSIG without signing
assert(xfr->query != NULL);
assert(knot_packet_additional_rrset_count(xfr->query) > 0);
@@ -2564,7 +2606,7 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
// Clean the response structure
dbg_ns_verb("Clearing response structure..\n");
knot_response_clear(xfr->response, 0);
-
+
// increment the packet number
++xfr->packet_nr;
if ((xfr->tsig_key && knot_ns_tsig_required(xfr->packet_nr))
@@ -2623,8 +2665,8 @@ dbg_ns_exec_verb(
assert(rrsets[i] != NULL);
rrset = rrsets[i];
rrset:
- dbg_ns_verb(" Type: %s\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ dbg_ns_verb(" Type: %u\n",
+ knot_rrset_type(rrset));
// do not add SOA
if (knot_rrset_type(rrset) == KNOT_RRTYPE_SOA) {
@@ -2633,12 +2675,12 @@ rrset:
}
ret = knot_response_add_rrset_answer(params->xfr->response,
- rrset, 0, 0, 1, 0);
+ rrset, 0, 0, 0);
if (ret == KNOT_ESPACE) {
// TODO: send the packet and clean the structure
dbg_ns("Packet full, sending..\n");
- ret = ns_xfr_send_and_clear(params->xfr,
+ ret = ns_xfr_send_and_clear(params->xfr,
knot_ns_tsig_required(params->xfr->packet_nr));
if (ret != KNOT_EOK) {
// some wierd problem, we should end
@@ -2662,7 +2704,7 @@ rrsigs:
}
ret = knot_response_add_rrset_answer(params->xfr->response,
- rrset, 0, 0, 1, 0);
+ rrset, 0, 0, 0);
if (ret == KNOT_ESPACE) {
// TODO: send the packet and clean the structure
@@ -2687,9 +2729,7 @@ rrsigs:
++i;
}
- if (rrsets != NULL) {
- free(rrsets);
- }
+ free(rrsets);
/*! \todo maybe distinguish some error codes. */
//params->ret = (ret == 0) ? KNOT_EOK : KNOT_ERROR;
@@ -2711,7 +2751,7 @@ static int ns_axfr_from_zone(knot_zone_contents_t *zone, knot_ns_xfr_t *xfr)
params.ret = KNOT_EOK;
xfr->packet_nr = 0;
-
+
/*
* First SOA
*/
@@ -2727,8 +2767,7 @@ static int ns_axfr_from_zone(knot_zone_contents_t *zone, knot_ns_xfr_t *xfr)
int ret;
// add SOA RR to the response
- ret = knot_response_add_rrset_answer(xfr->response, soa_rrset, 0, 0, 1,
- 0);
+ ret = knot_response_add_rrset_answer(xfr->response, soa_rrset, 0, 0, 0);
if (ret != KNOT_EOK) {
// something is really wrong
return KNOT_ERROR;
@@ -2738,7 +2777,7 @@ static int ns_axfr_from_zone(knot_zone_contents_t *zone, knot_ns_xfr_t *xfr)
knot_rrset_t *rrset = knot_rrset_get_rrsigs(soa_rrset);
if (rrset != NULL
&& (ret = knot_response_add_rrset_answer(xfr->response, rrset,
- 0, 0, 1, 0)) != KNOT_EOK) {
+ 0, 0, 0)) != KNOT_EOK) {
// something is really wrong, these should definitely fit in
return KNOT_ERROR;
}
@@ -2762,10 +2801,9 @@ static int ns_axfr_from_zone(knot_zone_contents_t *zone, knot_ns_xfr_t *xfr)
*/
// try to add the SOA to the response again (last RR)
- ret = knot_response_add_rrset_answer(xfr->response, soa_rrset, 0, 0, 1,
- 0);
+ ret = knot_response_add_rrset_answer(xfr->response, soa_rrset, 0, 0, 0);
if (ret == KNOT_ESPACE) {
-
+
// if there is not enough space, send the response and
// add the SOA record to a new packet
dbg_ns("Packet full, sending..\n");
@@ -2776,7 +2814,7 @@ static int ns_axfr_from_zone(knot_zone_contents_t *zone, knot_ns_xfr_t *xfr)
}
ret = knot_response_add_rrset_answer(xfr->response,
- soa_rrset, 0, 0, 1, 0);
+ soa_rrset, 0, 0, 0);
if (ret != KNOT_EOK) {
return KNOT_ERROR;
}
@@ -2795,14 +2833,14 @@ static int ns_axfr_from_zone(knot_zone_contents_t *zone, knot_ns_xfr_t *xfr)
static int ns_ixfr_put_rrset(knot_ns_xfr_t *xfr, knot_rrset_t *rrset)
{
int res = knot_response_add_rrset_answer(xfr->response, rrset,
- 0, 0, 0, 0);
+ 0, 0, 0);
if (res == KNOT_ESPACE) {
knot_response_set_rcode(xfr->response, KNOT_RCODE_NOERROR);
/*! \todo Probably rename the function. */
ns_xfr_send_and_clear(xfr, knot_ns_tsig_required(xfr->packet_nr));
res = knot_response_add_rrset_answer(xfr->response,
- rrset, 0, 0, 0, 0);
+ rrset, 0, 0, 0);
}
if (res != KNOT_EOK) {
@@ -2865,7 +2903,7 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
assert(xfr->data != NULL);
rcu_read_lock();
-
+
knot_changesets_t *chgsets = (knot_changesets_t *)xfr->data;
knot_zone_contents_t *contents = knot_zone_get_contents(xfr->zone);
assert(contents);
@@ -2874,8 +2912,8 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
KNOT_RRTYPE_SOA);
// 4) put the zone SOA as the first Answer RR
- int res = knot_response_add_rrset_answer(xfr->response, zone_soa, 0,
- 0, 0, 0);
+ int res = knot_response_add_rrset_answer(xfr->response, zone_soa, 0,
+ 0, 0);
if (res != KNOT_EOK) {
dbg_ns("IXFR query cannot be answered: %s.\n",
knot_strerror(res));
@@ -2888,11 +2926,17 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
// 5) put the changesets into the response while they fit in
for (int i = 0; i < chgsets->count; ++i) {
- res = ns_ixfr_put_changeset(xfr, &chgsets->sets[i]);
+ knot_changeset_t *chs = chgsets->sets + i;
+ res = ns_ixfr_put_changeset(xfr, chs);
if (res != KNOT_EOK) {
// answer is sent
rcu_read_unlock();
return res;
+ } else {
+ log_zone_info("%s Serial %u -> %u.\n",
+ xfr->msg,
+ knot_rrset_rdata_soa_serial(chs->soa_from),
+ knot_rrset_rdata_soa_serial(chs->soa_to));
}
}
@@ -2955,9 +2999,9 @@ static int knot_ns_prepare_response(knot_packet_t *query, knot_packet_t **resp,
size_t max_size, int copy_question)
{
assert(max_size >= 500);
-
+
// initialize response packet structure
- *resp = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
+ *resp = knot_packet_new_mm(KNOT_PACKET_PREALLOC_RESPONSE, &query->mm);
if (*resp == NULL) {
dbg_ns("Failed to create packet structure.\n");
return KNOT_ENOMEM;
@@ -3085,6 +3129,10 @@ knot_nameserver_t *knot_ns_create()
ns->opt_rr = NULL;
}
+ ns->identity = NULL;
+ ns->version = NULL;
+ ns->hostname = NULL;
+
knot_packet_free(&err);
return ns;
@@ -3140,19 +3188,19 @@ void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid, size_t le
dbg_ns("NS: set_nsid: nameserver=NULL.\n");
return;
}
-
+
if (nsid == NULL) {
/* This is fine. */
return;
}
-
+
int ret = knot_ns_replace_nsid(nameserver->opt_rr, nsid, len);
if (ret != KNOT_EOK) {
dbg_ns("NS: set_nsid: could not add EDNS option.\n");
return;
}
-
+
dbg_ns_verb("NS: set_nsid: added successfully.\n");
}
@@ -3172,9 +3220,10 @@ int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
dbg_ns_verb("Parsing packet...\n");
int ret = 0;
+ *type = KNOT_QUERY_INVALID;
if ((ret = knot_packet_parse_from_wire(packet, query_wire,
- qsize, 1)) != 0) {
+ qsize, 1, 0)) != 0) {
dbg_ns("Error while parsing packet, "
"libknot error '%s'.\n", knot_strerror(ret));
return KNOT_RCODE_FORMERR;
@@ -3308,19 +3357,19 @@ int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver,
/*
* At this point, the wireformat of query may be in the
* same place where the response is assembled. This does
- * not matter before this point, although the query
+ * not matter before this point, although the query
* wireformat is rewritten. Now we just need to copy
* the original Question section. So if the pointers are
- * the same, we may just leave it and increase the
+ * the same, we may just leave it and increase the
* response wire size. Otherwise we must copy the data.
*/
if (response_wire != knot_packet_wireformat(query)) {
memcpy(response_wire + KNOT_WIRE_HEADER_SIZE,
- knot_packet_wireformat(query)
+ knot_packet_wireformat(query)
+ KNOT_WIRE_HEADER_SIZE, question_size);
}
*rsize += question_size;
-
+
// adjust QDCOUNT
knot_wire_set_qdcount(response_wire, 1);
}
@@ -3364,7 +3413,7 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
knot_packet_parsed(query), knot_packet_size(query));
int ret;
- ret = knot_packet_parse_rest(query);
+ ret = knot_packet_parse_rest(query, 0);
if (ret != KNOT_EOK) {
dbg_ns("Failed to parse rest of the query: %s.\n",
knot_strerror(ret));
@@ -3419,7 +3468,7 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
size_t resp_max_size = 0;
knot_packet_dump(query);
-
+
if (max_size > 0) {
// if TCP is used, buffer size is the only constraint
assert(max_size > 0);
@@ -3448,10 +3497,6 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
query->parsed, query->size);
dbg_ns_detail("Opt RR: version: %d, payload: %d\n",
query->opt_rr.version, query->opt_rr.payload);
-
- // get the answer for the query
- knot_zonedb_t *zonedb = rcu_dereference(nameserver->zone_db);
-
dbg_ns_detail("EDNS supported in query: %d\n",
knot_query_edns_supported(query));
@@ -3472,6 +3517,11 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
dbg_ns_verb("Response max size: %zu\n", (*resp)->max_size);
+ // search for zone only for IN and ANY classes
+ uint16_t qclass = knot_packet_qclass(*resp);
+ if (qclass != KNOT_CLASS_IN && qclass != KNOT_CLASS_ANY)
+ return KNOT_EOK;
+
const knot_dname_t *qname = knot_packet_qname(*resp);
assert(qname != NULL);
@@ -3482,6 +3532,7 @@ dbg_ns_exec_verb(
free(name_str);
);
// find zone in which to search for the name
+ knot_zonedb_t *zonedb = rcu_dereference(nameserver->zone_db);
*zone = ns_get_zone_for_qname(zonedb, qname, qtype);
return KNOT_EOK;
@@ -3506,7 +3557,7 @@ int knot_ns_prep_update_response(knot_nameserver_t *nameserver,
knot_packet_parsed(query), knot_packet_size(query));
int ret;
- ret = knot_packet_parse_rest(query);
+ ret = knot_packet_parse_rest(query, 0);
if (ret != KNOT_EOK) {
dbg_ns("Failed to parse rest of the query: %s.\n",
knot_strerror(ret));
@@ -3626,7 +3677,7 @@ dbg_ns_exec_verb(
/*----------------------------------------------------------------------------*/
-int knot_ns_answer_normal(knot_nameserver_t *nameserver,
+int knot_ns_answer_normal(knot_nameserver_t *nameserver,
const knot_zone_t *zone, knot_packet_t *resp,
uint8_t *response_wire, size_t *rsize, int check_any)
{
@@ -3684,7 +3735,7 @@ int knot_ns_answer_ixfr_udp(knot_nameserver_t *nameserver,
knot_rrset_t *soa = knot_node_get_rrset(apex, KNOT_RRTYPE_SOA);
// just put the SOA to the Answer section of the response and send back
- int ret = knot_response_add_rrset_answer(resp, soa, 1, 0, 0, 0);
+ int ret = knot_response_add_rrset_answer(resp, soa, 1, 0, 0);
if (ret != KNOT_EOK) {
knot_ns_error_response_full(nameserver, resp,
KNOT_RCODE_SERVFAIL,
@@ -3723,42 +3774,69 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
return ret;
}
- ret = knot_packet_parse_rest(xfr->query);
+ ret = knot_packet_parse_rest(xfr->query, 0);
if (ret != KNOT_EOK) {
- dbg_ns("Failed to parse rest of the query: %s\n",
+ dbg_ns("Failed to parse rest of the query: %s\n",
knot_strerror(ret));
- knot_ns_error_response_from_query(nameserver, xfr->query,
- (ret == KNOT_EMALF) ? KNOT_RCODE_FORMERR
- : KNOT_RCODE_SERVFAIL,
- xfr->wire, &xfr->wire_size);
- ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
- xfr->wire_size);
+ xfr->rcode = (ret == KNOT_EMALF) ? KNOT_RCODE_FORMERR
+ : KNOT_RCODE_SERVFAIL;
return ret;
}
-
+
dbg_ns_exec_verb(
dbg_ns_verb("Parsed XFR query:\n");
knot_packet_dump(xfr->query);
);
- // initialize response packet structure
- knot_packet_t *response = knot_packet_new(
- KNOT_PACKET_PREALLOC_RESPONSE);
- if (response == NULL) {
+ knot_zonedb_t *zonedb = rcu_dereference(nameserver->zone_db);
+ const knot_dname_t *qname = knot_packet_qname(xfr->query);
+
+dbg_ns_exec_verb(
+ char *name_str = knot_dname_to_str(qname);
+ dbg_ns_verb("Trying to find zone with name %s\n", name_str);
+ free(name_str);
+);
+ // find zone in which to search for the name
+ knot_zone_t *zone = knot_zonedb_find_zone(zonedb, qname);
+
+ // if no zone found, return NotAuth
+ if (zone == NULL) {
+ dbg_ns("No zone found.\n");
+ xfr->rcode = KNOT_RCODE_NOTAUTH;
+ return KNOT_ENOZONE;
+ }
+
+dbg_ns_exec(
+ char *name2_str = knot_dname_to_str(qname);
+ dbg_ns("Found zone for name %s\n", name2_str);
+ free(name2_str);
+);
+ knot_zone_retain(zone);
+ xfr->zone = zone;
+
+
+ return KNOT_EOK;
+}
+
+int knot_ns_init_xfr_resp(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
+{
+ int ret = KNOT_EOK;
+ knot_packet_t *resp = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
+ if (resp == NULL) {
dbg_ns("Failed to create packet structure.\n");
/*! \todo xfr->wire is not NULL, will fail on assert! */
knot_ns_error_response_from_query(nameserver, xfr->query,
KNOT_RCODE_SERVFAIL,
xfr->wire, &xfr->wire_size);
- ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
+ ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
return ret;
}
- response->wireformat = xfr->wire;
- response->max_size = xfr->wire_size;
+ resp->wireformat = xfr->wire;
+ resp->max_size = xfr->wire_size;
- ret = knot_response_init_from_query(response, xfr->query, 1);
+ ret = knot_response_init_from_query(resp, xfr->query, 1);
if (ret != KNOT_EOK) {
dbg_ns("Failed to init response structure.\n");
@@ -3766,45 +3844,17 @@ dbg_ns_exec_verb(
knot_ns_error_response_from_query(nameserver, xfr->query,
KNOT_RCODE_SERVFAIL,
xfr->wire, &xfr->wire_size);
- int res = xfr->send(xfr->session, &xfr->addr, xfr->wire,
+ int res = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
- knot_packet_free(&response);
+ knot_packet_free(&resp);
return res;
}
- xfr->response = response;
-
- knot_zonedb_t *zonedb = rcu_dereference(nameserver->zone_db);
-
- const knot_dname_t *qname = knot_packet_qname(xfr->response);
+ xfr->response = resp;
assert(knot_packet_qtype(xfr->response) == KNOT_RRTYPE_AXFR ||
knot_packet_qtype(xfr->response) == KNOT_RRTYPE_IXFR);
-
-dbg_ns_exec_verb(
- char *name_str = knot_dname_to_str(qname);
- dbg_ns_verb("Trying to find zone with name %s\n", name_str);
- free(name_str);
-);
- // find zone in which to search for the name
- knot_zone_t *zone = knot_zonedb_find_zone(zonedb, qname);
-
- // if no zone found, return NotAuth
- if (zone == NULL) {
- dbg_ns("No zone found.\n");
- knot_response_set_rcode(xfr->response, KNOT_RCODE_NOTAUTH);
- ns_xfr_send_and_clear(xfr, 1);
- return KNOT_ENOZONE;
- }
-
-dbg_ns_exec(
- char *name2_str = knot_dname_to_str(qname);
- dbg_ns("Found zone for name %s\n", name2_str);
- free(name2_str);
-);
- xfr->zone = zone;
-
- return KNOT_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -3813,36 +3863,34 @@ int ns_serial_compare(uint32_t s1, uint32_t s2)
{
int32_t diff = ns_serial_difference(s1, s2);
return (s1 == s2) /* s1 equal to s2 */
- ? 0
- :((diff >= 1 && diff < ((uint32_t)1 << 31))
+ ? 0
+ :((diff >= 1 && diff < ((uint32_t)1 << 31))
? 1 /* s1 larger than s2 */
: -1); /* s1 less than s2 */
}
/*----------------------------------------------------------------------------*/
-int ns_ixfr_load_serials(const knot_ns_xfr_t *xfr, uint32_t *serial_from,
+int ns_ixfr_load_serials(const knot_ns_xfr_t *xfr, uint32_t *serial_from,
uint32_t *serial_to)
{
- if (xfr == NULL || xfr->zone == NULL || serial_from == NULL
+ if (xfr == NULL || xfr->zone == NULL || serial_from == NULL
|| serial_to == NULL) {
- dbg_ns("Wrong parameters: xfr=%p,"
- " xfr->zone = %p\n", xfr, xfr->zone);
return KNOT_EINVAL;
}
-
+
const knot_zone_t *zone = xfr->zone;
const knot_zone_contents_t *contents = knot_zone_contents(zone);
if (!contents) {
dbg_ns("Missing contents\n");
return KNOT_EINVAL;
}
-
+
if (knot_zone_contents_apex(contents) == NULL) {
dbg_ns("No apex.\n");
return KNOT_EINVAL;
}
-
+
const knot_rrset_t *zone_soa =
knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
@@ -3850,22 +3898,22 @@ int ns_ixfr_load_serials(const knot_ns_xfr_t *xfr, uint32_t *serial_from,
dbg_ns("No SOA.\n");
return KNOT_EINVAL;
}
-
+
if (knot_packet_nscount(xfr->query) < 1) {
dbg_ns("No Authority record.\n");
return KNOT_EMALF;
}
-
+
if (knot_packet_authority_rrset(xfr->query, 0) == NULL) {
dbg_ns("Authority record missing.\n");
return KNOT_ERROR;
}
-
+
// retrieve origin (xfr) serial and target (zone) serial
- *serial_to = knot_rdata_soa_serial(knot_rrset_rdata(zone_soa));
- *serial_from = knot_rdata_soa_serial(knot_rrset_rdata(
- knot_packet_authority_rrset(xfr->query, 0)));
-
+ *serial_to = knot_rrset_rdata_soa_serial(zone_soa);
+ *serial_from =
+ knot_rrset_rdata_soa_serial(knot_packet_authority_rrset(xfr->query, 0));
+
return KNOT_EOK;
}
@@ -3876,7 +3924,7 @@ int knot_ns_xfr_send_error(const knot_nameserver_t *nameserver,
{
/*! \todo Handle TSIG errors differently. */
knot_response_set_rcode(xfr->response, rcode);
-
+
int ret = 0;
if ((ret = ns_xfr_send_and_clear(xfr, 1)) != KNOT_EOK
|| xfr->response == NULL) {
@@ -3886,7 +3934,7 @@ int knot_ns_xfr_send_error(const knot_nameserver_t *nameserver,
xfr->wire, &size);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire, size);
}
-
+
return ret;
}
@@ -3897,9 +3945,9 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
if (xfr == NULL || nameserver == NULL || xfr->zone == NULL) {
return KNOT_EINVAL;
}
-
+
rcu_read_lock();
-
+
// take the contents and answer from them
int ret = 0;
knot_zone_contents_t *contents = knot_zone_get_contents(xfr->zone);
@@ -3912,13 +3960,13 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
knot_packet_free(&xfr->response);
return ret;
}
-
+
/*
* The TSIG data should already be stored in 'xfr'.
* Now just count the expected size of the TSIG RR and save it
* to the response structure.
*/
-
+
/*! \todo [TSIG] Get the TSIG size from some API function. */
if (xfr->tsig_size > 0) {
dbg_ns_verb("Setting TSIG size in packet: %zu\n",
@@ -3935,11 +3983,8 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
if (ret < 0 && ret != KNOT_ECONN) {
dbg_ns("AXFR failed, sending SERVFAIL.\n");
// now only one type of error (SERVFAIL), later maybe more
- knot_ns_error_response_from_query(nameserver, xfr->query,
- KNOT_RCODE_SERVFAIL,
- xfr->wire, &xfr->wire_size);
- ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
- xfr->wire_size);
+ /*! \todo #2176 This should send error response every time. */
+ knot_ns_xfr_send_error(nameserver, xfr, KNOT_RCODE_SERVFAIL);
} else if (ret > 0) {
ret = KNOT_ERROR;
}
@@ -3959,9 +4004,9 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
|| xfr->response == NULL) {
return KNOT_EINVAL;
}
-
+
// parse rest of the packet (we need the Authority record)
- int ret = knot_packet_parse_rest(xfr->query);
+ int ret = knot_packet_parse_rest(xfr->query, 0);
if (ret != KNOT_EOK) {
dbg_ns("Failed to parse rest of the packet: %s. "
"Reply FORMERR.\n", knot_strerror(ret));
@@ -3977,19 +4022,19 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
knot_packet_free(&xfr->response);
return ret;
}
-
+
/*
* The TSIG data should already be stored in 'xfr'.
* Now just count the expected size of the TSIG RR and save it
* to the response structure. This should be optional, only if
* the request contained TSIG, i.e. if there is the data in 'xfr'.
*/
-
+
/*! \todo [TSIG] Get the TSIG size from some API function. */
if (xfr->tsig_size > 0) {
knot_packet_set_tsig_size(xfr->response, xfr->tsig_size);
}
-
+
ret = ns_ixfr(xfr);
knot_packet_free(&xfr->response);
@@ -4006,77 +4051,67 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
* and the digest of the query sent to the master or the previous
* digest.
*/
-
+
dbg_ns("ns_process_axfrin: incoming packet, wire size: %zu\n",
xfr->wire_size);
-
int ret = xfrin_process_axfr_packet(xfr);
if (ret > 0) { // transfer finished
dbg_ns("ns_process_axfrin: AXFR finished, zone created.\n");
+
+ gettimeofday(&xfr->t_end, NULL);
+
/*
* Adjust zone so that node count is set properly and nodes are
* marked authoritative / delegation point.
*/
- xfrin_constructed_zone_t *constr_zone =
+ xfrin_constructed_zone_t *constr_zone =
(xfrin_constructed_zone_t *)xfr->data;
knot_zone_contents_t *zone = constr_zone->contents;
assert(zone != NULL);
-
- /* Create and fill hash table */
- dbg_ns_verb("ns_process_axfrin: filling hash table.\n");
- int rc = knot_zone_contents_create_and_fill_hash_table(zone);
- if (rc != KNOT_EOK) {
- return KNOT_ERROR; // TODO: change error code
- }
+ log_zone_info("%s Serial %u -> %u\n", xfr->msg,
+ knot_zone_serial(knot_zone_contents(xfr->zone)),
+ knot_zone_serial(zone));
dbg_ns_verb("ns_process_axfrin: adjusting zone.\n");
- rc = knot_zone_contents_adjust(zone);
+ int rc = knot_zone_contents_adjust(zone, NULL, NULL, 0);
if (rc != KNOT_EOK) {
return rc;
}
- dbg_ns_verb("ns_process_axfrin: checking loops.\n");
- rc = knot_zone_contents_check_loops(zone);
- if (rc != KNOT_EOK) {
- return rc;
- }
-
// save the zone contents to the xfr->data
xfr->new_contents = zone;
xfr->flags |= XFR_FLAG_AXFR_FINISHED;
assert(zone->nsec3_nodes != NULL);
-
+
// free the structure used for processing XFR
assert(constr_zone->rrsigs == NULL);
free(constr_zone);
- //knot_zone_contents_dump(zone, 0);
-
// check zone integrity
dbg_ns_exec_verb(
int errs = knot_zone_contents_integrity_check(zone);
dbg_ns_verb("Zone integrity check: %d errors.\n", errs);
);
}
-
+
/*! \todo In case of error, shouldn't the zone be destroyed here? */
-
+
return ret;
}
/*----------------------------------------------------------------------------*/
-int knot_ns_switch_zone(knot_nameserver_t *nameserver,
+int knot_ns_switch_zone(knot_nameserver_t *nameserver,
knot_ns_xfr_t *xfr)
{
if (xfr == NULL || nameserver == NULL || xfr->new_contents == NULL) {
return KNOT_EINVAL;
}
-
+
knot_zone_contents_t *zone = (knot_zone_contents_t *)xfr->new_contents;
-
+
dbg_ns("Replacing zone by new one: %p\n", zone);
if (zone == NULL) {
dbg_ns("No new zone!\n");
@@ -4122,28 +4157,29 @@ dbg_ns_exec_verb(
/*----------------------------------------------------------------------------*/
-int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
+int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
knot_ns_xfr_t *xfr)
{
dbg_ns("ns_process_ixfrin: incoming packet\n");
-
+
/*
* [TSIG] Here we assume that 'xfr' contains TSIG information
* and the digest of the query sent to the master or the previous
* digest.
*/
-
int ret = xfrin_process_ixfr_packet(xfr);
-
+
if (ret == XFRIN_RES_FALLBACK) {
dbg_ns("ns_process_ixfrin: Fallback to AXFR.\n");
- knot_free_changesets((knot_changesets_t **)&xfr->data);
- knot_packet_free(&xfr->query);
- return KNOT_ENOIXFR;
+ ret = KNOT_ENOIXFR;
}
-
- if (ret > 0) {
+
+ if (ret < 0) {
+ knot_packet_free(&xfr->query);
+ return ret;
+ } else if (ret > 0) {
dbg_ns("ns_process_ixfrin: IXFR finished\n");
+ gettimeofday(&xfr->t_end, NULL);
knot_changesets_t *chgsets = (knot_changesets_t *)xfr->data;
if (chgsets == NULL || chgsets->first_soa == NULL) {
@@ -4162,7 +4198,7 @@ int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
(knot_changesets_t **)(&xfr->data));
return KNOT_ENOZONE;
}
-
+
switch (ret) {
case XFRIN_RES_COMPLETE:
break;
@@ -4174,18 +4210,18 @@ int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
if (apex == NULL) {
return KNOT_ERROR;
}
-
+
const knot_rrset_t *zone_soa = knot_node_rrset(
apex, KNOT_RRTYPE_SOA);
if (zone_soa == NULL) {
return KNOT_ERROR;
}
-
- if (ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(chgsets->first_soa)),
- knot_rdata_soa_serial(knot_rrset_rdata(zone_soa)))
+
+ if (ns_serial_compare(
+ knot_rrset_rdata_soa_serial(chgsets->first_soa),
+ knot_rrset_rdata_soa_serial(zone_soa))
> 0) {
- if ((xfr->flags & XFR_FLAG_UDP) > 0) {
+ if ((xfr->flags & XFR_FLAG_UDP) != 0) {
// IXFR over UDP
dbg_ns("Update did not fit.\n");
return KNOT_EIXFRSPACE;
@@ -4209,22 +4245,22 @@ int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
} break;
}
}
-
+
/*! \todo In case of error, shouldn't the zone be destroyed here? */
-
+
return ret;
}
/*----------------------------------------------------------------------------*/
/*
- * The given query is already fully parsed. But the parameter contains an
- * already prepared response structure.
+ * The given query is already fully parsed. But the parameter contains an
+ * already prepared response structure.
*
* This function should process the contents, prepare prerequisities, prepare
* changeset and return to the caller.
*/
-int knot_ns_process_update(const knot_packet_t *query,
- const knot_zone_contents_t *zone,
+int knot_ns_process_update(const knot_packet_t *query,
+ const knot_zone_contents_t *zone,
knot_changeset_t *changeset, knot_rcode_t *rcode)
{
assert(knot_packet_is_query(query));
@@ -4232,7 +4268,7 @@ int knot_ns_process_update(const knot_packet_t *query,
dbg_ns("Processing Dynamic Update.\n");
*rcode = KNOT_RCODE_NOERROR;
-
+
// 1) Check zone
// Already done
// dbg_ns_verb("Checking zone for DDNS.\n");
@@ -4295,12 +4331,12 @@ int knot_ns_process_update(const knot_packet_t *query,
* - If everything went OK, continue.
* 3) Finalize the updated zone.
*
- * NOTE: Mostly copied from xfrin_apply_changesets(). Should be refactored in
+ * NOTE: Mostly copied from xfrin_apply_changesets(). Should be refactored in
* order to get rid of duplicate code.
*/
-int knot_ns_process_update2(const knot_packet_t *query,
- knot_zone_contents_t *old_contents,
- knot_zone_contents_t **new_contents,
+int knot_ns_process_update2(const knot_packet_t *query,
+ knot_zone_contents_t *old_contents,
+ knot_zone_contents_t **new_contents,
knot_changesets_t *chgs, knot_rcode_t *rcode)
{
/*! \todo Implement. */
@@ -4323,10 +4359,10 @@ int knot_ns_process_update2(const knot_packet_t *query,
*rcode = KNOT_RCODE_SERVFAIL;
return ret;
}
-
+
/* 2) Apply the UPDATE and create changesets. */
dbg_ns_verb("Applying the UPDATE and creating changeset...\n");
- ret = knot_ddns_process_update2(contents_copy, query, &chgs->sets[0],
+ ret = knot_ddns_process_update2(contents_copy, query, &chgs->sets[0],
changes, rcode);
if (ret != KNOT_EOK) {
dbg_ns("Failed to apply UPDATE to the zone copy or no update"
@@ -4335,9 +4371,9 @@ int knot_ns_process_update2(const knot_packet_t *query,
xfrin_rollback_update(old_contents, &contents_copy, &changes);
return ret;
}
-
+
dbg_ns_verb("Finalizing updated zone...\n");
- ret = xfrin_finalize_updated_zone(contents_copy, changes, old_contents);
+ ret = xfrin_finalize_updated_zone(contents_copy, changes);
if (ret != KNOT_EOK) {
dbg_ns("Failed to finalize updated zone: %s\n",
knot_strerror(ret));
@@ -4349,7 +4385,7 @@ int knot_ns_process_update2(const knot_packet_t *query,
chgs->changes = changes;
*new_contents = contents_copy;
-
+
return KNOT_EOK;
}
diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h
index 6bb7a86..58ea212 100644
--- a/src/libknot/nameserver/name-server.h
+++ b/src/libknot/nameserver/name-server.h
@@ -37,6 +37,7 @@
#include <stdint.h>
#include <string.h>
+#include <sys/time.h>
#include "zone/zonedb.h"
#include "edns.h"
@@ -44,6 +45,7 @@
#include "tsig.h"
#include "packet/packet.h"
#include "common/sockaddr.h"
+#include "common/lists.h"
#include "updates/changesets.h"
struct conf_t;
@@ -65,7 +67,11 @@ typedef struct knot_nameserver {
uint8_t *err_response; /*!< Prepared generic error response. */
size_t err_resp_size; /*!< Size of the prepared error response. */
knot_opt_rr_t *opt_rr; /*!< OPT RR with the server's EDNS0 info. */
-
+
+ const char *identity; //!< RFC 4892, server identity (id.server).
+ const char *version; //!< RFC 4892, server version (version.server).
+ const char *hostname; //!< RFC 4892, server host name (hostname.server).
+
void *data;
} knot_nameserver_t;
@@ -79,6 +85,7 @@ typedef int (*xfr_callback_t)(int session, sockaddr_t *addr,
* Used for communication with XFR handler.
*/
typedef struct knot_ns_xfr {
+ node n;
int type;
int flags;
sockaddr_t addr, saddr;
@@ -86,55 +93,59 @@ typedef struct knot_ns_xfr {
knot_packet_t *response;
knot_rcode_t rcode;
xfr_callback_t send;
+ xfr_callback_t recv;
int session;
- int session_closed;
-
+ struct timeval t_start, t_end;
+
/*!
* XFR-out: Output buffer.
* XFR-in: Buffer for query or incoming packet.
*/
uint8_t *wire;
-
- /*!
- * XFR-out: Size of the output buffer.
- * XFR-in: Size of the current packet.
+
+ /*!
+ * XFR-out: Size of the output buffer.
+ * XFR-in: Size of the current packet.
*/
size_t wire_size;
+ size_t wire_maxlen;
void *data;
knot_zone_t *zone;
char* zname;
- void *owner;
knot_zone_contents_t *new_contents;
- char *msgpref;
-
+ char *msg;
+
/*! \note [TSIG] TSIG fields */
- /*! \brief Message(s) to sign in wireformat.
+ /*! \brief Message(s) to sign in wireformat.
*
- * This field should be allocated at the start of transfer and
+ * This field should be allocated at the start of transfer and
* freed at the end. During the transfer it is only rewritten.
*/
uint8_t *tsig_data;
- size_t tsig_data_size; /*!< Size of the message(s) in bytes */
- size_t tsig_size; /*!< Size of the TSIG RR wireformat in bytes.*/
- knot_key_t *tsig_key; /*!< Associated TSIG key for signing. */
-
+ size_t tsig_data_size; /*!< Size of the message(s) in bytes */
+ size_t tsig_size; /*!< Size of the TSIG RR wireformat in bytes.*/
+ knot_tsig_key_t *tsig_key; /*!< Associated TSIG key for signing. */
+
uint8_t *digest; /*!< Buffer for counting digest. */
size_t digest_size; /*!< Size of the digest. */
size_t digest_max_size; /*!< Size of the buffer. */
-
+
/*! \note [DDNS] Update forwarding fields. */
int fwd_src_fd; /*!< Query originator fd. */
+ sockaddr_t fwd_addr;
uint16_t tsig_rcode;
uint64_t tsig_prev_time_signed;
-
- /*!
+
+ /*!
* \brief Number of the packet currently assembled.
*
- * In case of XFR-in, this is not the overall number of packet, just
+ * In case of XFR-in, this is not the overall number of packet, just
* number counted from last TSIG check.
*/
int packet_nr;
+
+ hattrie_t *lookup_tree;
} knot_ns_xfr_t;
@@ -161,14 +172,14 @@ typedef enum knot_ns_transport {
*/
typedef enum knot_ns_xfr_type_t {
/* DNS events. */
- XFR_TYPE_AIN = 1 << 0, /*!< AXFR-IN request (start transfer). */
- XFR_TYPE_AOUT= 1 << 1, /*!< AXFR-OUT request (incoming transfer). */
- XFR_TYPE_IIN = 1 << 2, /*!< IXFR-IN request (start transfer). */
- XFR_TYPE_IOUT = 1 << 3, /*!< IXFR-OUT request (incoming transfer). */
- XFR_TYPE_SOA = 1 << 4, /*!< Pending SOA request. */
- XFR_TYPE_NOTIFY = 1 << 5, /*!< Pending NOTIFY query. */
- XFR_TYPE_UPDATE = 1 << 6, /*!< UPDATE request (incoming UPDATE). */
- XFR_TYPE_FORWARD = 1 << 7 /*!< UPDATE forward request. */
+ XFR_TYPE_AIN = 0, /*!< AXFR-IN request (start transfer). */
+ XFR_TYPE_AOUT, /*!< AXFR-OUT request (incoming transfer). */
+ XFR_TYPE_IIN, /*!< IXFR-IN request (start transfer). */
+ XFR_TYPE_IOUT, /*!< IXFR-OUT request (incoming transfer). */
+ XFR_TYPE_SOA, /*!< Pending SOA request. */
+ XFR_TYPE_NOTIFY, /*!< Pending NOTIFY query. */
+ XFR_TYPE_UPDATE, /*!< UPDATE request (incoming UPDATE). */
+ XFR_TYPE_FORWARD /*!< UPDATE forward request. */
} knot_ns_xfr_type_t;
/*----------------------------------------------------------------------------*/
@@ -249,7 +260,7 @@ int knot_ns_prep_update_response(knot_nameserver_t *nameserver,
* \retval KNOT_EOK if a valid response was created.
* \retval KNOT_EMALF if an error occured and the response is not valid.
*/
-int knot_ns_answer_normal(knot_nameserver_t *nameserver,
+int knot_ns_answer_normal(knot_nameserver_t *nameserver,
const knot_zone_t *zone, knot_packet_t *resp,
uint8_t *response_wire, size_t *rsize, int check_any);
@@ -258,8 +269,9 @@ int knot_ns_answer_ixfr_udp(knot_nameserver_t *nameserver,
uint8_t *response_wire, size_t *rsize);
int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr);
+int knot_ns_init_xfr_resp(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr);
-/*!
+/*!
* \brief Compares two zone serials.
*
* \retval < 0 if s1 is less than s2.
@@ -268,7 +280,7 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr);
*/
int ns_serial_compare(uint32_t s1, uint32_t s2);
-int ns_ixfr_load_serials(const knot_ns_xfr_t *xfr, uint32_t *serial_from,
+int ns_ixfr_load_serials(const knot_ns_xfr_t *xfr, uint32_t *serial_from,
uint32_t *serial_to);
int knot_ns_xfr_send_error(const knot_nameserver_t *nameserver,
@@ -314,11 +326,11 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr);
* \param xfr Persistent transfer-specific data.
*
*/
-int knot_ns_process_axfrin(knot_nameserver_t *nameserver,
+int knot_ns_process_axfrin(knot_nameserver_t *nameserver,
knot_ns_xfr_t *xfr);
/*! \todo Document me. */
-int knot_ns_switch_zone(knot_nameserver_t *nameserver,
+int knot_ns_switch_zone(knot_nameserver_t *nameserver,
knot_ns_xfr_t *xfr);
/*!
@@ -329,14 +341,14 @@ int knot_ns_switch_zone(knot_nameserver_t *nameserver,
*
* \retval KNOT_EOK If this packet was processed successfuly and another packet
* is expected. (RFC1995bis, case c)
- * \retval KNOT_ENOXFR If the transfer is not taking place because server's
+ * \retval KNOT_ENOXFR If the transfer is not taking place because server's
* SERIAL is the same as this client's SERIAL. The client
* should close the connection and do no further processing.
* (RFC1995bis case a).
* \retval KNOT_EAGAIN If the server could not fit the transfer into the packet.
* This should happen only if UDP was used. In this case
* the client should retry the request via TCP. If UDP was
- * not used, it should be considered that the transfer was
+ * not used, it should be considered that the transfer was
* malformed and the connection should be closed.
* (RFC1995bis case b).
* \retval >0 Transfer successully finished. Changesets are created and furter
@@ -345,16 +357,16 @@ int knot_ns_switch_zone(knot_nameserver_t *nameserver,
*
* \todo Document me.
*/
-int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
+int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
knot_ns_xfr_t *xfr);
-int knot_ns_process_update(const knot_packet_t *query,
- const knot_zone_contents_t *zone,
+int knot_ns_process_update(const knot_packet_t *query,
+ const knot_zone_contents_t *zone,
knot_changeset_t *changeset, knot_rcode_t *rcode);
-int knot_ns_process_update2(const knot_packet_t *query,
- knot_zone_contents_t *old_contents,
- knot_zone_contents_t **new_contents,
+int knot_ns_process_update2(const knot_packet_t *query,
+ knot_zone_contents_t *old_contents,
+ knot_zone_contents_t **new_contents,
knot_changesets_t *chgs, knot_rcode_t *rcode);
int knot_ns_create_forward_query(const knot_packet_t *query,
diff --git a/src/libknot/nsec3.c b/src/libknot/nsec3.c
index 23130ba..4fe332a 100644
--- a/src/libknot/nsec3.c
+++ b/src/libknot/nsec3.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdint.h>
#include <assert.h>
#include <stdlib.h>
@@ -24,7 +25,7 @@
#include "nsec3.h"
#include "common.h"
-#include "util/descriptor.h"
+#include "common/descriptor.h"
#include "util/utils.h"
#include "util/tolower.h"
#include "util/debug.h"
@@ -34,24 +35,18 @@
int knot_nsec3_params_from_wire(knot_nsec3_params_t *params,
const knot_rrset_t *nsec3param)
{
- if (params == NULL || nsec3param == NULL) {
+ if (params == NULL || nsec3param == NULL ||
+ knot_rrset_rdata_rr_count(nsec3param) == 0) {
return KNOT_EINVAL;
}
assert(knot_rrset_type(nsec3param) == KNOT_RRTYPE_NSEC3PARAM);
- const knot_rdata_t *rdata = knot_rrset_rdata(nsec3param);
-
- assert(rdata->count == 4);
-
- params->algorithm = *(uint8_t *)
- (&knot_rdata_item(rdata, 0)->raw_data[1]);
- params->flags = *(uint8_t *)
- (&knot_rdata_item(rdata, 1)->raw_data[1]);
- params->iterations = knot_wire_read_u16(
- (uint8_t *)(knot_rdata_item(rdata, 2)->raw_data + 1));
+ params->algorithm = knot_rrset_rdata_nsec3param_algorithm(nsec3param);
+ params->iterations = knot_rrset_rdata_nsec3param_iterations(nsec3param);
+ params->flags = knot_rrset_rdata_nsec3param_flags(nsec3param);
params->salt_length =
- ((uint8_t *)knot_rdata_item(rdata, 3)->raw_data)[2];
+ knot_rrset_rdata_nsec3param_salt_length(nsec3param);
if (params->salt_length > 0) {
/* It is called also on reload, so we need to free if exists. */
@@ -60,19 +55,19 @@ int knot_nsec3_params_from_wire(knot_nsec3_params_t *params,
params->salt = NULL;
}
params->salt = (uint8_t *)malloc(params->salt_length);
- CHECK_ALLOC_LOG(params->salt, -1);
+ CHECK_ALLOC_LOG(params->salt, KNOT_ENOMEM);
memcpy(params->salt,
- (uint8_t *)knot_rdata_item(rdata, 3)->raw_data + 3,
+ knot_rrset_rdata_nsec3param_salt(nsec3param),
params->salt_length);
} else {
params->salt = NULL;
}
dbg_nsec3("Parsed NSEC3PARAM:\n");
- dbg_nsec3("Algorithm: %hu\n", params->algorithm);
- dbg_nsec3("Flags: %hu\n", params->flags);
- dbg_nsec3("Iterations: %hu\n", params->iterations);
- dbg_nsec3("Salt length: %hu\n", params->salt_length);
+ dbg_nsec3("Algorithm: %u\n", params->algorithm);
+ dbg_nsec3("Flags: %u\n", params->flags);
+ dbg_nsec3("Iterations: %u\n", params->iterations);
+ dbg_nsec3("Salt length: %u\n", params->salt_length);
dbg_nsec3("Salt: \n");
if (params->salt != NULL) {
dbg_nsec3_hex((char *)params->salt,
@@ -90,7 +85,7 @@ static uint8_t *knot_nsec3_to_lowercase(const uint8_t *data, size_t size)
uint8_t *out = (uint8_t *)malloc(size);
CHECK_ALLOC_LOG(out, NULL);
- for (int i = 0; i < size; ++i) {
+ for (size_t i = 0; i < size; ++i) {
out[i] = knot_tolower(data[i]);
}
@@ -194,7 +189,7 @@ int knot_nsec3_sha1(const knot_nsec3_params_t *params,
uint16_t iterations = params->iterations;
dbg_nsec3_verb("Hashing: \n");
- dbg_nsec3_verb(" Data: %.*s \n", size, data);
+ dbg_nsec3_verb(" Data: %.*s \n", (int)size, data);
dbg_nsec3_hex_verb((const char *)data, size);
dbg_nsec3_verb(" (size %d)\n Iterations: %u\n", (int)size, iterations);
dbg_nsec3_verb(" Salt length: %u\n", salt_length);
@@ -250,7 +245,7 @@ int knot_nsec3_sha1(const knot_nsec3_params_t *params,
*digest_size = SHA_DIGEST_LENGTH;
- dbg_nsec3_verb("Hash: %.*s\n", *digest_size, *digest);
+ dbg_nsec3_verb("Hash: %.*s\n", (int)*digest_size, *digest);
dbg_nsec3_hex_verb((const char *)*digest, *digest_size);
dbg_nsec3_verb("\n");
@@ -263,7 +258,5 @@ int knot_nsec3_sha1(const knot_nsec3_params_t *params,
void knot_nsec3_params_free(knot_nsec3_params_t *params)
{
- if (params->salt != NULL) {
- free(params->salt);
- }
+ free(params->salt);
}
diff --git a/src/libknot/packet/packet.c b/src/libknot/packet/packet.c
index 2e6e922..52ed72b 100644
--- a/src/libknot/packet/packet.c
+++ b/src/libknot/packet/packet.c
@@ -14,12 +14,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
+#include <stdlib.h>
#include "packet/packet.h"
#include "util/debug.h"
#include "common.h"
-#include "util/descriptor.h"
+#include "common/descriptor.h"
#include "util/wire.h"
#include "tsig.h"
@@ -35,13 +37,6 @@
? DEFAULT_##type##_QUERY \
: DEFAULT_##type)
-
-
-typedef enum {
- KNOT_PACKET_DUPL_IGNORE,
- KNOT_PACKET_DUPL_SKIP,
- KNOT_PACKET_DUPL_MERGE
-} knot_packet_duplicate_handling_t;
/*----------------------------------------------------------------------------*/
/* Non-API functions */
/*----------------------------------------------------------------------------*/
@@ -52,7 +47,7 @@ typedef enum {
static void knot_packet_init_pointers_response(knot_packet_t *pkt)
{
dbg_packet_detail("Packet pointer: %p\n", pkt);
-
+
char *pos = (char *)pkt + PREALLOC_PACKET;
// put QNAME directly after the structure
@@ -66,10 +61,6 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->question.qname->labels = (uint8_t *)pos;
pos += PREALLOC_QNAME_LABELS;
- pkt->owner_tmp = (uint8_t *)pos;
- dbg_packet_detail("Tmp owner: %p\n", pkt->owner_tmp);
- pos += PREALLOC_RR_OWNER;
-
// then answer, authority and additional sections
if (DEFAULT_ANCOUNT == 0) {
pkt->answer = NULL;
@@ -77,14 +68,14 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->answer = (const knot_rrset_t **)pos;
pos += DEFAULT_ANCOUNT * sizeof(const knot_rrset_t *);
}
-
+
if (DEFAULT_NSCOUNT == 0) {
pkt->authority = NULL;
} else {
pkt->authority = (const knot_rrset_t **)pos;
pos += DEFAULT_NSCOUNT * sizeof(const knot_rrset_t *);
}
-
+
if (DEFAULT_ARCOUNT == 0) {
pkt->additional = NULL;
} else {
@@ -100,21 +91,6 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->max_ns_rrsets = DEFAULT_NSCOUNT;
pkt->max_ar_rrsets = DEFAULT_ARCOUNT;
- // then domain names for compression and offsets
- pkt->compression.dnames = (const knot_dname_t **)pos;
- pos += DEFAULT_DOMAINS_IN_RESPONSE * sizeof(const knot_dname_t *);
- pkt->compression.offsets = (size_t *)pos;
- pos += DEFAULT_DOMAINS_IN_RESPONSE * sizeof(size_t);
- pkt->compression.to_free = (int *)pos;
- pos += DEFAULT_DOMAINS_IN_RESPONSE * sizeof(int);
-
- dbg_packet_detail("Compression dnames: %p\n", pkt->compression.dnames);
- dbg_packet_detail("Compression offsets: %p\n", pkt->compression.offsets);
- dbg_packet_detail("Compression to_free: %p\n", pkt->compression.to_free);
-
- pkt->compression.max = DEFAULT_DOMAINS_IN_RESPONSE;
- pkt->compression.default_count = DEFAULT_DOMAINS_IN_RESPONSE;
-
// wildcard nodes and SNAMEs associated with them
pkt->wildcard_nodes.nodes = (const knot_node_t **)pos;
pos += DEFAULT_WILDCARD_NODES * sizeof(const knot_node_t *);
@@ -145,7 +121,7 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
static void knot_packet_init_pointers_query(knot_packet_t *pkt)
{
dbg_packet_detail("Packet pointer: %p\n", pkt);
-
+
char *pos = (char *)pkt + PREALLOC_PACKET;
// put QNAME directly after the structure
@@ -169,14 +145,14 @@ static void knot_packet_init_pointers_query(knot_packet_t *pkt)
pkt->answer = (const knot_rrset_t **)pos;
pos += DEFAULT_ANCOUNT_QUERY * sizeof(const knot_rrset_t *);
}
-
+
if (DEFAULT_NSCOUNT_QUERY == 0) {
pkt->authority = NULL;
} else {
pkt->authority = (const knot_rrset_t **)pos;
pos += DEFAULT_NSCOUNT_QUERY * sizeof(const knot_rrset_t *);
}
-
+
if (DEFAULT_ARCOUNT_QUERY == 0) {
pkt->additional = NULL;
} else {
@@ -232,10 +208,8 @@ static int knot_packet_parse_header(const uint8_t *wire, size_t *pos,
}
header->id = knot_wire_get_id(wire);
- // copy some of the flags: OPCODE and RD
- // do this by copying flags1 and setting QR to 1, AA to 0 and TC to 0
header->flags1 = knot_wire_get_flags1(wire);
- // do not copy flags2 (all set by server)
+ header->flags2 = knot_wire_get_flags2(wire);
header->qdcount = knot_wire_get_qdcount(wire);
header->ancount = knot_wire_get_ancount(wire);
@@ -298,6 +272,7 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos,
if (question->qname == NULL) {
return KNOT_ENOMEM;
}
+ knot_dname_to_lower(question->qname);
} else {
assert(question->qname != NULL); /* When alloc=0, must be set. */
void *parsed = knot_dname_parse_from_wire(wire, pos,
@@ -306,6 +281,7 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos,
if (!parsed) {
return KNOT_EMALF;
}
+ knot_dname_to_lower(question->qname);
}
question->qtype = knot_wire_read_u16(wire + i + 1);
question->qclass = knot_wire_read_u16(wire + i + 3);
@@ -356,26 +332,74 @@ static int knot_packet_realloc_rrsets(const knot_rrset_t ***rrsets,
/*----------------------------------------------------------------------------*/
-static knot_rdata_t *knot_packet_parse_rdata(const uint8_t *wire,
- size_t *pos, size_t total_size, size_t rdlength,
- const knot_rrtype_descriptor_t *desc)
+static int knot_packet_parse_rdata(knot_rrset_t *rr, const uint8_t *wire,
+ size_t *pos, size_t total_size,
+ size_t rdlength)
{
- knot_rdata_t *rdata = knot_rdata_new();
- if (rdata == NULL) {
- return NULL;
+ if (!rr || !wire || !pos || rdlength == 0) {
+ return KNOT_EINVAL;
}
- int rc = knot_rdata_from_wire(rdata, wire, pos, total_size, rdlength,
- desc);
- if (rc != KNOT_EOK) {
- dbg_packet("rdata_from_wire() returned: %s\n",
- knot_strerror(rc));
- knot_rdata_free(&rdata);
- return NULL;
- }
- return rdata;
+ /*! \todo As I'm revising it, seems highly inefficient to me.
+ * We just need to skim through the packet,
+ * check if it is in valid format and store pointers to various
+ * parts in rdata instead of copying memory blocks and
+ * parsing domain names (with additional allocation) and then
+ * use use the wireformat for lookup again. Compression could
+ * be handled in-situ without additional memory allocs...
+ */
+
+ int ret = knot_rrset_rdata_from_wire_one(rr, wire, pos, total_size,
+ rdlength);
+ if (ret != KNOT_EOK) {
+ dbg_packet("packet: parse_rdata: Failed to parse RDATA (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+// uint8_t* rd = knot_rrset_create_rdata(rr, rdlength);
+// if (!rd) {
+// return KNOT_ERROR;
+// }
+// uint8_t* np = rd + rdlength;
+
+// const rdata_descriptor_t *desc = get_rdata_descriptor(knot_rrset_type(rr));
+// if (!desc) {
+// /*! \todo Free rdata mem ? Not essential, but nice. */
+// return KNOT_EINVAL;
+// }
+
+// for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+// const int id = desc->block_types[i];
+// if (descriptor_item_is_dname(id)) {
+// knot_dname_t *dn = NULL;
+// dn = knot_dname_parse_from_wire(wire, pos, total_size, NULL, NULL);
+// if (dn == NULL) {
+// return KNOT_EMALF;
+// }
+// /* Store ptr in rdata. */
+// *((knot_dname_t**)rd) = dn;
+// rd += sizeof(knot_dname_t*);
+// } else if (descriptor_item_is_fixed(id)) {
+// memcpy(rd, wire + *pos, id);
+// rd += id; /* Item represents fixed len here */
+// *pos += id;
+// } else if (descriptor_item_is_remainder(id)) {
+// size_t rchunk = np - rd;
+// memcpy(rd, wire + *pos, rchunk);
+// rd += rchunk;
+// *pos += rchunk;
+// } else {
+// //NAPTR
+// assert(knot_rrset_type(rr) == KNOT_RRTYPE_NAPTR);
+// assert(0);
+// }
+
+// }
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -393,6 +417,7 @@ static knot_rrset_t *knot_packet_parse_rr(const uint8_t *wire, size_t *pos,
if (owner == NULL) {
return NULL;
}
+ knot_dname_to_lower(owner);
dbg_packet_exec_verb(
char *name = knot_dname_to_str(owner);
@@ -435,7 +460,7 @@ dbg_packet_exec_verb(
if (size - *pos < rdlength) {
dbg_packet("Malformed RR: Not enough data to parse RR"
" RDATA (size: %zu, position: %zu).\n", size, *pos);
- knot_rrset_deep_free(&rrset, 1, 1, 0);
+ knot_rrset_deep_free(&rrset, 1, 1);
return NULL;
}
@@ -445,20 +470,14 @@ dbg_packet_exec_verb(
return rrset;
}
+
// parse RDATA
- knot_rdata_t *rdata = knot_packet_parse_rdata(wire, pos, size,
- rdlength,
- knot_rrtype_descriptor_by_type(rrset->type));
- if (rdata == NULL) {
+ /*! \todo Merge with add_rdata_to_rr in zcompile, should be a rrset func
+ * probably. */
+ int ret = knot_packet_parse_rdata(rrset, wire, pos, size, rdlength);
+ if (ret != KNOT_EOK) {
dbg_packet("Malformed RR: Could not parse RDATA.\n");
- knot_rrset_deep_free(&rrset, 1, 1, 0);
- return NULL;
- }
-
- if (knot_rrset_add_rdata(rrset, rdata) != KNOT_EOK) {
- dbg_packet("Malformed RR: Could not add RDATA to RRSet.\n");
- knot_rdata_free(&rdata);
- knot_rrset_deep_free(&rrset, 1, 1, 0);
+ knot_rrset_deep_free(&rrset, 1, 1);
return NULL;
}
@@ -473,7 +492,7 @@ static int knot_packet_add_rrset(knot_rrset_t *rrset,
short *max_rrsets,
short default_rrsets,
const knot_packet_t *packet,
- knot_packet_duplicate_handling_t dupl)
+ knot_packet_flag_t flags)
{
assert(rrset != NULL);
assert(rrsets != NULL);
@@ -482,8 +501,8 @@ static int knot_packet_add_rrset(knot_rrset_t *rrset,
dbg_packet_exec_verb(
char *name = knot_dname_to_str(rrset->owner);
- dbg_packet_verb("packet_add_rrset(), owner: %s, type: %s\n",
- name, knot_rrtype_to_string(rrset->type));
+ dbg_packet_verb("packet_add_rrset(), owner: %s, type: %u\n",
+ name, rrset->type);
free(name);
);
@@ -493,33 +512,30 @@ dbg_packet_exec_verb(
return KNOT_ENOMEM;
}
- if (dupl == KNOT_PACKET_DUPL_SKIP &&
+ if ((flags & KNOT_PACKET_DUPL_SKIP) &&
knot_packet_contains(packet, rrset, KNOT_RRSET_COMPARE_PTR)) {
- /*! \todo This should also return > 0, as it means that the
- RRSet was not used actually. */
- return KNOT_EOK;
+ return 2;
}
- if (dupl == KNOT_PACKET_DUPL_MERGE) {
+ // Try to merge rdata to rrset if flag NO_MERGE isn't set.
+ if ((flags & KNOT_PACKET_DUPL_NO_MERGE) == 0) {
// try to find the RRSet in this array of RRSets
for (int i = 0; i < *rrset_count; ++i) {
-
dbg_packet_exec_detail(
char *name = knot_dname_to_str((*rrsets)[i]->owner);
dbg_packet_detail("Comparing to RRSet: owner: %s, "
- "type: %s\n", name,
- knot_rrtype_to_string(
- (*rrsets)[i]->type));
+ "type: %u\n", name,
+ (*rrsets)[i]->type);
free(name);
);
- if (knot_rrset_match((*rrsets)[i], rrset,
+ if (knot_rrset_equal((*rrsets)[i], rrset,
KNOT_RRSET_COMPARE_HEADER)) {
/*! \todo Test this!!! */
// no duplicate checking here, the packet should
// look exactly as it came from wire
int rc = knot_rrset_merge(
- (void **)((*rrsets) + i), (void **)&rrset);
+ ((knot_rrset_t *)(*rrsets)[i]), rrset);
if (rc != KNOT_EOK) {
return rc;
}
@@ -542,7 +558,8 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
const knot_rrset_t ***rrsets,
short *rrset_count, short *max_rrsets,
short default_rrsets,
- knot_packet_t *packet)
+ knot_packet_t *packet,
+ knot_packet_flag_t flags)
{
assert(pos != NULL);
assert(wire != NULL);
@@ -573,13 +590,15 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
++(*parsed_rrs);
err = knot_packet_add_rrset(rrset, rrsets, rrset_count,
- max_rrsets, default_rrsets, packet,
- KNOT_PACKET_DUPL_MERGE);
+ max_rrsets, default_rrsets, packet, flags);
if (err < 0) {
break;
- } else if (err > 0) { // merged
+ } else if (err == 1) { // merged, shallow data copy
dbg_packet_detail("RRSet merged, freeing.\n");
- knot_rrset_deep_free(&rrset, 1, 0, 0); // TODO: ok??
+ knot_rrset_deep_free(&rrset, 1, 0);
+ continue;
+ } else if (err == 2) { // skipped
+ knot_rrset_deep_free(&rrset, 1, 1);
continue;
}
@@ -588,7 +607,7 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
// remove the last RRSet from the list of RRSets
// - just decrement the count
--(*rrset_count);
- knot_rrset_deep_free(&rrset, 1, 1, 1);
+ knot_rrset_deep_free(&rrset, 1, 1);
break;
}
@@ -638,12 +657,6 @@ static void knot_packet_free_allocated_space(knot_packet_t *pkt)
free(pkt->additional);
}
- if (pkt->compression.max > pkt->compression.default_count) {
- free(pkt->compression.dnames);
- free(pkt->compression.offsets);
- free(pkt->compression.to_free);
- }
-
if (pkt->wildcard_nodes.max > pkt->wildcard_nodes.default_count) {
free(pkt->wildcard_nodes.nodes);
free(pkt->wildcard_nodes.snames);
@@ -656,8 +669,8 @@ static void knot_packet_free_allocated_space(knot_packet_t *pkt)
/*----------------------------------------------------------------------------*/
-static int knot_packet_parse_rr_sections(knot_packet_t *packet,
- size_t *pos)
+static int knot_packet_parse_rr_sections(knot_packet_t *packet, size_t *pos,
+ knot_packet_flag_t flags)
{
assert(packet != NULL);
assert(packet->wireformat != NULL);
@@ -673,7 +686,7 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet,
if ((err = knot_packet_parse_rrs(packet->wireformat, pos,
packet->size, packet->header.ancount, &packet->parsed_an,
&packet->answer, &packet->an_rrsets, &packet->max_an_rrsets,
- DEFAULT_RRSET_COUNT(ANCOUNT, packet), packet)) != KNOT_EOK) {
+ DEFAULT_RRSET_COUNT(ANCOUNT, packet), packet, flags)) != KNOT_EOK) {
return err;
}
@@ -686,7 +699,7 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet,
if ((err = knot_packet_parse_rrs(packet->wireformat, pos,
packet->size, packet->header.nscount, &packet->parsed_ns,
&packet->authority, &packet->ns_rrsets, &packet->max_ns_rrsets,
- DEFAULT_RRSET_COUNT(NSCOUNT, packet), packet)) != KNOT_EOK) {
+ DEFAULT_RRSET_COUNT(NSCOUNT, packet), packet, flags)) != KNOT_EOK) {
return err;
}
@@ -699,7 +712,7 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet,
if ((err = knot_packet_parse_rrs(packet->wireformat, pos,
packet->size, packet->header.arcount, &packet->parsed_ar,
&packet->additional, &packet->ar_rrsets, &packet->max_ar_rrsets,
- DEFAULT_RRSET_COUNT(ARCOUNT, packet), packet)) != KNOT_EOK) {
+ DEFAULT_RRSET_COUNT(ARCOUNT, packet), packet, flags)) != KNOT_EOK) {
return err;
}
@@ -744,7 +757,14 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet,
knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc)
{
- knot_packet_t *pkt;
+ mm_ctx_t mm;
+ mm_ctx_init(&mm);
+ return knot_packet_new_mm(prealloc, &mm);
+}
+
+knot_packet_t *knot_packet_new_mm(knot_packet_prealloc_type_t prealloc, mm_ctx_t *mm)
+{
+ knot_packet_t *pkt = NULL;
void (*init_pointers)(knot_packet_t *pkt) = NULL;
size_t size = 0;
@@ -762,9 +782,10 @@ knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc)
break;
}
- pkt = (knot_packet_t *)malloc(size);
+ pkt = (knot_packet_t *)mm->alloc(mm->ctx, size);
CHECK_ALLOC_LOG(pkt, NULL);
memset(pkt, 0, size);
+ memcpy(&pkt->mm, mm, sizeof(mm_ctx_t));
if (init_pointers != NULL) {
init_pointers(pkt);
}
@@ -781,7 +802,7 @@ knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc)
int knot_packet_parse_from_wire(knot_packet_t *packet,
const uint8_t *wireformat, size_t size,
- int question_only)
+ int question_only, knot_packet_flag_t flags)
{
if (packet == NULL || wireformat == NULL) {
return KNOT_EINVAL;
@@ -821,7 +842,7 @@ int knot_packet_parse_from_wire(knot_packet_t *packet,
if (packet->header.qdcount == 1) {
if ((err = knot_packet_parse_question(wireformat, &pos, size,
- &packet->question, packet->prealloc_type
+ &packet->question, packet->prealloc_type
== KNOT_PACKET_PREALLOC_NONE)
) != KNOT_EOK) {
return err;
@@ -838,7 +859,7 @@ dbg_packet_exec_detail(
}
/*! \todo Replace by call to parse_rest()? */
- err = knot_packet_parse_rest(packet);
+ err = knot_packet_parse_rest(packet, flags);
dbg_packet_exec_detail(
knot_packet_dump(packet);
@@ -849,7 +870,7 @@ dbg_packet_exec_detail(
/*----------------------------------------------------------------------------*/
-int knot_packet_parse_rest(knot_packet_t *packet)
+int knot_packet_parse_rest(knot_packet_t *packet, knot_packet_flag_t flags)
{
if (packet == NULL) {
return KNOT_EINVAL;
@@ -864,13 +885,13 @@ int knot_packet_parse_rest(knot_packet_t *packet)
// If there is less data then required, the next function will find out.
// If there is more data than required, it also returns EMALF.
-
+
size_t pos = packet->parsed;
/*! \todo If we already parsed some part of the packet, it is not ok
* to begin parsing from the Answer section.
*/
- return knot_packet_parse_rr_sections(packet, &pos);
+ return knot_packet_parse_rr_sections(packet, &pos, flags);
}
/*----------------------------------------------------------------------------*/
@@ -898,7 +919,7 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet,
if (packet->parsed_an == packet->header.ancount) {
assert(packet->parsed < packet->size);
//dbg_packet("Trailing garbage, ignoring...\n");
- // there may be other data in the packet
+ // there may be other data in the packet
// (authority or additional).
return KNOT_EOK;
}
@@ -911,7 +932,7 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet,
dbg_packet_verb("Failed to parse RR!\n");
return KNOT_EMALF;
}
-
+
dbg_packet_detail("Parsed. Pos: %zu.\n", pos);
packet->parsed = pos;
@@ -960,7 +981,7 @@ int knot_packet_parse_next_rr_additional(knot_packet_t *packet,
dbg_packet_verb("Failed to parse RR!\n");
return KNOT_EMALF;
}
-
+
dbg_packet_detail("Parsed. Pos: %zu.\n", pos);
packet->parsed = pos;
@@ -981,6 +1002,13 @@ size_t knot_packet_size(const knot_packet_t *packet)
/*----------------------------------------------------------------------------*/
+size_t knot_packet_max_size(const knot_packet_t *packet)
+{
+ return packet->max_size;
+}
+
+/*----------------------------------------------------------------------------*/
+
size_t knot_packet_question_size(const knot_packet_t *packet)
{
return (KNOT_WIRE_HEADER_SIZE + 4
@@ -1005,7 +1033,7 @@ int knot_packet_set_max_size(knot_packet_t *packet, int max_size)
if (packet->max_size < max_size) {
// reallocate space for the wire format (and copy anything
// that might have been there before
- uint8_t *wire_new = (uint8_t *)malloc(max_size);
+ uint8_t *wire_new = packet->mm.alloc(packet->mm.ctx, max_size);
if (wire_new == NULL) {
return KNOT_ENOMEM;
}
@@ -1016,7 +1044,8 @@ int knot_packet_set_max_size(knot_packet_t *packet, int max_size)
packet->wireformat = wire_new;
if (packet->max_size > 0 && packet->free_wireformat) {
- free(wire_old);
+ if (packet->mm.free)
+ packet->mm.free(wire_old);
}
packet->free_wireformat = 1;
@@ -1068,6 +1097,14 @@ uint8_t knot_packet_opcode(const knot_packet_t *packet)
/*----------------------------------------------------------------------------*/
+knot_question_t *knot_packet_question(knot_packet_t *packet)
+{
+ if (packet == NULL) return NULL;
+ return &packet->question;
+}
+
+/*----------------------------------------------------------------------------*/
+
const knot_dname_t *knot_packet_qname(const knot_packet_t *packet)
{
if (packet == NULL) {
@@ -1087,7 +1124,7 @@ uint16_t knot_packet_qtype(const knot_packet_t *packet)
/*----------------------------------------------------------------------------*/
-void knot_packet_set_qtype(knot_packet_t *packet, knot_rr_type_t qtype)
+void knot_packet_set_qtype(knot_packet_t *packet, uint16_t qtype)
{
assert(packet != NULL);
packet->question.qtype = qtype;
@@ -1130,7 +1167,7 @@ int knot_packet_rcode(const knot_packet_t *packet)
if (packet == NULL) {
return KNOT_EINVAL;
}
-
+
return knot_wire_flags_get_rcode(packet->header.flags2);
}
@@ -1141,7 +1178,7 @@ int knot_packet_tc(const knot_packet_t *packet)
if (packet == NULL) {
return KNOT_EINVAL;
}
-
+
return knot_wire_flags_get_tc(packet->header.flags1);
}
@@ -1290,19 +1327,19 @@ int knot_packet_contains(const knot_packet_t *packet,
}
for (int i = 0; i < packet->an_rrsets; ++i) {
- if (knot_rrset_match(packet->answer[i], rrset, cmp)) {
+ if (knot_rrset_equal(packet->answer[i], rrset, cmp)) {
return 1;
}
}
for (int i = 0; i < packet->ns_rrsets; ++i) {
- if (knot_rrset_match(packet->authority[i], rrset, cmp)) {
+ if (knot_rrset_equal(packet->authority[i], rrset, cmp)) {
return 1;
}
}
for (int i = 0; i < packet->ar_rrsets; ++i) {
- if (knot_rrset_match(packet->additional[i], rrset, cmp)) {
+ if (knot_rrset_equal(packet->additional[i], rrset, cmp)) {
return 1;
}
}
@@ -1351,18 +1388,18 @@ dbg_packet_exec(
char *name = knot_dname_to_str(
(((knot_rrset_t **)(pkt->tmp_rrsets))[i])->owner);
dbg_packet_verb("Freeing tmp RRSet on ptr: %p (ptr to ptr:"
- " %p, type: %s, owner: %s)\n",
+ " %p, type: %u, owner: %s)\n",
(((knot_rrset_t **)(pkt->tmp_rrsets))[i]),
&(((knot_rrset_t **)(pkt->tmp_rrsets))[i]),
- knot_rrtype_to_string(
- (((knot_rrset_t **)(pkt->tmp_rrsets))[i])->type),
+ (((knot_rrset_t **)(pkt->tmp_rrsets))[i])->type,
name);
free(name);
);
// TODO: this is quite ugly, but better than copying whole
// function (for reallocating rrset array)
+ // TODO sort out freeing, this WILL leak.
knot_rrset_deep_free(
- &(((knot_rrset_t **)(pkt->tmp_rrsets))[i]), 1, 1, 1);
+ &(((knot_rrset_t **)(pkt->tmp_rrsets))[i]), 1, 1);
}
}
@@ -1490,32 +1527,22 @@ void knot_packet_free(knot_packet_t **packet)
dbg_packet("Freeing tmp RRSets...\n");
knot_packet_free_tmp_rrsets(*packet);
- dbg_packet("Freeing copied dnames for compression...\n");
- for (int i = 0; i < (*packet)->compression.count; ++i) {
- if ((*packet)->compression.to_free[i]) {
- knot_dname_release(
- (knot_dname_t *)(*packet)->compression.dnames[i]);
- }
- }
-
- /*! \note The above code will free the domain names pointed to by
- * the list of wildcard nodes. It should not matter, however.
- */
-
// check if some additional space was allocated for the packet
dbg_packet("Freeing additional allocated space...\n");
knot_packet_free_allocated_space(*packet);
// free the space for wireformat
if ((*packet)->wireformat != NULL && (*packet)->free_wireformat) {
- free((*packet)->wireformat);
+ if ((*packet)->mm.free)
+ (*packet)->mm.free((*packet)->wireformat);
}
// free EDNS options
knot_edns_free_options(&(*packet)->opt_rr);
dbg_packet("Freeing packet structure\n");
- free(*packet);
+ if ((*packet)->mm.free)
+ (*packet)->mm.free(*packet);
*packet = NULL;
}
@@ -1527,7 +1554,7 @@ static void knot_packet_dump_rrsets(const knot_rrset_t **rrsets,
assert((rrsets != NULL && *rrsets != NULL) || count < 1);
for (int i = 0; i < count; ++i) {
- knot_rrset_dump(rrsets[i], 0);
+ knot_rrset_dump(rrsets[i]);
}
}
#endif
@@ -1566,10 +1593,10 @@ void knot_packet_dump(const knot_packet_t *packet)
char *qname = knot_dname_to_str(packet->question.qname);
dbg_packet(" QNAME: %s\n", qname);
free(qname);
- dbg_packet(" QTYPE: %u (%s)\n", packet->question.qtype,
- knot_rrtype_to_string(packet->question.qtype));
- dbg_packet(" QCLASS: %u (%s)\n", packet->question.qclass,
- knot_rrclass_to_string(packet->question.qclass));
+ dbg_packet(" QTYPE: %u (%u)\n", packet->question.qtype,
+ packet->question.qtype);
+ dbg_packet(" QCLASS: %u (%u)\n", packet->question.qclass,
+ packet->question.qclass);
}
dbg_packet("\nAnswer RRSets:\n");
@@ -1592,3 +1619,18 @@ void knot_packet_dump(const knot_packet_t *packet)
#endif
}
+static int knot_packet_free_section(const knot_rrset_t **s, short count) {
+ /*! \todo The API is really incompatible here. */
+ for (short i = 0; i < count; ++i)
+ knot_rrset_deep_free((knot_rrset_t **)s + i, 1, 1);
+ return count;
+}
+
+int knot_packet_free_rrsets(knot_packet_t *packet)
+{
+ int ret = 0;
+ ret += knot_packet_free_section(packet->answer, packet->an_rrsets);
+ ret += knot_packet_free_section(packet->authority, packet->ns_rrsets);
+ ret += knot_packet_free_section(packet->additional, packet->ar_rrsets);
+ return ret;
+}
diff --git a/src/libknot/packet/packet.h b/src/libknot/packet/packet.h
index ba85aed..0921fba 100644
--- a/src/libknot/packet/packet.h
+++ b/src/libknot/packet/packet.h
@@ -37,24 +37,6 @@
#include "zone/zone.h"
/*----------------------------------------------------------------------------*/
-/*!
- * \brief Structure for holding information needed for compressing domain names.
- *
- * It's a simple table of domain names and their offsets in wire format of the
- * packet.
- *
- * \todo Consider using some better lookup structure, such as skip-list.
- */
-struct knot_compressed_dnames {
- const knot_dname_t **dnames; /*!< Domain names present in packet. */
- size_t *offsets; /*!< Offsets of domain names in the packet. */
- int *to_free; /*< Indices of dnames to free. */
- short count; /*!< Count of items in the previous arrays. */
- short max; /*!< Capacity of the structure (allocated). */
- short default_count;
-};
-
-typedef struct knot_compressed_dnames knot_compressed_dnames_t;
struct knot_wildcard_nodes {
const knot_node_t **nodes; /*!< Wildcard nodes from CNAME processing. */
@@ -101,6 +83,18 @@ enum knot_packet_prealloc_type {
typedef enum knot_packet_prealloc_type knot_packet_prealloc_type_t;
+/* Maximum number of compressed names. */
+#define COMPR_MAXLEN 64
+/* Volatile portion of the compression table. */
+#define COMPR_VOLATILE (COMPR_MAXLEN / 4)
+#define COMPR_FIXEDLEN (COMPR_MAXLEN - COMPR_VOLATILE)
+
+/* Compression table pointer. */
+typedef struct {
+ uint16_t off; /*!< Packet data offset. */
+ uint8_t lbcount; /*!< Dname label count. */
+} knot_compr_ptr_t;
+
/*----------------------------------------------------------------------------*/
/*!
* \brief Structure representing a DNS packet.
@@ -120,8 +114,6 @@ struct knot_packet {
*/
knot_question_t question;
- uint8_t *owner_tmp; /*!< Allocated space for RRSet owner wire format.*/
-
const knot_rrset_t **answer; /*!< Answer RRSets. */
const knot_rrset_t **authority; /*!< Authority RRSets. */
const knot_rrset_t **additional; /*!< Additional RRSets. */
@@ -148,7 +140,7 @@ struct knot_packet {
size_t max_size; /*!< Maximum allowed size of the packet. */
/*! \brief Information needed for compressing domain names in packet. */
- knot_compressed_dnames_t compression;
+ knot_compr_ptr_t compression[COMPR_MAXLEN];
/*! \brief Wildcard nodes to be processed for NSEC/NSEC3. */
knot_wildcard_nodes_t wildcard_nodes;
@@ -161,11 +153,12 @@ struct knot_packet {
struct knot_packet *query; /*!< Associated query. */
knot_packet_prealloc_type_t prealloc_type;
-
+
size_t tsig_size; /*!< Space to reserve for the TSIG RR. */
knot_rrset_t *tsig_rr; /*!< TSIG RR stored in the packet. */
uint16_t flags; /*!< Packet flags. */
const knot_zone_t *zone; /*!< Associated zone. */
+ mm_ctx_t mm; /*!< Memory allocation context. */
};
typedef struct knot_packet knot_packet_t;
@@ -235,25 +228,6 @@ enum {
PREALLOC_QNAME = PREALLOC_QNAME_DNAME
+ PREALLOC_QNAME_NAME
+ PREALLOC_QNAME_LABELS,
- /*!
- * \brief Space for RR owner wire format.
- *
- * Temporary buffer, used when putting RRSets to the response.
- */
- PREALLOC_RR_OWNER = 256,
-
- /*! \brief Space for one part of the compression table (domain names).*/
- PREALLOC_DOMAINS =
- DEFAULT_DOMAINS_IN_RESPONSE * sizeof(knot_dname_t *),
- /*! \brief Space for other part of the compression table (offsets). */
- PREALLOC_OFFSETS =
- DEFAULT_DOMAINS_IN_RESPONSE * sizeof(size_t),
-
- PREALLOC_TO_FREE =
- DEFAULT_DOMAINS_IN_RESPONSE * sizeof(int),
-
- PREALLOC_COMPRESSION = PREALLOC_DOMAINS + PREALLOC_OFFSETS
- + PREALLOC_TO_FREE,
PREALLOC_WC_NODES =
DEFAULT_WILDCARD_NODES * sizeof(knot_node_t *),
@@ -271,15 +245,21 @@ enum {
/*! \brief Total preallocated size for the response. */
PREALLOC_RESPONSE = PREALLOC_PACKET
+ PREALLOC_QNAME
- + PREALLOC_RR_OWNER
+ PREALLOC_RRSETS(DEFAULT_ANCOUNT)
+ PREALLOC_RRSETS(DEFAULT_NSCOUNT)
+ PREALLOC_RRSETS(DEFAULT_ARCOUNT)
- + PREALLOC_COMPRESSION
+ PREALLOC_WC
+ PREALLOC_RRSETS(DEFAULT_TMP_RRSETS)
};
+/*! \brief Flags which control packet parsing. */
+typedef enum {
+ // Don't add duplicate rdata to rrset.
+ KNOT_PACKET_DUPL_NO_MERGE = 1,
+ // Skip RR if RRSet is not empty
+ KNOT_PACKET_DUPL_SKIP = 2
+} knot_packet_flag_t;
+
/*----------------------------------------------------------------------------*/
/*!
* \brief Creates new empty packet structure.
@@ -291,6 +271,13 @@ enum {
knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc);
/*!
+ * \brief Memory managed version of new packet create.
+ *
+ * See knot_packet_new() for info about parameters and output.
+ */
+knot_packet_t *knot_packet_new_mm(knot_packet_prealloc_type_t prealloc, mm_ctx_t *mm);
+
+/*!
* \brief Parses the DNS packet from wire format.
*
* \param packet Packet structure to parse into.
@@ -299,14 +286,15 @@ knot_packet_t *knot_packet_new(knot_packet_prealloc_type_t prealloc);
* \param question_only Set to <> 0 if you do not want to parse the whole
* packet. In such case the parsing will end after the
* Question section. Set to 0 to parse the whole packet.
+ * \param flags Can control packet processing.
*
* \retval KNOT_EOK
*/
int knot_packet_parse_from_wire(knot_packet_t *packet,
const uint8_t *wireformat, size_t size,
- int question_only);
+ int question_only, knot_packet_flag_t flags);
-int knot_packet_parse_rest(knot_packet_t *packet);
+int knot_packet_parse_rest(knot_packet_t *packet, knot_packet_flag_t flags);
int knot_packet_parse_next_rr_answer(knot_packet_t *packet,
knot_rrset_t **rr);
@@ -316,6 +304,8 @@ int knot_packet_parse_next_rr_additional(knot_packet_t *packet,
size_t knot_packet_size(const knot_packet_t *packet);
+size_t knot_packet_max_size(const knot_packet_t *packet);
+
/*! \brief Returns size of the wireformat of Header and Question sections. */
size_t knot_packet_question_size(const knot_packet_t *packet);
@@ -361,6 +351,15 @@ void knot_packet_set_random_id(knot_packet_t *packet);
uint8_t knot_packet_opcode(const knot_packet_t *packet);
/*!
+ * \brief Return question section from the packet.
+ *
+ * \param packet Packet instance.
+ *
+ * \return pointer to question section.
+ */
+knot_question_t *knot_packet_question(knot_packet_t *packet);
+
+/*!
* \brief Returns the QNAME from the packet.
*
* \param packet Packet (with parsed query) to get the QNAME from.
@@ -384,7 +383,7 @@ uint16_t knot_packet_qtype(const knot_packet_t *packet);
* \param packet Packet containing question.
* \param qtype New QTYPE for question.
*/
-void knot_packet_set_qtype(knot_packet_t *packet, knot_rr_type_t qtype);
+void knot_packet_set_qtype(knot_packet_t *packet, uint16_t qtype);
/*!
@@ -573,6 +572,11 @@ void knot_packet_free(knot_packet_t **packet);
*/
void knot_packet_dump(const knot_packet_t *packet);
+/*!
+ * \brief Free all rrsets associated with packet.
+ */
+int knot_packet_free_rrsets(knot_packet_t *packet);
+
#endif /* _KNOT_PACKET_H_ */
/*! @} */
diff --git a/src/libknot/packet/query.c b/src/libknot/packet/query.c
index 8f4cf18..4bededc 100644
--- a/src/libknot/packet/query.c
+++ b/src/libknot/packet/query.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdlib.h>
#include "packet/query.h"
#include "util/wire.h"
@@ -21,74 +22,6 @@
/*----------------------------------------------------------------------------*/
-int knot_query_rr_to_wire(const knot_rrset_t *rrset, const knot_rdata_t *rdata,
- uint8_t **wire, uint8_t *endp)
-{
- /* Store owner. */
- knot_dname_t *owner = rrset->owner;
- if (*wire + owner->size > endp) {
- return KNOT_ENOMEM;
- }
- memcpy(*wire, owner->name, owner->size);
- *wire += owner->size;
-
- if (*wire + 10 > endp) {
- return KNOT_ENOMEM;
- }
-
- /* Write RR header. */
- knot_wire_write_u16(*wire, rrset->type); *wire += 2;
- knot_wire_write_u16(*wire, rrset->rclass); *wire += 2;
- knot_wire_write_u32(*wire, rrset->ttl); *wire += 4;
- knot_wire_write_u16(*wire, 0); *wire += 2; /* RDLENGTH reserve. */
- uint8_t *rdlength_p = *wire - 2;
- uint16_t rdlength = 0;
-
- /* Write data. */
- knot_dname_t *dname = 0;
- uint16_t *raw_data = 0;
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
-
- for (int i = 0; i < rdata->count; ++i) {
- switch (desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME:
-
- /* Check space for dname. */
- dname = knot_rdata_item(rdata, i)->dname;
- if (*wire + dname->size > endp) {
- return KNOT_ESPACE;
- }
-
- /* Save domain name. */
- memcpy(*wire, dname->name, dname->size);
- *wire += dname->size;
- rdlength += dname->size;
- break;
- default:
- raw_data = knot_rdata_item(rdata, i)->raw_data;
- if (*wire + raw_data[0] > endp) {
- return KNOT_ESPACE;
- }
-
- /* Copy data. */
- memcpy(*wire, raw_data + 1, raw_data[0]);
- *wire += raw_data[0];
- rdlength += raw_data[0];
- break;
-
- }
- }
-
- /* Store rdlength. */
- knot_wire_write_u16(rdlength_p, rdlength);
-
- return KNOT_EOK;
-}
-/*----------------------------------------------------------------------------*/
-
int knot_query_dnssec_requested(const knot_packet_t *query)
{
if (query == NULL) {
@@ -153,9 +86,7 @@ int knot_query_set_question(knot_packet_t *query,
query->header.qdcount = 1;
// convert the Question to wire format right away
- knot_packet_question_to_wire(query);
-
- return KNOT_EOK;
+ return knot_packet_question_to_wire(query);
}
/*----------------------------------------------------------------------------*/
@@ -203,26 +134,24 @@ int knot_query_add_rrset_authority(knot_packet_t *query,
/* Write to wire. */
uint8_t *startp = query->wireformat + query->size;
uint8_t *endp = query->wireformat + query->max_size;
-
+
assert(endp - startp > query->opt_rr.size + query->tsig_size);
// reserve space for OPT RR
/*! \todo Why here??? */
endp -= query->opt_rr.size;
/* Reserve space for TSIG RR */
endp -= query->tsig_size;
-
- uint8_t *pos = startp;
- const knot_rdata_t *rdata = 0;
- while ((rdata = knot_rrset_rdata_next(rrset, rdata))) {
- knot_query_rr_to_wire(rrset, rdata, &pos, endp);
+ size_t written = 0;
+ uint16_t rr_count = 0;
+ int ret = knot_rrset_to_wire(rrset, startp, &written, query->max_size,
+ &rr_count, NULL);
+ if (ret != KNOT_EOK) {
+ return ret;
}
-
- size_t written = (pos - startp);
query->size += written;
++query->ns_rrsets;
++query->header.nscount;
return KNOT_EOK;
}
-
diff --git a/src/libknot/packet/query.h b/src/libknot/packet/query.h
index 3ca4fd3..ee5418a 100644
--- a/src/libknot/packet/query.h
+++ b/src/libknot/packet/query.h
@@ -81,9 +81,6 @@ int knot_query_set_opcode(knot_packet_t *query, uint8_t opcode);
int knot_query_add_rrset_authority(knot_packet_t *query,
const knot_rrset_t *rrset);
-int knot_query_rr_to_wire(const knot_rrset_t *rrset, const knot_rdata_t *rdata,
- uint8_t **wire, uint8_t *endp);
-
#endif /* _KNOT_QUERY_H_ */
/*! @} */
diff --git a/src/libknot/packet/response.c b/src/libknot/packet/response.c
index 69678c7..015cdb1 100644
--- a/src/libknot/packet/response.c
+++ b/src/libknot/packet/response.c
@@ -14,725 +14,159 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdlib.h>
+#include <stdint.h>
#include "packet/response.h"
#include "util/wire.h"
-#include "util/descriptor.h"
#include "common.h"
#include "util/debug.h"
+#include "rrset.h"
#include "packet/packet.h"
#include "edns.h"
-#define COMPRESSION_PEDANTIC
-
/*----------------------------------------------------------------------------*/
-/*!
- * \brief Holds information about compressed domain name.
- *
- * Used only to pass information between functions.
- *
- * \todo This description should be revised and clarified.
- */
-struct knot_compr_owner {
- /*!
- * \brief Place where the name is stored in the wire format of the
- * packet.
- */
- uint8_t *wire;
- short size; /*!< Size of the domain name in bytes. */
- /*! \brief Position of the name relative to the start of the packet. */
- size_t pos;
-};
-
-typedef struct knot_compr_owner knot_compr_owner_t;
/*!
- * \brief Holds information about compressed domain names in packet.
- *
- * Used only to pass information between functions.
+ * \brief Compare suffixes and calculate score (number of matching labels).
*
- * \todo This description should be revised and clarified.
+ * Update current best score.
*/
-struct knot_compr {
- knot_compressed_dnames_t *table; /*!< Compression table. */
- size_t wire_pos; /*!< Current position in the wire format. */
- knot_compr_owner_t owner; /*!< Information about the current name. */
-};
-
-typedef struct knot_compr knot_compr_t;
-
-static const size_t KNOT_RESPONSE_MAX_PTR = 16383;
-
-/*----------------------------------------------------------------------------*/
-/* Non-API functions */
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Reallocates space for compression table.
- *
- * \param table Compression table to reallocate space for.
- *
- * \retval KNOT_EOK
- * \retval KNOT_ENOMEM
- */
-static int knot_response_realloc_compr(knot_compressed_dnames_t *table)
+static bool knot_response_compr_score(uint8_t *n, uint8_t *p, uint8_t labels,
+ uint8_t *wire, knot_compr_ptr_t *match)
{
- int free_old = table->max != table->default_count;
- size_t *old_offsets = table->offsets;
- int *old_to_free = table->to_free;
- const knot_dname_t **old_dnames = table->dnames;
-
- short new_max_count = table->max + STEP_DOMAINS;
-
- size_t *new_offsets = (size_t *)malloc(new_max_count * sizeof(size_t));
- CHECK_ALLOC_LOG(new_offsets, -1);
-
- int *new_to_free = (int *)malloc(new_max_count * sizeof(int));
- if (new_to_free == NULL) {
- ERR_ALLOC_FAILED;
- free(new_offsets);
- return KNOT_ENOMEM;
- }
-
- const knot_dname_t **new_dnames = (const knot_dname_t **)malloc(
- new_max_count * sizeof(knot_dname_t *));
- if (new_dnames == NULL) {
- ERR_ALLOC_FAILED;
- free(new_offsets);
- free(new_to_free);
- return KNOT_ENOMEM;
- }
-
- memcpy(new_offsets, table->offsets, table->max * sizeof(size_t));
- memcpy(new_to_free, table->to_free, table->max * sizeof(int));
- memcpy(new_dnames, table->dnames,
- table->max * sizeof(knot_dname_t *));
-
- table->offsets = new_offsets;
- table->to_free = new_to_free;
- table->dnames = new_dnames;
- table->max = new_max_count;
-
- if (free_old) {
- free(old_offsets);
- free(old_to_free);
- free(old_dnames);
- }
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Stores new mapping between domain name and offset in the compression
- * table.
- *
- * If the domain name is already present in the table, it is not inserted again.
- *
- * \param table Compression table to save the mapping into.
- * \param dname Domain name to insert.
- * \param pos Position of the domain name in the packet's wire format.
- */
-static void knot_response_compr_save(knot_compressed_dnames_t *table,
- const knot_dname_t *dname, size_t pos,
- int copied_dname)
-{
- assert(table->count < table->max);
-
- for (int i = 0; i < table->count; ++i) {
- if (table->dnames[i] == dname) {
- dbg_response("Already present, skipping..\n");
- return;
- }
- }
-
- table->dnames[table->count] = dname;
- table->offsets[table->count] = pos;
- table->to_free[table->count] = copied_dname;
- ++table->count;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Stores domain name position and positions of its parent domain names
- * to the compression table.
- *
- * If part of the domain name (\a dname) was not found previously in the
- * compression table, this part and all its parent domains is stored also, to
- * maximize compression potential.
- *
- * \param table Compression table to save the information into.
- * \param dname Domain name to save.
- * \param not_matched Count of labels not matched when previously searching in
- * the compression table for \a dname.
- * \param pos Position of the domain name in the wire format of the packet.
- * \param unmatched_offset Position of the unmatched parent domain of \a dname.
- *
- * \retval KNOT_EOK
- * \retval KNOT_ENOMEM
- */
-static int knot_response_store_dname_pos(knot_compressed_dnames_t *table,
- const knot_dname_t *dname,
- int not_matched, size_t pos,
- size_t unmatched_offset,
- int compr_cs)
-{
-dbg_response_exec(
- char *name = knot_dname_to_str(dname);
- dbg_response_detail("Putting dname %s into compression table."
- " Labels not matched: %d, position: %zu,"
- ", pointer: %p, unmatched off: %zu\n", name,
- not_matched, pos, dname, unmatched_offset);
- free(name);
-);
- if (pos > KNOT_RESPONSE_MAX_PTR) {
- dbg_response("Pointer larger than it can be, not saving\n");
- return KNOT_EDNAMEPTR;
- }
-
- if (table->count == table->max &&
- knot_response_realloc_compr(table) != 0) {
- return KNOT_ENOMEM;
- }
-
- /*
- * Store positions of ancestors if more than 1 label was not matched.
- *
- * In case the name is not in the zone, the counting to not_matched
- * may be limiting, because the search stopped before after the first
- * label (i.e. not_matched == 1). So we do not store the parents in
- * this case. However, storing them will require creating those domain
- * names, as they do not exist.
- *
- * The same problem is with domain names synthetized from wildcards.
- * These also do not have any node to follow.
- *
- * We accept this as performance has higher
- * priority than the best possible compression.
- */
- const knot_dname_t *to_save = dname;
- size_t parent_pos = pos;
- int i = 0, copied = 0;
-
- while (to_save != NULL && i < knot_dname_label_count(dname)
- && parent_pos <= KNOT_RESPONSE_MAX_PTR) {
- if (i == not_matched) {
- parent_pos = unmatched_offset;
- }
-
-dbg_response_exec_detail(
- char *name = knot_dname_to_str(to_save);
- dbg_response_detail("Putting dname %s into compression table."
- " Position: %zu, pointer: %p\n",
- name, parent_pos, to_save);
- free(name);
-);
-
- if (table->count == table->max &&
- knot_response_realloc_compr(table) != 0) {
- dbg_response("Unable to realloc.\n");
- return KNOT_ENOMEM;
- }
-
- knot_response_compr_save(table, to_save, parent_pos, copied);
-
- /*! \todo Remove '!compr_cs'. */
- // This is a temporary hack to avoid the wrong behaviour
- // when the wrong not_matched count is used to compare with i
- // and resulting in using the 0 offset.
- // If case-sensitive search is in place, we should not save the
- // node's parent's positions.
-
- // Added check to rule out wildcard-covered dnames
- // (in such case the offset is not right)
-
- /*! \todo The whole compression requires a serious refactoring.
- * Or better - a rewrite!
- */
- const knot_dname_t *to_save_new =
- (!compr_cs && knot_dname_node(to_save) != NULL
- && knot_node_owner(knot_dname_node(to_save))
- != to_save
- && knot_node_parent(knot_dname_node(to_save))
- != NULL)
- ? knot_node_owner(knot_node_parent(
- knot_dname_node(to_save)))
- : NULL;
-
-#ifdef COMPRESSION_PEDANTIC
- if (to_save_new == NULL) {
- // copied name - must be freed later
- to_save_new = knot_dname_left_chop(to_save);
- copied = 1;
+ uint16_t score = 0;
+ uint16_t off = 0;
+ while (*n != '\0') {
+ /* Can't exceed current best coverage. */
+ if (score + labels <= match->lbcount)
+ return false; /* Early cut. */
+ /* Keep track of contiguous matches. */
+ if (*n == *p && memcmp(n + 1, p + 1, *n) == 0) {
+ if (score == 0)
+ off = (p - wire);
+ ++score;
} else {
- copied = 0;
+ score = 0; /* Non-contiguous match. */
}
-#endif
-
- to_save = to_save_new;
-
- dbg_response("i: %d\n", i);
- parent_pos += knot_dname_label_size(dname, i) + 1;
- ++i;
+ n = knot_wire_next_label(n, wire);
+ p = knot_wire_next_label(p, wire);
+ --labels;
}
- if (copied == 1 && to_save != NULL) {
- // The last name was not used, free it
- dbg_response("Freeing last chopped dname.\n");
- knot_dname_release((knot_dname_t *)to_save);
+ /* New best score. */
+ if (score > match->lbcount && off <= KNOT_WIRE_PTR_MAX) {
+ match->lbcount = score;
+ match->off = off;
+ return true;
}
- return KNOT_EOK;
+ return false;
}
-/*---------------------------------------------------------------------------*/
/*!
- * \brief Tries to find offset of domain name in the compression table.
- *
- * \param table Compression table to search in.
- * \param dname Domain name to search for.
- * \param compr_cs Set to <> 0 if dname compression should use case sensitive
- * comparation. Set to 0 otherwise.
- *
- * \return Offset of \a dname stored in the compression table or -1 if the name
- * was not found in the table.
+ * \brief Align name and reference to a common number of suffix labels.
*/
-static size_t knot_response_find_dname_pos(
- const knot_compressed_dnames_t *table,
- const knot_dname_t *dname, int compr_cs)
+static uint8_t knot_response_compr_align(uint8_t **name, uint8_t nlabels,
+ uint8_t **ref, uint8_t reflabels,
+ uint8_t *wire)
{
- for (int i = 0; i < table->count; ++i) {
- int ret = (compr_cs)
- ? knot_dname_compare_cs(table->dnames[i], dname)
- : knot_dname_compare(table->dnames[i], dname);
- if (ret == 0) {
- dbg_response_detail("Found offset: %zu\n",
- table->offsets[i]);
- return table->offsets[i];
- }
- }
- return 0;
-}
+ for (unsigned j = nlabels; j < reflabels; ++j)
+ *ref = knot_wire_next_label(*ref, wire);
-/*---------------------------------------------------------------------------*/
-/*!
- * \brief Put a compressed domain name to the wire format of the packet.
- *
- * Puts the not matched part of the domain name to the wire format and puts
- * a pointer to the rest of the name after that.
- *
- * \param dname Domain name to put to the wire format.
- * \param not_matched Size of the part of domain name that cannot be compressed.
- * \param offset Position of the rest of the domain name in the packet's wire
- * format.
- * \param wire Place where to put the wire format of the name.
- * \param max Maximum available size of the place for the wire format.
- *
- * \return Size of the compressed domain name put into the wire format or
- * KNOT_ESPACE if it did not fit.
- */
-static int knot_response_put_dname_ptr(const knot_dname_t *dname,
- int not_matched, size_t offset,
- uint8_t *wire, size_t max)
-{
- // put the not matched labels
- short size = knot_dname_size_part(dname, not_matched);
- if (size + 2 > max) {
- return KNOT_ESPACE;
- }
+ for (unsigned j = reflabels; j < nlabels; ++j)
+ *name = knot_wire_next_label(*name, wire);
- memcpy(wire, knot_dname_name(dname), size);
- knot_wire_put_pointer(wire + size, offset);
-
- dbg_response_detail("Size of the dname with ptr: %d\n", size + 2);
-
- return size + 2;
+ return (nlabels < reflabels) ? nlabels : reflabels;
}
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tries to compress domain name and creates its wire format.
- *
- * \param dname Domain name to convert and compress.
- * \param compr Compression table holding information about offsets of domain
- * names in the packet.
- * \param dname_wire Place where to put the wire format of the name.
- * \param max Maximum available size of the place for the wire format.
- * \param compr_cs Set to <> 0 if dname compression should use case sensitive
- * comparation. Set to 0 otherwise.
- *
- * \return Size of the domain name's wire format or KNOT_ESPACE if it did not
- * fit into the provided space.
- */
-static int knot_response_compress_dname(const knot_dname_t *dname,
- knot_compr_t *compr, uint8_t *dname_wire, size_t max, int compr_cs)
+int knot_response_compress_dname(const knot_dname_t *dname, knot_compr_t *compr,
+ uint8_t *dst, size_t max)
{
- int size = 0;
- if (!dname || !compr || !dname_wire) {
+ if (!dname || !compr || !dst) {
return KNOT_EINVAL;
}
- // try to find the name or one of its ancestors in the compr. table
-#ifdef COMPRESSION_PEDANTIC
- knot_dname_t *to_find = (knot_dname_t *)dname;
- int copied = 0;
-#else
- const knot_dname_t *to_find = dname;
-#endif
- size_t offset = 0;
- int not_matched = 0;
-
- while (to_find != NULL && knot_dname_label_count(to_find) != 0) {
-dbg_response_exec_detail(
- char *name = knot_dname_to_str(to_find);
- dbg_response_detail("Searching for name %s in the compression"
- " table, not matched labels: %d\n", name,
- not_matched);
- free(name);
-);
- offset = knot_response_find_dname_pos(compr->table, to_find,
- compr_cs);
- if (offset == 0) {
- ++not_matched;
- } else {
- break;
+ /* Do not compress small dnames. */
+ uint8_t *name = dname->name;
+ if (dname->size <= 2) {
+ if (dname->size > max)
+ return KNOT_ESPACE;
+ memcpy(dst, name, dname->size);
+ return dname->size;
+ }
+
+ /* Align and compare name and pointer in the compression table. */
+ unsigned i = 0;
+ unsigned lbcount = 0;
+ unsigned match_id = 0;
+ knot_compr_ptr_t match = { 0, 0 };
+ for (; i < COMPR_MAXLEN && compr->table[i].off > 0; ++i) {
+ uint8_t *name = dname->name;
+ uint8_t *ref = compr->wire + compr->table[i].off;
+ lbcount = knot_response_compr_align(&name, dname->label_count,
+ &ref, compr->table[i].lbcount,
+ compr->wire);
+
+ if (knot_response_compr_score(name, ref, lbcount, compr->wire,
+ &match)) {
+ match_id = i;
+ if (match.lbcount == dname->label_count)
+ break; /* Best match, break. */
}
-#ifdef COMPRESSION_PEDANTIC
- if (compr_cs || to_find->node == NULL
- || to_find->node->owner != to_find
- || to_find->node->parent == NULL) {
- if (!copied) {
- to_find = knot_dname_left_chop(to_find);
- copied = 1;
- } else {
- knot_dname_left_chop_no_copy(to_find);
- }
- } else {
- assert(knot_dname_node(to_find) !=
- knot_node_parent(knot_dname_node(to_find)));
- assert(to_find != knot_node_owner(
- knot_node_parent(knot_dname_node(to_find))));
- to_find = knot_node_get_owner(
- knot_node_parent(knot_dname_node(to_find)));
- }
- dbg_response_detail("New to_find: %p\n", to_find);
-#else
- // if case-sensitive comparation, we cannot just take the parent
- if (compr_cs || knot_dname_node(to_find) == NULL
- || knot_node_owner(knot_dname_node(to_find)) != to_find
- || knot_node_parent(knot_dname_node(to_find))
- == NULL) {
- dbg_response_detail("compr_cs: %d\n", compr_cs);
- dbg_response_detail("knot_dname_node(to_find, 1) == %p"
- "\n", knot_dname_node(to_find));
-
- if (knot_dname_node(to_find) != NULL) {
- dbg_response_detail("knot_node_owner(knot_dname_node("
- "to_find, 1)) = %p, to_find = %p\n",
- knot_node_owner(knot_dname_node(to_find)),
- to_find);
- dbg_response_detail("knot_node_parent(knot_dname_node("
- "to_find, 1), 1) = %p\n",
- knot_node_parent(knot_dname_node(to_find)));
- }
- break;
- } else {
- assert(knot_dname_node(to_find) !=
- knot_node_parent(knot_dname_node(to_find)));
- assert(to_find != knot_node_owner(
- knot_node_parent(knot_dname_node(to_find))));
- to_find = knot_node_owner(
- knot_node_parent(knot_dname_node(to_find)));
- dbg_response_detail("New to_find: %p\n", to_find);
- }
-#endif
}
-#ifdef COMPRESSION_PEDANTIC
- if (copied) {
- knot_dname_free(&to_find);
- }
-#endif
-
- dbg_response_detail("Max size available for domain name: %zu\n", max);
-
- if (offset > 0) {
- // found such dname somewhere in the packet
- // the pointer should be legal as no illegal pointers are stored
- assert(offset <= KNOT_RESPONSE_MAX_PTR);
- dbg_response_detail("Found name in the compression table.\n");
- assert(offset >= KNOT_WIRE_HEADER_SIZE);
- size = knot_response_put_dname_ptr(dname, not_matched, offset,
- dname_wire, max);
- if (size <= 0) {
+ /* Write non-matching prefix. */
+ unsigned written = 0;
+ for (unsigned j = match.lbcount; j < dname->label_count; ++j) {
+ if (written + *name + 1 > max)
return KNOT_ESPACE;
- }
- } else {
- dbg_response_detail("Not found, putting whole name.\n");
- // now just copy the dname without compressing
- if (dname->size > max) {
- return KNOT_ESPACE;
- }
-
- memcpy(dname_wire, dname->name, dname->size);
- size = dname->size;
- }
-
- // in either way, put info into the compression table
- /*! \todo This is useless if the name was already in the table.
- * It is meaningful only if the found name is the one from QNAME
- * and thus its parents are not stored yet.
- */
- // only put legal pointers (#2131)
- if (knot_response_store_dname_pos(compr->table, dname, not_matched,
- compr->wire_pos, offset, compr_cs)
- != 0) {
- dbg_response_detail("Compression info could not be stored.\n");
- }
-
- return size;
-}
-
-/*---------------------------------------------------------------------------*/
-/*!
- * \brief Convert one RR into wire format.
- *
- * \param[in] rrset RRSet to which the RR belongs.
- * \param[in] rdata The actual RDATA of this RR.
- * \param[in] compr Information about compressed domain names in the packet.
- * \param[out] rrset_wire Place to put the wire format of the RR into.
- * \param[in] max_size Size of space available for the wire format.
- * \param[in] compr_cs Set to <> 0 if dname compression should use case
- * sensitive comparation. Set to 0 otherwise.
- *
- * \return Size of the RR's wire format or KNOT_ESPACE if it did not fit into
- * the provided space.
- */
-static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
- const knot_rdata_t *rdata,
- knot_compr_t *compr,
- uint8_t **rrset_wire, size_t max_size,
- int compr_cs)
-{
- int size = 0;
-
- dbg_response_detail("Max size: %zu, owner pos: %zu, owner size: %d\n",
- max_size, compr->owner.pos, compr->owner.size);
-
- if (size + ((compr->owner.pos == 0
- || compr->owner.pos > KNOT_RESPONSE_MAX_PTR)
- ? compr->owner.size : 2) + 10
- > max_size) {
- return KNOT_ESPACE;
+ memcpy(dst + written, name, *name + 1);
+ written += *name + 1;
+ name = knot_wire_next_label(name, compr->wire);
}
- dbg_response_detail("Owner position: %zu\n", compr->owner.pos);
-
- // put owner if needed (already compressed)
- if (compr->owner.pos == 0 || compr->owner.pos > KNOT_RESPONSE_MAX_PTR) {
- memcpy(*rrset_wire, compr->owner.wire, compr->owner.size);
- compr->owner.pos = compr->wire_pos;
- *rrset_wire += compr->owner.size;
- size += compr->owner.size;
+ /* Write out pointer covering suffix. */
+ if (*name != '\0') {
+ if (written + sizeof(uint16_t) > max)
+ return KNOT_ESPACE;
+ knot_wire_put_pointer(dst + written, match.off);
+ written += sizeof(uint16_t);
} else {
- dbg_response_detail("Putting pointer: %zu\n",
- compr->owner.pos);
- knot_wire_put_pointer(*rrset_wire, compr->owner.pos);
- *rrset_wire += 2;
- size += 2;
- }
-
- dbg_response_detail("Max size: %zu, size: %d\n", max_size, size);
-
- dbg_response_detail("Wire format:\n");
-
- // put rest of RR 'header'
- knot_wire_write_u16(*rrset_wire, rrset->type);
- dbg_response_detail(" Type: %u\n", rrset->type);
- *rrset_wire += 2;
-
- knot_wire_write_u16(*rrset_wire, rrset->rclass);
- dbg_response_detail(" Class: %u\n", rrset->rclass);
- *rrset_wire += 2;
-
- knot_wire_write_u32(*rrset_wire, rrset->ttl);
- dbg_response_detail(" TTL: %u\n", rrset->ttl);
- *rrset_wire += 4;
-
- // save space for RDLENGTH
- uint8_t *rdlength_pos = *rrset_wire;
- *rrset_wire += 2;
-
- size += 10;
- compr->wire_pos += size;
-
- dbg_response_detail("Max size: %zu, size: %d\n", max_size, size);
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
-
- uint16_t rdlength = 0;
-
- for (int i = 0; i < rdata->count; ++i) {
- if (max_size < size + rdlength) {
+ /* Not covered by compression table, write terminal. */
+ if (written + 1 > max)
return KNOT_ESPACE;
- }
-
- switch (desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME: {
- int ret = knot_response_compress_dname(
- knot_rdata_item(rdata, i)->dname,
- compr, *rrset_wire, max_size - size - rdlength,
- compr_cs);
-
- if (ret < 0) {
- return KNOT_ESPACE;
- }
-
- dbg_response_detail("Compressed dname size: %d\n", ret);
- *rrset_wire += ret;
- rdlength += ret;
- compr->wire_pos += ret;
- // TODO: compress domain name
- break;
- }
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME: {
- knot_dname_t *dname =
- knot_rdata_item(rdata, i)->dname;
- if (size + rdlength + dname->size > max_size) {
- return KNOT_ESPACE;
- }
-
- // save whole domain name
- memcpy(*rrset_wire, dname->name, dname->size);
- dbg_response_detail("Uncompressed dname size: %d\n",
- dname->size);
- *rrset_wire += dname->size;
- rdlength += dname->size;
- compr->wire_pos += dname->size;
- break;
- }
- default: {
- uint16_t *raw_data =
- knot_rdata_item(rdata, i)->raw_data;
-
- if (size + rdlength + raw_data[0] > max_size) {
- return KNOT_ESPACE;
- }
-
- // copy just the rdata item data (without size)
- memcpy(*rrset_wire, raw_data + 1, raw_data[0]);
- dbg_response_detail("Raw data size: %d\n",
- raw_data[0]);
- *rrset_wire += raw_data[0];
- rdlength += raw_data[0];
- compr->wire_pos += raw_data[0];
- break;
- }
- }
+ *(dst + written) = '\0';
+ written += 1;
}
-
- dbg_response_detail("Max size: %zu, size: %d\n", max_size, size);
-
- assert(size + rdlength <= max_size);
- size += rdlength;
- knot_wire_write_u16(rdlength_pos, rdlength);
-
- return size;
-}
-
-/*---------------------------------------------------------------------------*/
-/*!
- * \brief Convert whole RRSet into wire format.
- *
- * \param[in] rrset RRSet to convert
- * \param[out] pos Place where to put the wire format.
- * \param[out] size Size of the converted wire format.
- * \param[in] max_size Maximum available space for the wire format.
- * \param wire_pos Current position in the wire format of the whole packet.
- * \param owner_tmp Wire format of the RRSet's owner, possibly compressed.
- * \param compr Information about compressed domain names in the packet.
- * \param compr_cs Set to <> 0 if dname compression should use case sensitive
- * comparation. Set to 0 otherwise.
- *
- * \return Size of the RRSet's wire format or KNOT_ESPACE if it did not fit
- * into the provided space.
- */
-static int knot_response_rrset_to_wire(const knot_rrset_t *rrset,
- uint8_t **pos, size_t *size,
- size_t max_size, size_t wire_pos,
- uint8_t *owner_tmp,
- knot_compressed_dnames_t *compr,
- int compr_cs)
-{
-dbg_response_exec_verb(
- char *name = knot_dname_to_str(rrset->owner);
- dbg_response_verb("Converting RRSet with owner %s, type %s\n",
- name, knot_rrtype_to_string(rrset->type));
- free(name);
- dbg_response_verb(" Size before: %zu\n", *size);
-);
- // if no RDATA in RRSet, return
- if (rrset->rdata == NULL) {
- return KNOT_EOK;
+ /* Promote good matches. */
+ if (match_id > 1) {
+ match = compr->table[match_id];
+ compr->table[match_id] = compr->table[match_id - 1];
+ compr->table[match_id - 1] = match;
}
- /*
- * We may pass the current position to the compression function
- * because if the owner will be put somewhere, it will be on the
- * current position (first item of a RR). If it will not be put into
- * the wireformat, we may remove the dname (and possibly its parents)
- * from the compression table.
- */
+ /* Do not insert if exceeds bounds or full match. */
+ if (match.lbcount == dname->label_count ||
+ compr->wire_pos > KNOT_WIRE_PTR_MAX)
+ return written;
- knot_compr_t compr_info;
- compr_info.table = compr;
- compr_info.wire_pos = wire_pos;
- compr_info.owner.pos = 0;
- compr_info.owner.wire = owner_tmp;
- compr_info.owner.size =
- knot_response_compress_dname(rrset->owner, &compr_info,
- owner_tmp, max_size, compr_cs);
-
- dbg_response_detail(" Owner size: %d, position: %zu\n",
- compr_info.owner.size, compr_info.owner.pos);
- if (compr_info.owner.size < 0) {
- return KNOT_ESPACE;
+ /* If table is full, elect name from the lower 1/4 of the table
+ * and replace it. */
+ if (i == COMPR_MAXLEN) {
+ i = COMPR_FIXEDLEN + rand() % COMPR_VOLATILE;
+ compr->table[i].off = 0;
}
- int rrs = 0;
- short rrset_size = 0;
-
- const knot_rdata_t *rdata = rrset->rdata;
- do {
- int ret = knot_response_rr_to_wire(rrset, rdata, &compr_info,
- pos, max_size - rrset_size,
- compr_cs);
-
- assert(ret != 0);
-
- if (ret < 0) {
- // some RR didn't fit in, so no RRs should be used
- // TODO: remove last entries from compression table
- dbg_response("Some RR didn't fit in.\n");
- return KNOT_ESPACE;
- }
-
- dbg_response_verb("RR of size %d added.\n", ret);
- rrset_size += ret;
- ++rrs;
- } while ((rdata = knot_rrset_rdata_next(rrset, rdata)) != NULL);
-
-
- // the whole RRSet did fit in
- assert (rrset_size <= max_size);
- *size += rrset_size;
-
- dbg_response_verb(" Size after: %zu\n", *size);
+ /* Store in dname table. */
+ if (compr->table[i].off == 0) {
+ compr->table[i].off = (uint16_t)compr->wire_pos;
+ compr->table[i].lbcount = dname->label_count;
+ }
- return rrs;
+ return written;
}
/*----------------------------------------------------------------------------*/
@@ -752,8 +186,6 @@ dbg_response_exec_verb(
* \param rrset RRSet to add.
* \param tc Set to <> 0 if omitting the RRSet should cause the TC bit to be
* set in the response.
- * \param compr_cs Set to <> 0 if dname compression should use case sensitive
- * comparation. Set to 0 otherwise.
*
* \return Count of RRs added to the response or KNOT_ESPACE if the RRSet did
* not fit in the available space.
@@ -762,29 +194,36 @@ static int knot_response_try_add_rrset(const knot_rrset_t **rrsets,
short *rrset_count,
knot_packet_t *resp,
size_t max_size,
- const knot_rrset_t *rrset, int tc,
- int compr_cs)
+ const knot_rrset_t *rrset, int tc)
{
//short size = knot_response_rrset_size(rrset, &resp->compression);
dbg_response_exec(
char *name = knot_dname_to_str(rrset->owner);
- dbg_response_verb("\nAdding RRSet with owner %s and type %s: \n",
- name, knot_rrtype_to_string(rrset->type));
+ dbg_response_verb("\nAdding RRSet with owner %s and type %u: \n",
+ name, rrset->type);
free(name);
);
-
uint8_t *pos = resp->wireformat + resp->size;
- size_t size = 0;
- int rrs = knot_response_rrset_to_wire(rrset, &pos, &size, max_size,
- resp->size, resp->owner_tmp,
- &resp->compression, compr_cs);
+ size_t size = max_size;
+ compression_param_t param;
+ param.compressed_dnames = resp->compression;
+ param.wire_pos = resp->size;
+ param.wire = resp->wireformat;
+ uint16_t rr_count = 0;
+ int ret = knot_rrset_to_wire(rrset, pos, &size, max_size,
+ &rr_count, &param);
- if (rrs >= 0) {
+ if (ret != KNOT_EOK) {
+ dbg_response("Failed to convert RRSet to wire. (%s).\n,",
+ knot_strerror(ret));
+ }
+
+ if (rr_count > 0) {
rrsets[(*rrset_count)++] = rrset;
resp->size += size;
dbg_response_verb("RRset added, size: %zu, RRs: %d, total "
- "size of response: %zu\n\n", size, rrs,
+ "size of response: %zu\n\n", size, rr_count,
resp->size);
} else if (tc) {
dbg_response_verb("Setting TC bit.\n");
@@ -792,7 +231,7 @@ dbg_response_exec(
knot_wire_set_tc(resp->wireformat);
}
- return rrs;
+ return rr_count > 0 ? rr_count : ret;
}
/*----------------------------------------------------------------------------*/
@@ -917,7 +356,6 @@ int knot_response_init_from_query(knot_packet_t *response,
// copy the header from the query
memcpy(&response->header, &query->header, sizeof(knot_header_t));
- int err = 0;
/*! \todo Constant. */
size_t to_copy = 12;
@@ -926,13 +364,10 @@ int knot_response_init_from_query(knot_packet_t *response,
memcpy(&response->question, &query->question,
sizeof(knot_question_t));
- // put the qname into the compression table
- // TODO: get rid of the numeric constants
- if ((err = knot_response_store_dname_pos(&response->compression,
- response->question.qname, 0, 12, 12, 0))
- != KNOT_EOK) {
- return err;
- }
+ /* Insert QNAME into compression table. */
+ response->compression[0].off = KNOT_WIRE_HEADER_SIZE;
+ response->compression[0].lbcount = response->question.qname->label_count;
+
/*! \todo Constant. */
to_copy += 4 + knot_dname_size(response->question.qname);
@@ -942,7 +377,9 @@ int knot_response_init_from_query(knot_packet_t *response,
}
assert(response->max_size >= to_copy);
- memcpy(response->wireformat, query->wireformat, to_copy);
+ if (response->wireformat != query->wireformat) {
+ memcpy(response->wireformat, query->wireformat, to_copy);
+ }
response->size = to_copy;
// set the qr bit to 1
@@ -952,11 +389,11 @@ int knot_response_init_from_query(knot_packet_t *response,
// clear TC flag
knot_wire_flags_clear_tc(&response->header.flags1);
knot_wire_clear_tc(response->wireformat);
-
+
// clear AD flag
knot_wire_flags_clear_ad(&response->header.flags2);
knot_wire_clear_ad(response->wireformat);
-
+
// clear RA flag
knot_wire_flags_clear_ra(&response->header.flags2);
knot_wire_clear_ad(response->wireformat);
@@ -989,14 +426,8 @@ void knot_response_clear(knot_packet_t *resp, int clear_question)
resp->ns_rrsets = 0;
resp->ar_rrsets = 0;
- // free copied names for compression
- for (int i = 0; i < resp->compression.count; ++i) {
- if (resp->compression.to_free[i]) {
- knot_dname_release(
- (knot_dname_t *)resp->compression.dnames[i]);
- }
- }
- resp->compression.count = 0;
+ /* Clear compression table. */
+ memset(resp->compression, 0, COMPR_MAXLEN * sizeof(knot_compr_ptr_t));
/*! \todo Temporary RRSets are not deallocated, which may potentially
* lead to memory leaks should this function be used in other
@@ -1089,7 +520,7 @@ int knot_response_add_opt(knot_packet_t *resp,
int knot_response_add_rrset_answer(knot_packet_t *response,
knot_rrset_t *rrset, int tc,
- int check_duplicates, int compr_cs,
+ int check_duplicates,
int rotate)
{
if (response == NULL || rrset == NULL) {
@@ -1122,7 +553,7 @@ int knot_response_add_rrset_answer(knot_packet_t *response,
- response->size
- response->opt_rr.size
- response->tsig_size,
- rrset, tc, compr_cs);
+ rrset, tc);
if (rrs >= 0) {
response->header.ancount += rrs;
@@ -1142,7 +573,7 @@ int knot_response_add_rrset_answer(knot_packet_t *response,
int knot_response_add_rrset_authority(knot_packet_t *response,
knot_rrset_t *rrset, int tc,
- int check_duplicates, int compr_cs,
+ int check_duplicates,
int rotate)
{
if (response == NULL || rrset == NULL) {
@@ -1171,7 +602,7 @@ int knot_response_add_rrset_authority(knot_packet_t *response,
- response->size
- response->opt_rr.size
- response->tsig_size,
- rrset, tc, compr_cs);
+ rrset, tc);
if (rrs >= 0) {
response->header.nscount += rrs;
@@ -1191,7 +622,7 @@ int knot_response_add_rrset_authority(knot_packet_t *response,
int knot_response_add_rrset_additional(knot_packet_t *response,
knot_rrset_t *rrset, int tc,
- int check_duplicates, int compr_cs,
+ int check_duplicates,
int rotate)
{
if (response == NULL || rrset == NULL) {
@@ -1225,8 +656,8 @@ int knot_response_add_rrset_additional(knot_packet_t *response,
&response->ar_rrsets, response,
response->max_size
- response->size
- - response->tsig_size, rrset,
- tc, compr_cs);
+ - response->tsig_size, rrset,
+ tc);
if (rrs >= 0) {
response->header.arcount += rrs;
diff --git a/src/libknot/packet/response.h b/src/libknot/packet/response.h
index 277b1aa..b68ca45 100644
--- a/src/libknot/packet/response.h
+++ b/src/libknot/packet/response.h
@@ -24,8 +24,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOT_response_H_
-#define _KNOT_response_H_
+#ifndef _KNOT_RESPONSE_H_
+#define _KNOT_RESPONSE_H_
#include <stdint.h>
#include <string.h>
@@ -37,6 +37,50 @@
#include "edns.h"
/*!
+ * \brief Holds information about compressed domain name.
+ *
+ * Used only to pass information between functions.
+ *
+ * \todo This description should be revised and clarified.
+ */
+struct knot_compr_owner {
+ /*!
+ * \brief Place where the name is stored in the wire format of the
+ * packet.
+ */
+ uint8_t *wire;
+ uint8_t size; /*!< Size of the domain name in bytes. */
+ /*! \brief Position of the name relative to the start of the packet. */
+ size_t pos;
+};
+
+typedef struct knot_compr_owner knot_compr_owner_t;
+
+/*!
+ * \brief Holds information about compressed domain names in packet.
+ *
+ * Used only to pass information between functions.
+ *
+ * \todo This description should be revised and clarified.
+ */
+struct knot_compr {
+ knot_compr_ptr_t *table; /*!< Compression table. */
+ uint8_t *wire;
+ size_t wire_pos; /*!< Current position in the wire format. */
+ knot_compr_owner_t owner; /*!< Information about the current name. */
+};
+
+typedef struct knot_compr knot_compr_t;
+
+struct compression_param {
+ uint8_t *wire;
+ size_t wire_pos;
+ knot_compr_ptr_t *compressed_dnames;
+};
+
+typedef struct compression_param compression_param_t;
+
+/*!
* \brief Default maximum DNS response size
*
* This size must be supported by all servers and clients.
@@ -109,8 +153,6 @@ int knot_response_add_opt(knot_packet_t *resp,
* Otherwise set to 0.
* \param check_duplicates Set to <> 0 if the RRSet should not be added to the
* response in case it is already there.
- * \param compr_cs Set to <> 0 if dname compression should use case sensitive
- * comparation. Set to 0 otherwise.
*
* \retval KNOT_EOK if successful, or the RRSet was already in the answer.
* \retval KNOT_ENOMEM
@@ -118,7 +160,7 @@ int knot_response_add_opt(knot_packet_t *resp,
*/
int knot_response_add_rrset_answer(knot_packet_t *response,
knot_rrset_t *rrset, int tc,
- int check_duplicates, int compr_cs,
+ int check_duplicates,
int rotate);
/*!
@@ -130,8 +172,6 @@ int knot_response_add_rrset_answer(knot_packet_t *response,
* Otherwise set to 0.
* \param check_duplicates Set to <> 0 if the RRSet should not be added to the
* response in case it is already there.
- * \param compr_cs Set to <> 0 if dname compression should use case sensitive
- * comparation. Set to 0 otherwise.
*
* \retval KNOT_EOK if successful, or the RRSet was already in the answer.
* \retval KNOT_ENOMEM
@@ -139,7 +179,7 @@ int knot_response_add_rrset_answer(knot_packet_t *response,
*/
int knot_response_add_rrset_authority(knot_packet_t *response,
knot_rrset_t *rrset, int tc,
- int check_duplicates, int compr_cs,
+ int check_duplicates,
int rotate);
/*!
@@ -151,8 +191,6 @@ int knot_response_add_rrset_authority(knot_packet_t *response,
* Otherwise set to 0.
* \param check_duplicates Set to <> 0 if the RRSet should not be added to the
* response in case it is already there.
- * \param compr_cs Set to <> 0 if dname compression should use case sensitive
- * comparation. Set to 0 otherwise.
*
* \retval KNOT_EOK if successful, or the RRSet was already in the answer.
* \retval KNOT_ENOMEM
@@ -160,7 +198,7 @@ int knot_response_add_rrset_authority(knot_packet_t *response,
*/
int knot_response_add_rrset_additional(knot_packet_t *response,
knot_rrset_t *rrset, int tc,
- int check_duplicates, int compr_cs,
+ int check_duplicates,
int rotate);
/*!
@@ -201,6 +239,22 @@ int knot_response_add_nsid(knot_packet_t *response, const uint8_t *data,
int knot_response_add_wildcard_node(knot_packet_t *response,
const knot_node_t *node,
const knot_dname_t *sname);
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief Tries to compress domain name and creates its wire format.
+ *
+ * \param dname Domain name to convert and compress.
+ * \param compr Compression table holding information about offsets of domain
+ * names in the packet.
+ * \param dst Place where to put the wire format of the name.
+ * \param max Maximum available size of the place for the wire format.
+ *
+ * \return Size of the domain name's wire format or KNOT_ESPACE if it did not
+ * fit into the provided space.
+ */
+int knot_response_compress_dname(const knot_dname_t *dname,
+ knot_compr_t *compr, uint8_t *dst, size_t max);
+
#endif /* _KNOT_response_H_ */
diff --git a/src/libknot/rdata.c b/src/libknot/rdata.c
deleted file mode 100644
index d59b4e0..0000000
--- a/src/libknot/rdata.c
+++ /dev/null
@@ -1,873 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#include "common.h"
-#include "rdata.h"
-#include "util/descriptor.h"
-#include "dname.h"
-#include "zone/node.h"
-#include "util/utils.h"
-#include "util/debug.h"
-
-/*----------------------------------------------------------------------------*/
-/* Non-API functions */
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Compares two RDATA items as binary data.
- *
- * \param d1 First item.
- * \param d2 Second item.
- * \param count1 Size of the first item in bytes. If set to < 0, the size will
- * be taken from the first two bytes of \a d1.
- * \param count2 Size of the second item in bytes. If set to < 0, the size will
- * be taken from the first two bytes of \a d2.
- *
- * \retval 0 if the items are identical.
- * \retval < 0 if \a d1 goes before \a d2 in canonical order.
- * \retval > 0 if \a d1 goes after \a d2 in canonical order.
- */
-static int knot_rdata_compare_binary(const uint8_t *d1, const uint8_t *d2,
- int count1, int count2)
-{
- int i1 = 0, i2 = 0;
-
- // length stored in the first octet
- if (count1 < 0) {
- // take count from the first two bytes
- count1 = (int)(*(uint16_t *)d1);
- // and start from the third byte
- i1 = 2;
- }
- if (count2 < 0) { // dtto
- count2 = (int)(*(uint16_t *)d2);
- i2 = 2;
- }
-
-
- while (i1 < count1 && i2 < count2 && d1[i1] == d2[i2]) {
- ++i1;
- ++i2;
- }
-
- if (i1 == count1 && i2 == count2) {
- return 0;
- }
-
- if (i1 == count1 && i2 < count2) {
- return -1;
- } else if (i2 == count2 && i1 < count1) {
- return 1;
- } else {
- assert(i1 < count1 && i2 < count2);
- return (d1[i1] < d2[i2]) ? -1 : 1;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Retrieves the domain name from MX RDATA.
- *
- * \note This is only convenience function. It does not (and cannot) check if
- * the given RDATA is of the right type, so it always returns the second
- * RDATA item, even if it is not a domain name.
- *
- * \param rdata RDATA to get the MX domain name from.
- *
- * \return MX domain name stored in \a rdata or NULL if \a rdata has less than 2
- * items.
- */
-static const knot_dname_t *knot_rdata_mx_name(const knot_rdata_t *rdata)
-{
- if (rdata->count < 2) {
- return NULL;
- }
- return rdata->items[1].dname;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Retrieves the domain name from NS RDATA.
- *
- * \note This is only convenience function. It does not (and cannot) check if
- * the given RDATA is of the right type, so it always returns the first
- * RDATA item, even if it is not a domain name.
- *
- * \param rdata RDATA to get the NS domain name from.
- *
- * \return NS domain name stored in \a rdata or NULL if \a rdata has no items.
- */
-static const knot_dname_t *knot_rdata_ns_name(const knot_rdata_t *rdata)
-{
- if (rdata->count < 1) {
- return NULL;
- }
- return rdata->items[0].dname;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Retrieves the domain name from SRV RDATA.
- *
- * \note This is only convenience function. It does not (and cannot) check if
- * the given RDATA is of the right type, so it always returns the fourth
- * RDATA item, even if it is not a domain name.
- *
- * \param rdata RDATA to get the SRV domain name from.
- *
- * \return SRV domain name stored in \a rdata or NULL if \a rdata has less than
- * 4 items.
- */
-static const knot_dname_t *knot_rdata_srv_name(const knot_rdata_t *rdata)
-{
- if (rdata->count < 4) {
- return NULL;
- }
- return rdata->items[3].dname;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void knot_rdata_free_items(knot_rdata_item_t *items, unsigned int count,
- uint type, int free_all_dnames)
-{
- if (items == NULL) {
- return;
- }
-
- knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(type);
- assert(desc != NULL);
-
- assert(count <= desc->length);
-
- for (int i = 0; i < count; i++) {
- if (&(items[i]) == NULL) {
- continue;
- }
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME
- || desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME) {
- if ((items[i].dname != NULL)) {
- /*! \todo This is hack to prevent memory errors,
- * as the rdata_set_items() cannot determine
- * items type and so cannot increment
- * reference count in case of dname type.
- * Free would then release dnames that
- * aren't referenced by the rdata.
- */
- if (free_all_dnames) {
- knot_dname_release(items[i].dname);
- }
- }
- } else {
- free(items[i].raw_data);
- }
- }
-
- free(items);
-}
-
-/*----------------------------------------------------------------------------*/
-/* API functions */
-/*----------------------------------------------------------------------------*/
-
-knot_rdata_t *knot_rdata_new()
-{
- knot_rdata_t *rdata =
- (knot_rdata_t *)malloc(sizeof(knot_rdata_t));
- if (rdata == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
-
- rdata->items = NULL;
- rdata->count = 0;
- rdata->next = NULL;
-
- return rdata;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
- size_t *pos, size_t total_size, size_t rdlength,
- const knot_rrtype_descriptor_t *desc)
-{
- int i = 0;
- uint8_t item_type;
- size_t parsed = 0;
- if (!rdata || !wire || !pos || !desc) {
- return KNOT_EINVAL;
- }
-
- if (rdlength == 0) {
- rdata->items = NULL;
- return KNOT_EOK;
- }
-
- knot_rdata_item_t *items = (knot_rdata_item_t *)malloc(
- desc->length * sizeof(knot_rdata_item_t));
- CHECK_ALLOC_LOG(items, KNOT_ENOMEM);
-
- size_t item_size = 0;
- uint8_t gateway_type = 0; // only to handle IPSECKEY record
- knot_dname_t *dname = NULL;
-
- while (i < desc->length && (desc->fixed_items || parsed < rdlength)) {
-
- item_type = desc->wireformat[i];
- item_size = 0;
-
- size_t pos2;
-
- switch (item_type) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME:
- pos2 = *pos;
- dname = knot_dname_parse_from_wire(
- wire, &pos2, total_size, NULL, NULL);
- if (dname == NULL) {
- free(items);
- return KNOT_ERROR;
- }
- items[i].dname = dname;
- parsed += pos2 - *pos;
- *pos = pos2;
- dname = 0;
- break;
- case KNOT_RDATA_WF_BYTE:
- if (desc->type == KNOT_RRTYPE_IPSECKEY && i == 1) {
- gateway_type = *(wire + *pos);
- }
- item_size = 1;
- break;
- case KNOT_RDATA_WF_SHORT:
- item_size = 2;
- break;
- case KNOT_RDATA_WF_LONG:
- item_size = 4;
- break;
- case KNOT_RDATA_WF_UINT48:
- item_size = 6;
- break;
- case KNOT_RDATA_WF_TEXT:
- item_size = rdlength - parsed;
- break;
- case KNOT_RDATA_WF_TEXT_SINGLE:
- item_size = *(wire + *pos) + 1;
- break;
- case KNOT_RDATA_WF_A:
- item_size = 4;
- break;
- case KNOT_RDATA_WF_AAAA:
- item_size = 16;
- break;
- case KNOT_RDATA_WF_BINARY:
- item_size = rdlength - parsed;
- break;
- case KNOT_RDATA_WF_BINARYWITHLENGTH:
- item_size = *(wire + *pos) + 1;
- break;
- case KNOT_RDATA_WF_BINARYWITHSHORT:
- item_size = knot_wire_read_u16(wire + *pos) + 2;
- break;
- case KNOT_RDATA_WF_APL:
- // WTF? what to do with this??
- // Same as TXT, I guess.
- item_size = rdlength - parsed;
- break;
- case KNOT_RDATA_WF_IPSECGATEWAY:
- // determine size based on the 'gateway type' field
- switch (gateway_type) {
- case 0:
- item_size = 0;
- break;
- case 1:
- item_size = 4;
- break;
- case 2:
- item_size = 16;
- break;
- case 3:
- pos2 = *pos;
- dname = knot_dname_parse_from_wire(
- wire, &pos2, total_size, NULL, NULL);
- if (dname == NULL) {
- knot_rdata_free_items(items, i,
- desc->type, 1);
- return KNOT_ERROR;
- }
-
- items[i].raw_data = (uint16_t *)malloc(
- knot_dname_size(dname) + 2);
- if (items[i].raw_data == NULL) {
- knot_dname_free(&dname);
- knot_rdata_free_items(items, i,
- desc->type, 1);
- return KNOT_ENOMEM;
- }
-
- items[i].raw_data[0] = knot_dname_size(dname);
- memcpy((uint8_t *)(items[i].raw_data + 1),
- knot_dname_name(dname),
- knot_dname_size(dname));
-
- parsed += pos2 - *pos;
-
- *pos = pos2;
- knot_dname_free(&dname);
-
- // continue with next item
- ++i;
- continue;
-
- break;
- default:
- assert(0);
- }
-
- break;
- default:
- knot_rdata_free_items(items, i,
- desc->type, 1);
- return KNOT_EMALF;
-
- }
-
- if (item_size != 0) {
- if (parsed + item_size > rdlength) {
- knot_rdata_free_items(items, i,
- desc->type, 1);
- return KNOT_EFEWDATA;
- }
-
- items[i].raw_data = (uint16_t *)malloc(item_size + 2);
- if (items[i].raw_data == NULL) {
- knot_rdata_free_items(items, i,
- desc->type, 1);
- return KNOT_ENOMEM;
- }
- memcpy(items[i].raw_data, &item_size, 2);
- memcpy(items[i].raw_data + 1, wire + *pos, item_size);
- *pos += item_size;
- parsed += item_size;
- } else if (item_type == KNOT_RDATA_WF_BINARY) {
- // in this case we are at the end of the RDATA
- // and should create an empty RDATA item
- items[i].raw_data = (uint16_t *)malloc(2);
- if (items[i].raw_data == NULL) {
- knot_rdata_free_items(items, i,
- desc->type, 1);
- return KNOT_ENOMEM;
- }
- memcpy(items[i].raw_data, &item_size, 2);
- } else if (item_type != KNOT_RDATA_WF_COMPRESSED_DNAME
- && item_type != KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- && item_type != KNOT_RDATA_WF_LITERAL_DNAME) {
- assert(0);
- }
-
- ++i;
- }
-
- assert(!desc->fixed_items || i == desc->length);
-
- // all items are parsed, insert into the RDATA
- int rc;
- rc = knot_rdata_set_items(rdata, items, i);
-
- for (int j = 0; j < i; ++j) {
- assert(rdata->items[j].raw_data != NULL);
- }
-
- free(items);
- return rc;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_set_item(knot_rdata_t *rdata, uint pos,
- knot_rdata_item_t item)
-{
- if (pos >= rdata->count) {
- return KNOT_EINVAL;
- }
-
- /*! \todo As in set_items() we should increment refcounter for dnames,
- * but we don't know the item type.
- */
-
- rdata->items[pos] = item; // this should copy the union; or use memcpy?
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-unsigned int knot_rdata_item_count(const knot_rdata_t *rdata)
-{
- return rdata->count;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_set_items(knot_rdata_t *rdata,
- const knot_rdata_item_t *items, uint count)
-{
- if (rdata == NULL || items == NULL || count == 0 ||
- rdata->items != NULL) {
- return KNOT_EINVAL;
- }
-
- assert(rdata->count == 0);
- if ((rdata->items = (knot_rdata_item_t *)malloc(
- count * sizeof(knot_rdata_item_t))) == NULL) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
- }
-
- memcpy(rdata->items, items, count * sizeof(knot_rdata_item_t));
- rdata->count = count;
-
- /*! \todo Cannot determine items type, so the dname
- * refcounters should be increased in caller.
- */
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-const knot_rdata_item_t *knot_rdata_item(const knot_rdata_t *rdata,
- uint pos)
-{
- if (pos >= rdata->count) {
- return NULL;
- } else {
- return &rdata->items[pos];
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-knot_rdata_item_t *knot_rdata_get_item(const knot_rdata_t *rdata,
- uint pos)
-{
- if (pos >= rdata->count) {
- return NULL;
- } else {
- return &rdata->items[pos];
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_item_set_dname(knot_rdata_t *rdata, uint pos,
- knot_dname_t *dname)
-{
- if (pos >= rdata->count) {
- return KNOT_EINVAL;
- }
-
- /* Retain dname. */
- knot_dname_retain(dname);
-
- rdata->items[pos].dname = dname;
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_item_set_raw_data(knot_rdata_t *rdata, uint pos,
- uint16_t *raw_data)
-{
- if (pos >= rdata->count) {
- return KNOT_EINVAL;
- }
-
- rdata->items[pos].raw_data = raw_data;
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_count(const knot_rdata_t *rdata)
-{
- if (rdata == NULL) {
- return 0;
- }
-
- int count = 1;
- const knot_rdata_t *r = rdata;
-
- while (r->next != NULL && r->next != rdata) {
- r = r->next;
- ++count;
- }
-
- return count;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void knot_rdata_free(knot_rdata_t **rdata)
-{
- if (rdata == NULL || *rdata == NULL) {
- return;
- }
-
- if ((*rdata)->items) {
- free((*rdata)->items);
- }
- free(*rdata);
- *rdata = NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void knot_rdata_deep_free(knot_rdata_t **rdata, uint type,
- int free_all_dnames)
-{
- if (rdata == NULL || *rdata == NULL) {
- return;
- }
-
- if ((*rdata)->items != NULL) {
- knot_rdata_free_items((*rdata)->items, (*rdata)->count, type,
- free_all_dnames);
- }
-
- free(*rdata);
- *rdata = NULL;
-}
-
-/*----------------------------------------------------------------------------*/
-
-knot_rdata_t *knot_rdata_deep_copy(const knot_rdata_t *rdata,
- uint16_t type, int copy_dnames)
-{
- knot_rdata_t *copy = knot_rdata_new();
- CHECK_ALLOC_LOG(copy, NULL);
-
-
- if ((copy->items = (knot_rdata_item_t *)malloc(
- rdata->count * sizeof(knot_rdata_item_t))) == NULL) {
- knot_rdata_free(&copy);
- ERR_ALLOC_FAILED;
- return NULL;
- }
-
- copy->count = rdata->count;
-
- knot_rrtype_descriptor_t *d = knot_rrtype_descriptor_by_type(type);
-
- assert(copy->count <= d->length);
-
- // copy all items one by one
- for (int i = 0; i < copy->count; ++i) {
- if (d->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME
- || d->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || d->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME) {
- if (copy_dnames) {
- copy->items[i].dname =
- knot_dname_deep_copy(rdata->items[i].dname);
- } else {
- copy->items[i].dname = rdata->items[i].dname;
- knot_dname_retain(rdata->items[i].dname);
- }
- } else {
- copy->items[i].raw_data = (uint16_t *)malloc(
- rdata->items[i].raw_data[0] + 2);
- if (copy->items[i].raw_data == NULL) {
- knot_rdata_deep_free(&copy, type, 1);
- return NULL;
- }
- memcpy(copy->items[i].raw_data,
- rdata->items[i].raw_data,
- rdata->items[i].raw_data[0] + 2);
- }
- }
-
- return copy;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_compare(const knot_rdata_t *r1, const knot_rdata_t *r2,
- const uint8_t *format)
-{
- uint count = (r1->count < r2->count) ? r1->count : r2->count;
-
- int cmp = 0;
-
- for (int i = 0; i < count; ++i) {
- if (format[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- format[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- format[i] == KNOT_RDATA_WF_LITERAL_DNAME) {
- cmp = knot_dname_compare(r1->items[i].dname,
- r2->items[i].dname);
- } else {
- cmp = knot_rdata_compare_binary(
- (uint8_t *)(r1->items[i].raw_data + 1),
- (uint8_t *)(r2->items[i].raw_data + 1),
- r1->items[i].raw_data[0],
- r1->items[i].raw_data[0]);
- }
-
- if (cmp != 0) {
- return cmp;
- }
- }
-
- assert(cmp == 0);
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-const knot_dname_t *knot_rdata_cname_name(const knot_rdata_t *rdata)
-{
- if (rdata->count < 1) {
- return NULL;
- }
- return rdata->items[0].dname;
-}
-
-/*----------------------------------------------------------------------------*/
-
-const knot_dname_t *knot_rdata_dname_target(const knot_rdata_t *rdata)
-{
- if (rdata->count < 1) {
- return NULL;
- }
- return rdata->items[0].dname;
-}
-
-/*---------------------------------------------------------------------------*/
-
-const knot_dname_t *knot_rdata_get_name(const knot_rdata_t *rdata,
- uint16_t type)
-{
- // iterate over the rdata items or act as if we knew where the name is?
-
- switch (type) {
- case KNOT_RRTYPE_NS:
- return knot_rdata_ns_name(rdata);
- case KNOT_RRTYPE_MX:
- return knot_rdata_mx_name(rdata);
- case KNOT_RRTYPE_SRV:
- return knot_rdata_srv_name(rdata);
- case KNOT_RRTYPE_CNAME:
- return knot_rdata_cname_name(rdata);
- }
-
- return NULL;
-}
-
-/*---------------------------------------------------------------------------*/
-int64_t knot_rdata_soa_serial(const knot_rdata_t *rdata)
-{
- if (!rdata) {
- return -1;
- }
-
- if (rdata->count < 3) {
- return -1;
- }
-
- // the number is in network byte order, transform it
- return knot_wire_read_u32((uint8_t *)(rdata->items[2].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-void knot_rdata_soa_serial_set(knot_rdata_t *rdata, uint32_t serial)
-{
- if (!rdata || rdata->count < 3) {
- return;
- }
-
- // the number is in network byte order, transform it
- knot_wire_write_u32((uint8_t *)(rdata->items[2].raw_data + 1),
- serial);
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint32_t knot_rdata_soa_refresh(const knot_rdata_t *rdata)
-{
- if (!rdata) {
- return 0;
- }
-
- if (rdata->count < 4) {
- return 0; /*! \todo Some other error value. */
- }
-
- // the number is in network byte order, transform it
- return knot_wire_read_u32((uint8_t *)(rdata->items[3].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint32_t knot_rdata_soa_retry(const knot_rdata_t *rdata)
-{
- if (!rdata) {
- return 0;
- }
-
- if (rdata->count < 5) {
- return 0; /*! \todo Some other error value. */
- }
-
- // the number is in network byte order, transform it
- return knot_wire_read_u32((uint8_t *)(rdata->items[4].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint32_t knot_rdata_soa_expire(const knot_rdata_t *rdata)
-{
- if (!rdata) {
- return -1;
- }
-
- if (rdata->count < 6) {
- return 0; /*! \todo Some other error value. */
- }
-
- // the number is in network byte order, transform it
- return knot_wire_read_u32((uint8_t *)(rdata->items[5].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint32_t knot_rdata_soa_minimum(const knot_rdata_t *rdata)
-{
- if (!rdata) {
- return -1;
- }
-
- if (rdata->count < 7) {
- return 0; /*! \todo Some other error value. */
- }
-
- // the number is in network byte order, transform it
- return knot_wire_read_u32((uint8_t *)(rdata->items[6].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint16_t knot_rdata_rrsig_type_covered(const knot_rdata_t *rdata)
-{
- if (rdata->count < 1) {
- return 0;
- }
-
- return knot_wire_read_u16((uint8_t *)(rdata->items[0].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint8_t knot_rdata_nsec3_algorithm(const knot_rdata_t *rdata)
-{
- if (rdata->count < 1) {
- return 0;
- }
-
- return *((uint8_t *)(rdata->items[0].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint16_t knot_rdata_nsec3_iterations(const knot_rdata_t *rdata)
-{
- if (rdata->count < 3) {
- // this is actually valid value...what to return??
- return 0;
- }
-
- return knot_wire_read_u16((uint8_t *)(rdata->items[2].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-uint8_t knot_rdata_nsec3_salt_length(const knot_rdata_t *rdata)
-{
- if (rdata->count < 4) {
- return 0;
- }
-
- return *((uint8_t *)(rdata->items[3].raw_data + 1));
-}
-
-/*---------------------------------------------------------------------------*/
-
-const uint8_t *knot_rdata_nsec3_salt(const knot_rdata_t *rdata)
-{
- if (rdata->count < 4) {
- return NULL;
- }
-
- return ((uint8_t *)(rdata->items[3].raw_data + 1)) + 1;
-}
-
-/*----------------------------------------------------------------------------*/
-
-uint8_t knot_rdata_ds_digest_type(const knot_rdata_t *rdata)
-{
- if (rdata->count < 3) {
- return 0;
- }
-
- return *((uint8_t *)(rdata->items[2].raw_data + 1));
-}
-
-/*----------------------------------------------------------------------------*/
-
-uint16_t knot_rdata_ds_digest_len(const knot_rdata_t *rdata)
-{
- if (rdata->count < 4) {
- return 0;
- }
-
- return *(rdata->items[3].raw_data);
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rdata_ds_check(const knot_rdata_t *rdata)
-{
- // Check if the legth of the digest corresponds to the proper size of
- // the digest according to the given algorithm
- uint16_t len = knot_rdata_ds_digest_len(rdata);
- uint8_t type = knot_rdata_ds_digest_type(rdata);
-
- if (type == 0 || len == 0) {
- return KNOT_EINVAL;
- } else if (len != knot_ds_digest_length(type)) {
- return KNOT_EDSDIGESTLEN;
- } else {
- return KNOT_EOK;
- }
-}
diff --git a/src/libknot/rdata.h b/src/libknot/rdata.h
deleted file mode 100644
index eb7bd55..0000000
--- a/src/libknot/rdata.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/*!
- * \file rdata.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Structures representing RDATA and its items and API for manipulating
- * both.
- *
- * \addtogroup libknot
- * @{
- */
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOT_RDATA_H_
-#define _KNOT_RDATA_H_
-
-#include <stdint.h>
-#include <string.h>
-
-#include "dname.h"
-#include "util/descriptor.h"
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief RDATA item structure.
- *
- * Each RDATA may be logically divided into items, each of possible different
- * type. This structure distinguishes between general data (\a raw_data)
- * represented as an array of octets, and domain name (\a dname) as domain names
- * require special treatment within some RDATA (e.g. compressing in packets).
- */
-union knot_rdata_item {
- knot_dname_t *dname; /*!< RDATA item represented as a domain name. */
-
- /*!
- * \brief RDATA item represented as raw array of octets.
- *
- * The first two bytes hold the length of the item in bytes. The length
- * is stored in little endian.
- *
- * In some cases the stored length is also used in the wire format of
- * RDATA (e.g. character-data as defined in RFC1035). In such case,
- * the length should be less than 256, so that it fits into one byte
- * in the wireformat.
- *
- * \todo Store the length in system byte order.
- */
- uint16_t *raw_data;
-};
-
-typedef union knot_rdata_item knot_rdata_item_t;
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief RDATA structure.
- *
- * Each RDATA may be logically divided into items, each of possible different
- * type (see knot_rdata_item). This structure stores an array of such items.
- * It is not dynamic, so any RDATA structure may hold either 0 or one specified
- * number of items which cannot be changed later. However, the number of items
- * may be different for each RDATA structure. The number of items should be
- * given by descriptors for each RR type. Some types may have variable number
- * of items. In such cases, the last item in the array will be set tu NULL
- * to distinguish the actual count of items.
- *
- * This structure does not hold information about the RDATA items, such as
- * what type is which item or how long are they. This information should be
- * stored elsewhere (in descriptors) as it is RR-specific and given for each
- * RR type.
- *
- * \todo Find out whether NULL is appropriate value. If it is a possible
- * value for some of the items, we must find some other way to deal with
- * this.
- * \todo Add some function for freeing particular item? Or a non-const getter?
- */
-struct knot_rdata {
- knot_rdata_item_t *items; /*!< RDATA items comprising this RDATA. */
- unsigned int count; /*! < Count of RDATA items in this RDATA. */
- struct knot_rdata *next; /*!< Next RDATA item in a linked list. */
-};
-
-typedef struct knot_rdata knot_rdata_t;
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Creates an empty RDATA structure.
- *
- * \return Pointer to the new RDATA structure or NULL if an error occured.
- */
-knot_rdata_t *knot_rdata_new();
-
-/*!
- * \brief Parses RDATA from the given data in wire format.
- *
- * \param rdata RDATA to fill.
- * \param wire Wire format of the whole data in which the RDATA are present.
- * \param pos Position in \a wire where to start parsing.
- * \param total_size Size of the whole data.
- * \param rdlength Size of the RDATA to parse in bytes.
- * \param desc RR type descriptor for the RDATA type.
- *
- * \retval KNOT_ENOMEM
- * \retval KNOT_EFEWDATA
- * \retval KNOT_EMALF
- * \retval KNOT_ERROR
- * \retval KNOT_EOK
- */
-int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
- size_t *pos, size_t total_size, size_t rdlength,
- const knot_rrtype_descriptor_t *desc);
-
-/*!
- * \brief Sets the RDATA item on position \a pos.
- *
- * \param rdata RDATA structure in which the item should be set.
- * \param pos Position of the RDATA item to be set.
- * \param item RDATA item value to be set.
- *
- * \retval KNOT_EOK if successful.
- * \retval KNOT_EINVAL if \a pos is not a valid position.
- *
- * \todo Use the union or a pointer to it as parameter? IMHO there is always
- * only one pointer that is copied, so it doesn't matter.
- */
-int knot_rdata_set_item(knot_rdata_t *rdata, unsigned int pos,
- knot_rdata_item_t item);
-
-/*!
- * \brief Sets all RDATA items within the given RDATA structure.
- *
- * \a rdata must be empty so far (\a rdata->count == 0). The necessary space
- * is allocated.
- *
- * This function copies the array of RDATA items from \a items to \a rdata.
- *
- * \param rdata RDATA structure to store the items in.
- * \param items An array of RDATA items to be stored in this RDATA structure.
- * \param count Count of RDATA items to be stored.
- *
- * \retval 0 if successful.
- * \retval KNOT_EINVAL
- * \retval KNOT_ENOMEM
- */
-int knot_rdata_set_items(knot_rdata_t *rdata,
- const knot_rdata_item_t *items,
- unsigned int count);
-
-unsigned int knot_rdata_item_count(const knot_rdata_t *rdata);
-
-/*!
- * \brief Returns the RDATA item on position \a pos.
- *
- * \note Although returning union would be OK (no overhead), we need to be able
- * to distinguish errors (in this case by returning NULL).
- *
- * \param rdata RDATA structure to get the item from.
- * \param pos Position of the item to retrieve.
- *
- * \return The RDATA item on position \a pos, or NULL if such position does not
- * exist within the given RDATA structure.
- */
-knot_rdata_item_t *knot_rdata_get_item(const knot_rdata_t *rdata,
- unsigned int pos);
-
-/*!
- * \brief Returns the RDATA item on position \a pos.
- *
- * \note Although returning union would be OK (no overhead), we need to be able
- * to distinguish errors (in this case by returning NULL).
- * \note This function is identical to knot_rdata_get_item(), only it returns
- * constant data.
- *
- * \param rdata RDATA structure to get the item from.
- * \param pos Position of the item to retrieve.
- *
- * \return The RDATA item on position \a pos, or NULL if such position does not
- * exist within the given RDATA structure.
- */
-const knot_rdata_item_t *knot_rdata_item(const knot_rdata_t *rdata,
- unsigned int pos);
-
-/*!
- * \brief Sets the given domain name as a value of RDATA item on position
- * \a pos.
- *
- * \param rdata RDATA structure to set the item in.
- * \param pos Position of the RDATA item to set.
- * \param dname Domain name to set to the item.
- *
- * \retval KNOT_EOK if successful.
- * \retval KNOT_EINVAL
- */
-int knot_rdata_item_set_dname(knot_rdata_t *rdata, unsigned int pos,
- knot_dname_t *dname);
-
-/*!
- * \brief Sets the given raw data as a value of RDATA item on position \a pos.
- *
- * \param rdata RDATA structure to set the item in.
- * \param pos Position of the RDATA item to set.
- * \param raw_data Raw data to set to the item.
- *
- * \retval KNOT_EOK if successful.
- * \retval KNOT_EINVAL
- */
-int knot_rdata_item_set_raw_data(knot_rdata_t *rdata, unsigned int pos,
- uint16_t *raw_data);
-
-int knot_rdata_count(const knot_rdata_t *rdata);
-
-/*!
- * \brief Copies the given RDATA.
- *
- * \param rdata RDATA to copy.
- * \param type RR type of the RDATA.
- *
- * \return Copy of \a rdata.
- */
-knot_rdata_t *knot_rdata_deep_copy(const knot_rdata_t *rdata,
- uint16_t type, int copy_dnames);
-
-/*!
- * \brief Destroys the RDATA structure without deleting RDATA items.
- *
- * Also sets the given pointer to NULL.
- *
- * \param rdata RDATA structure to be destroyed.
- */
-void knot_rdata_free(knot_rdata_t **rdata);
-
-/*!
- * \brief Destroys the RDATA structure and all its RDATA items.
- *
- * RDATA items are deleted according to the given RR Type. In case of domain
- * name, it is deallocated only if either the free_all_dnames parameter is set
- * to <> 0 or the name does not contain reference to a node (i.e. it is not an
- * owner of some node) or if it does contain a reference to a node, but is
- * not equal to its owner. (If free_all_dnames is set to <> 0, no other
- * condition is evaluated.)
- *
- * Also sets the given pointer to NULL.
- *
- * \param rdata RDATA structure to be destroyed.
- * \param type RR Type of the RDATA.
- * \param free_all_dnames Set to <> 0 if you want to delete ALL domain names
- * from the RDATA. Set to 0 otherwise.
- */
-void knot_rdata_deep_free(knot_rdata_t **rdata, unsigned int type,
- int free_all_dnames);
-
-/*!
- * \brief Compares two RDATAs of the same type.
- *
- * \note Compares domain names normally (dname_compare()), i.e.
- * case-insensitive.
- *
- * \param r1 First RDATA.
- * \param r2 Second RDATA.
- * \param format Descriptor of the RDATA format.
- *
- * \retval 0 if RDATAs are equal.
- * \retval < 0 if \a r1 goes before \a r2 in canonical order.
- * \retval > 0 if \a r1 goes after \a r2 in canonical order.
- */
-int knot_rdata_compare(const knot_rdata_t *r1, const knot_rdata_t *r2,
- const uint8_t *format);
-
-/*!
- * \brief Retrieves the domain name from CNAME RDATA.
- *
- * \note This is only convenience function. It does not (and cannot) check if
- * the given RDATA is of the right type, so it always returns the first
- * RDATA item, even if it is not a domain name.
- *
- * \param rdata RDATA to get the CNAME domain name from.
- *
- * \return Canonical name stored in \a rdata or NULL if \a rdata has no items.
- */
-const knot_dname_t *knot_rdata_cname_name(const knot_rdata_t *rdata);
-
-/*!
- * \brief Retrieves the domain name from DNAME RDATA.
- *
- * \note This is only convenience function. It does not (and cannot) check if
- * the given RDATA is of the right type, so it always returns the first
- * RDATA item, even if it is not a domain name.
- *
- * \param rdata RDATA to get the DNAME domain name from.
- *
- * \return Target domain name stored in \a rdata or NULL if \a rdata has no
- * items.
- */
-const knot_dname_t *knot_rdata_dname_target(const knot_rdata_t *rdata);
-
-/*!
- * \brief Retrieves the domain name from RDATA of given type.
- *
- * Supported types:
- * - KNOT_RRTYPE_NS
- * - KNOT_RRTYPE_MX
- * - KNOT_RRTYPE_SRV
- * - KNOT_RRTYPE_CNAME
- *
- * \note This is only convenience function. It does not (and cannot) check if
- * the given RDATA is of the right type, so it always returns the RDATA
- * item according to the given type, even if it is not a domain name.
- *
- * \param rdata RDATA to get the domain name from.
- * \param type RR type of the RDATA.
- *
- * \return Domain name stored in \a rdata or NULL if \a rdata has not enough
- * items.
- */
-const knot_dname_t *knot_rdata_get_name(const knot_rdata_t *rdata,
- uint16_t type);
-
-int64_t knot_rdata_soa_serial(const knot_rdata_t *rdata);
-void knot_rdata_soa_serial_set(knot_rdata_t *rdata, uint32_t serial);
-
-uint32_t knot_rdata_soa_refresh(const knot_rdata_t *rdata);
-uint32_t knot_rdata_soa_retry(const knot_rdata_t *rdata);
-uint32_t knot_rdata_soa_expire(const knot_rdata_t *rdata);
-uint32_t knot_rdata_soa_minimum(const knot_rdata_t *rdata);
-
-uint16_t knot_rdata_rrsig_type_covered(const knot_rdata_t *rdata);
-
-uint8_t knot_rdata_nsec3_algorithm(const knot_rdata_t *rdata);
-uint16_t knot_rdata_nsec3_iterations(const knot_rdata_t *rdata);
-uint8_t knot_rdata_nsec3_salt_length(const knot_rdata_t *rdata);
-const uint8_t *knot_rdata_nsec3_salt(const knot_rdata_t *rdata);
-
-uint8_t knot_rdata_ds_digest_type(const knot_rdata_t *rdata);
-uint16_t knot_rdata_ds_digest_len(const knot_rdata_t *rdata);
-int knot_rdata_ds_check(const knot_rdata_t *rdata);
-
-#endif /* _KNOT_RDATA_H */
-
-/*! @} */
diff --git a/src/libknot/rrset-dump.c b/src/libknot/rrset-dump.c
new file mode 100644
index 0000000..e22a629
--- /dev/null
+++ b/src/libknot/rrset-dump.c
@@ -0,0 +1,2090 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "libknot/rrset-dump.h"
+
+#include <stdlib.h> // free
+#include <stdbool.h> // bool
+#include <string.h> // memcpy
+#include <time.h> // strftime
+#include <ctype.h> // isprint
+#include <math.h> // pow
+#include <inttypes.h> // PRIu64
+#include <sys/types.h> // (OpenBSD)
+#include <sys/socket.h> // AF_INET (BSD)
+#include <netinet/in.h> // in_addr (BSD)
+#include <arpa/inet.h> // ntohs
+
+#include "common/errcode.h" // KNOT_EOK
+#include "common/base64.h" // base64
+#include "common/base32hex.h" // base32hex
+#include "common/descriptor.h" // KNOT_RRTYPE
+#include "libknot/consts.h" // knot_rcode_names
+#include "libknot/util/utils.h" // knot_wire_read_u16
+
+#define TAB_WIDTH 8
+#define BLOCK_WIDTH 40
+#define BLOCK_INDENT "\n\t\t\t\t"
+
+#define LOC_ZERO 2147483648 // 2^31
+
+typedef struct {
+ const knot_dump_style_t *style;
+ const uint8_t *in;
+ size_t in_max;
+ char *out;
+ size_t out_max;
+ size_t total;
+ int ret;
+} rrset_dump_params_t;
+
+const knot_dump_style_t KNOT_DUMP_STYLE_DEFAULT = {
+ .wrap = false,
+ .show_class = true,
+ .show_ttl = true,
+ .verbose = false,
+ .reduce = true,
+ .human_ttl = false,
+ .human_tmstamp = false
+};
+
+static void dump_string(rrset_dump_params_t *p, const char *str)
+{
+ size_t in_len = strlen(str);
+
+ p->ret = -1;
+
+ // Check input size (+ 1 termination).
+ if (in_len >= p->out_max) {
+ return;
+ }
+
+ // Copy string including termination '\0'!
+ if (memcpy(p->out, str, in_len + 1) == NULL) {
+ return;
+ }
+
+ // Fill in output.
+ p->out += in_len;
+ p->out_max -= in_len;
+ p->total += in_len;
+ p->ret = 0;
+}
+
+static void wire_num8_to_str(rrset_dump_params_t *p)
+{
+ uint8_t data = *(p->in);
+ size_t in_len = sizeof(data);
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Write number.
+ int ret = snprintf(p->out, p->out_max, "%u", data);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_num16_to_str(rrset_dump_params_t *p)
+{
+ uint16_t data;
+ size_t in_len = sizeof(data);
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ data = knot_wire_read_u16(p->in);
+
+ // Write number.
+ int ret = snprintf(p->out, p->out_max, "%u", data);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_num32_to_str(rrset_dump_params_t *p)
+{
+ uint32_t data;
+ size_t in_len = sizeof(data);
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ data = knot_wire_read_u32(p->in);
+
+ // Write number.
+ int ret = snprintf(p->out, p->out_max, "%u", data);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_num48_to_str(rrset_dump_params_t *p)
+{
+ uint64_t data;
+ size_t in_len = 6;
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ data = knot_wire_read_u48(p->in);
+
+ // Write number.
+ int ret = snprintf(p->out, p->out_max, "%"PRIu64"", data);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_ipv4_to_str(rrset_dump_params_t *p)
+{
+ struct in_addr addr4;
+ size_t in_len = sizeof(addr4.s_addr);
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ if (memcpy(&(addr4.s_addr), p->in, in_len) == NULL) {
+ return;
+ }
+
+ // Write address.
+ if (inet_ntop(AF_INET, &addr4, p->out, p->out_max) == NULL) {
+ return;
+ }
+ out_len = strlen(p->out);
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_ipv6_to_str(rrset_dump_params_t *p)
+{
+ struct in6_addr addr6;
+ size_t in_len = sizeof(addr6.s6_addr);
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ if (memcpy(&(addr6.s6_addr), p->in, in_len) == NULL) {
+ return;
+ }
+
+ // Write address.
+ if (inet_ntop(AF_INET6, &addr6, p->out, p->out_max) == NULL) {
+ return;
+ }
+ out_len = strlen(p->out);
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_type_to_str(rrset_dump_params_t *p)
+{
+ char type[32];
+ uint16_t data;
+ size_t in_len = sizeof(data);
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ if (memcpy(&data, p->in, in_len) == NULL) {
+ return;
+ }
+
+ // Get record type name string.
+ if (knot_rrtype_to_string(ntohs(data), type, sizeof(type)) <= 0) {
+ return;
+ }
+
+ // Write string.
+ int ret = snprintf(p->out, p->out_max, "%s", type);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+
+static int hex_encode(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t *out,
+ const uint32_t out_len)
+{
+ static const char hex[] = "0123456789ABCDEF";
+
+ if (out_len < 2 * in_len) {
+ return -1;
+ }
+
+ for (uint32_t i = 0; i < in_len; i++) {
+ out[2 * i] = hex[in[i] / 16];
+ out[2 * i + 1] = hex[in[i] % 16];
+ }
+
+ return 2 * in_len;
+}
+
+static int hex_encode_alloc(const uint8_t *in,
+ const uint32_t in_len,
+ uint8_t **out)
+{
+ uint32_t out_len = 2 * in_len;
+
+ // Allocating output buffer.
+ *out = malloc(out_len);
+
+ if (*out == NULL) {
+ return -1;
+ }
+
+ // Encoding data.
+ return hex_encode(in, in_len, *out, out_len);
+}
+
+typedef int (*encode_t)(const uint8_t *in, const uint32_t in_len,
+ uint8_t *out, const uint32_t out_len);
+
+typedef int (*encode_alloc_t)(const uint8_t *in, const uint32_t in_len,
+ uint8_t **out);
+
+static void wire_data_encode_to_str(rrset_dump_params_t *p,
+ encode_t enc, encode_alloc_t enc_alloc)
+{
+ int ret;
+ size_t in_len = p->in_max;
+
+ p->ret = -1;
+
+ // One-line vs multi-line mode.
+ if (p->style->wrap == false) {
+ // Encode data directly to the output.
+ ret = enc(p->in, in_len, (uint8_t *)(p->out), p->out_max);
+ if (ret <= 0) {
+ return;
+ }
+ size_t out_len = ret;
+
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ } else {
+ int src_begin, src_len;
+ char *buf;
+
+ // Encode data to the temporary buffer.
+ ret = enc_alloc(p->in, in_len, (uint8_t **)&buf);
+ if (ret <= 0) {
+ return;
+ }
+
+ // Loop which wraps base64 block in more lines.
+ for (src_begin = 0; src_begin < ret; src_begin += BLOCK_WIDTH) {
+ if (src_begin > 0) {
+ // Write indent block.
+ dump_string(p, BLOCK_INDENT);
+ if (p->ret != 0) {
+ free(buf);
+ return;
+ }
+ }
+
+ // Compute block length (the last one can be shorter).
+ src_len = (ret - src_begin) < BLOCK_WIDTH ?
+ (ret - src_begin) : BLOCK_WIDTH;
+
+ if ((size_t)src_len > p->out_max) {
+ free(buf);
+ return;
+ }
+
+ // Write data block.
+ memcpy(p->out, buf + src_begin, src_len);
+
+ p->out += src_len;
+ p->out_max -= src_len;
+ p->total += src_len;
+ }
+
+ // Destroy temporary buffer.
+ free(buf);
+ }
+
+ // String termination.
+ if (p->out_max > 0) {
+ *p->out = '\0';
+ } else {
+ return;
+ }
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->ret = 0;
+}
+
+static void wire_len_data_encode_to_str(rrset_dump_params_t *p,
+ encode_t enc,
+ const size_t len_len,
+ const bool print_len,
+ const char *empty_str)
+{
+ size_t in_len;
+
+ p->ret = -1;
+
+ // First len_len bytes are data length.
+ if (p->in_max < len_len) {
+ return;
+ }
+
+ // Read data length.
+ switch (len_len) {
+ case 1:
+ in_len = *(p->in);
+ break;
+ case 2:
+ in_len = knot_wire_read_u16(p->in);
+ break;
+ case 4:
+ in_len = knot_wire_read_u32(p->in);
+ break;
+ default:
+ return;
+ }
+
+ // If required print data length.
+ if (print_len == true) {
+ switch (len_len) {
+ case 1:
+ wire_num8_to_str(p);
+ break;
+ case 2:
+ wire_num16_to_str(p);
+ break;
+ case 4:
+ wire_num32_to_str(p);
+ break;
+ }
+
+ if (p->ret != 0) {
+ return;
+ }
+
+ // If something follows, print one space character.
+ if (in_len > 0 || *empty_str != '\0') {
+ dump_string(p, " ");
+ if (p->ret != 0) {
+ return;
+ }
+ }
+ } else {
+ p->in += len_len;
+ p->in_max -= len_len;
+ }
+
+ if (in_len > 0) {
+ // Encode data directly to the output.
+ int ret = enc(p->in, in_len, (uint8_t *)(p->out), p->out_max);
+ if (ret <= 0) {
+ return;
+ }
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+
+ // String termination.
+ if (p->out_max > 0) {
+ *p->out = '\0';
+ } else {
+ return;
+ }
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ } else if (*empty_str != '\0') {
+ dump_string(p, empty_str);
+ if (p->ret != 0) {
+ return;
+ }
+ }
+
+ p->ret = 0;
+}
+
+static void wire_text_to_str(rrset_dump_params_t *p)
+{
+ p->ret = -1;
+
+ // First byte is string length.
+ if (p->in_max < 1) {
+ return;
+ }
+ size_t in_len = *(p->in);
+ p->in++;
+ p->in_max--;
+
+ // Check if the given length makes sense.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Opening quoatition.
+ dump_string(p, "\"");
+ if (p->ret != 0) {
+ return;
+ }
+
+ // Loop over all characters.
+ for (size_t i = 0; i < in_len; i++) {
+ char ch = (char)(p->in)[i];
+
+ if (isprint((unsigned char)(ch)) != 0) {
+ // For special character print leading slash.
+ if (ch == '\\' || ch == '"') {
+ dump_string(p, "\\");
+ if (p->ret != 0) {
+ return;
+ }
+ }
+
+ // Print text character.
+ if (p->out_max == 0) {
+ return;
+ }
+
+ *p->out = ch;
+ p->out++;
+ p->out_max--;
+ p->total++;
+ } else {
+ // Unprintable character encode via \ddd notation.
+ int ret = snprintf(p->out, p->out_max,"\\%03u", ch);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+ }
+ }
+
+ // Closing quoatition.
+ dump_string(p, "\"");
+ if (p->ret != 0) {
+ return;
+ }
+
+ // String termination.
+ if (p->out_max > 0) {
+ *p->out = '\0';
+ } else {
+ return;
+ }
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->ret = 0;
+}
+
+static void wire_timestamp_to_str(rrset_dump_params_t *p)
+{
+ uint32_t data;
+ size_t in_len = sizeof(data);
+ size_t out_len = 0;
+ int ret;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ if (memcpy(&data, p->in, in_len) == NULL) {
+ return;
+ }
+
+ time_t timestamp = ntohl(data);
+
+ if (p->style->human_tmstamp) {
+ // Write timestamp in YYYYMMDDhhmmss format.
+ ret = strftime(p->out, p->out_max, "%Y%m%d%H%M%S",
+ gmtime(&timestamp));
+ if (ret == 0) {
+ return;
+ }
+ } else {
+ // Write timestamp only.
+ ret = snprintf(p->out, p->out_max, "%u", ntohl(data));
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static int time_to_human_str(char *out,
+ const size_t out_len,
+ uint32_t data)
+{
+ size_t total_len = 0;
+ uint32_t num;
+ int ret;
+
+ // Process days.
+ num = data / 86400;
+ if (num > 0) {
+ ret = snprintf(out + total_len, out_len - total_len,
+ "%ud", num);
+ if (ret <= 0 || (size_t)ret >= out_len - total_len) {
+ return -1;
+ }
+
+ total_len += ret;
+ data -= num * 86400;
+ }
+
+ // Process hours.
+ num = data / 3600;
+ if (num > 0) {
+ ret = snprintf(out + total_len, out_len - total_len,
+ "%uh", num);
+ if (ret <= 0 || (size_t)ret >= out_len - total_len) {
+ return -1;
+ }
+
+ total_len += ret;
+ data -= num * 3600;
+ }
+
+ // Process minutes.
+ num = data / 60;
+ if (num > 0) {
+ ret = snprintf(out + total_len, out_len - total_len,
+ "%um", num);
+ if (ret <= 0 || (size_t)ret >= out_len - total_len) {
+ return -1;
+ }
+
+ total_len += ret;
+ data -= num * 60;
+ }
+
+ // Process seconds.
+ num = data;
+ if (num > 0 || total_len == 0) {
+ ret = snprintf(out + total_len, out_len - total_len,
+ "%us", num);
+ if (ret <= 0 || (size_t)ret >= out_len - total_len) {
+ return -1;
+ }
+
+ total_len += ret;
+ }
+
+ return total_len;
+}
+
+static void wire_ttl_to_str(rrset_dump_params_t *p)
+{
+ uint32_t data;
+ size_t in_len = sizeof(data);
+ size_t out_len = 0;
+ int ret;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ if (memcpy(&data, p->in, in_len) == NULL) {
+ return;
+ }
+
+ if (p->style->human_ttl) {
+ // Write time in human readable format.
+ ret = time_to_human_str(p->out, p->out_max, ntohl(data));
+ if (ret <= 0) {
+ return;
+ }
+ } else {
+ // Write timestamp only.
+ ret = snprintf(p->out, p->out_max, "%u", ntohl(data));
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_bitmap_to_str(rrset_dump_params_t *p)
+{
+ int ret;
+ char type[32];
+ size_t i = 0;
+ size_t in_len = p->in_max;
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Loop over bitmap window array (can be empty).
+ while (i < in_len) {
+ // First byte is window number.
+ uint8_t win = p->in[i++];
+
+ // Check window length (length must follow).
+ if (i >= in_len) {
+ return;
+ }
+
+ // Second byte is window length.
+ uint8_t bitmap_len = p->in[i++];
+
+ // Check window length (len bytes must follow).
+ if (i + bitmap_len > in_len) {
+ return;
+ }
+
+ // Bitmap processing.
+ for (size_t j = 0; j < (bitmap_len * 8); j++) {
+ if ((p->in[i + j / 8] & (128 >> (j % 8))) != 0) {
+ uint16_t type_num = win * 256 + j;
+
+ if (knot_rrtype_to_string(type_num, type,
+ sizeof(type)) <= 0) {
+ return;
+ }
+
+ // Print type name to type list.
+ if (out_len > 0) {
+ ret = snprintf(p->out, p->out_max,
+ " %s", type);
+ } else {
+ ret = snprintf(p->out, p->out_max,
+ "%s", type);
+ }
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len += ret;
+ p->out += ret;
+ p->out_max -= ret;
+ }
+ }
+
+ i += bitmap_len;
+ }
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_dname_to_str(rrset_dump_params_t *p)
+{
+ knot_dname_t *dname;
+ uint8_t label_len;
+ size_t in_len = 0;
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Compute dname length.
+ do {
+ // Read label length.
+ if (p->in_max < 1) {
+ return;
+ }
+ label_len = *(p->in);
+ in_len++;
+ p->in++;
+ p->in_max--;
+
+ if (label_len > p->in_max) {
+ return;
+ }
+ in_len += label_len;
+ p->in += label_len;
+ p->in_max -= label_len;
+ } while (label_len > 0);
+
+ // Create dname.
+ dname = knot_dname_new_from_wire(p->in - in_len, in_len, NULL);
+ if (dname == NULL) {
+ return;
+ }
+
+ // Write dname string.
+ char *dname_str = knot_dname_to_str(dname);
+ knot_dname_release(dname);
+ int ret = snprintf(p->out, p->out_max, "%s", dname_str);
+ free(dname_str);
+ if (ret < 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void ptr_dname_to_str(rrset_dump_params_t *p)
+{
+ knot_dname_t *dname;
+ size_t in_len = sizeof(knot_dname_t *);
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ if (memcpy(&dname, p->in, in_len) == NULL) {
+ return;
+ }
+
+ // Write dname string.
+ char *dname_str = knot_dname_to_str(dname);
+ int ret = snprintf(p->out, p->out_max, "%s", dname_str);
+ free(dname_str);
+ if (ret < 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+ p->ret = 0;
+}
+
+static void wire_apl_to_str(rrset_dump_params_t *p)
+{
+ struct in_addr addr4;
+ struct in6_addr addr6;
+ int ret;
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Input check: family(2B) + prefix(1B) + afdlen(1B).
+ if (p->in_max < 4) {
+ return;
+ }
+
+ // Read fixed size values.
+ uint16_t family = knot_wire_read_u16(p->in);
+ uint8_t prefix = *(p->in + 2);
+ uint8_t negation = *(p->in + 3) >> 7;
+ uint8_t afdlen = *(p->in + 3) & 0x7F;
+ p->in += 4;
+ p->in_max -= 4;
+
+ // Write negation mark.
+ if (negation != 0) {
+ dump_string(p, "!");
+ if (p->ret != 0) {
+ return;
+ }
+ }
+
+ // Write address family with colon.
+ ret = snprintf(p->out, p->out_max, "%u:", family);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+
+ // Write address.
+ switch (family) {
+ case 1:
+ memset(&addr4, 0, sizeof(addr4));
+
+ if (afdlen > sizeof(addr4.s_addr) || afdlen > p->in_max) {
+ return;
+ }
+
+ if (memcpy(&(addr4.s_addr), p->in, afdlen) == NULL) {
+ return;
+ }
+
+ // Write address.
+ if (inet_ntop(AF_INET, &addr4, p->out, p->out_max) == NULL) {
+ return;
+ }
+ out_len = strlen(p->out);
+
+ break;
+ case 2:
+ memset(&addr6, 0, sizeof(addr6));
+
+ if (afdlen > sizeof(addr6.s6_addr) || afdlen > p->in_max) {
+ return;
+ }
+
+ if (memcpy(&(addr6.s6_addr), p->in, afdlen) == NULL) {
+ return;
+ }
+
+ // Write address.
+ if (inet_ntop(AF_INET6, &addr6, p->out, p->out_max) == NULL) {
+ return;
+ }
+ out_len = strlen(p->out);
+
+ break;
+ default:
+ return;
+ }
+ p->in += afdlen;
+ p->in_max -= afdlen;
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+
+ // Write prefix length with forward slash.
+ ret = snprintf(p->out, p->out_max, "/%u", prefix);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+
+ p->ret = 0;
+}
+
+static void wire_loc_to_str(rrset_dump_params_t *p)
+{
+ int ret;
+ size_t in_len = 16;
+
+ p->ret = -1;
+
+ // Check input size (1 LOC = 16 B).
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Read values.
+ uint8_t version = *p->in;
+ p->in++;
+ uint8_t size_w = *p->in;
+ p->in++;
+ uint8_t hpre_w = *p->in;
+ p->in++;
+ uint8_t vpre_w = *p->in;
+ p->in++;
+ uint32_t lat_w = knot_wire_read_u32(p->in);
+ p->in += 4;
+ uint32_t lon_w = knot_wire_read_u32(p->in);
+ p->in += 4;
+ uint32_t alt_w = knot_wire_read_u32(p->in);
+ p->in += 4;
+
+ p->in_max -= in_len;
+
+ // Version check.
+ if (version != 0) {
+ return;
+ }
+
+ // Latitude calculation.
+ char lat_mark;
+ uint32_t lat;
+ if (lat_w >= LOC_ZERO) {
+ lat_mark = 'N';
+ lat = lat_w - LOC_ZERO;
+ } else {
+ lat_mark = 'S';
+ lat = LOC_ZERO - lat_w;
+ }
+
+ uint32_t d1 = lat / 3600000;
+ uint32_t m1 = (lat - 3600000 * d1) / 60000;
+ double s1 = 0.001 * (lat - 3600000 * d1 - 60000 * m1);
+
+ // Longitude calculation.
+ char lon_mark;
+ uint32_t lon;
+ if (lon_w >= LOC_ZERO) {
+ lon_mark = 'E';
+ lon = lon_w - LOC_ZERO;
+ } else {
+ lon_mark = 'W';
+ lon = LOC_ZERO - lon_w;
+ }
+
+ uint32_t d2 = lon / 3600000;
+ uint32_t m2 = (lon - 3600000 * d2) / 60000;
+ double s2 = 0.001 * (lon - 3600000 * d2 - 60000 * m2);
+
+ // Write latitude and longitude.
+ ret = snprintf(p->out, p->out_max, "%u %u %.*f %c %u %u %.*f %c",
+ d1, m1, (uint32_t)s1 != s1 ? 3 : 0, s1, lat_mark,
+ d2, m2, (uint32_t)s2 != s2 ? 3 : 0, s2, lon_mark);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+
+ // Altitude calculation.
+ double alt = 0.01 * alt_w - 100000.0;
+
+ // Compute mantisa and exponent for each size.
+ uint8_t size_m = size_w >> 4;
+ uint8_t size_e = size_w & 0xF;
+ uint8_t hpre_m = hpre_w >> 4;
+ uint8_t hpre_e = hpre_w & 0xF;
+ uint8_t vpre_m = vpre_w >> 4;
+ uint8_t vpre_e = vpre_w & 0xF;
+
+ // Sizes check.
+ if (size_m > 9 || size_e > 9 || hpre_m > 9 || hpre_e > 9 ||
+ vpre_m > 9 || vpre_e > 9) {
+ return;
+ }
+
+ // Size and precisions calculation.
+ double size = 0.01 * size_m * pow(10, size_e);
+ double hpre = 0.01 * hpre_m * pow(10, hpre_e);
+ double vpre = 0.01 * vpre_m * pow(10, vpre_e);
+
+ // Write altitude and precisions.
+ ret = snprintf(p->out, p->out_max, " %.*fm %.*fm %.*fm %.*fm",
+ (int32_t)alt != alt ? 2 : 0, alt,
+ (uint32_t)size != size ? 2 : 0, size,
+ (uint32_t)hpre != hpre ? 2 : 0, hpre,
+ (uint32_t)vpre != vpre ? 2 : 0, vpre);
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+
+ p->ret = 0;
+}
+
+static void wire_gateway_to_str(rrset_dump_params_t *p)
+{
+ p->ret = -1;
+
+ // Input check: type(1B) + algo(1B).
+ if (p->in_max < 2) {
+ return;
+ }
+
+ uint8_t type = *p->in;
+ uint8_t alg = *(p->in + 1);
+
+ // Write gateway type.
+ wire_num8_to_str(p);
+ if (p->ret != 0) {
+ return;
+ }
+
+ // Write space.
+ dump_string(p, " ");
+ if (p->ret != 0) {
+ return;
+ }
+
+ // Write algorithm number.
+ wire_num8_to_str(p);
+ if (p->ret != 0) {
+ return;
+ }
+
+ // Write space.
+ dump_string(p, " ");
+ if (p->ret != 0) {
+ return;
+ }
+
+ // Write appropriate gateway.
+ switch (type) {
+ case 0:
+ dump_string(p, ".");
+ break;
+ case 1:
+ wire_ipv4_to_str(p);
+ break;
+ case 2:
+ wire_ipv6_to_str(p);
+ break;
+ case 3:
+ wire_dname_to_str(p);
+ break;
+ default:
+ return;
+ }
+ if (p->ret != 0) {
+ return;
+ }
+
+ if (alg > 0) {
+ // If wrap mode wrap line.
+ if (p->style->wrap) {
+ dump_string(p, BLOCK_INDENT);
+ } else {
+ dump_string(p, " ");
+ }
+ if (p->ret != 0) {
+ return;
+ }
+
+ // Write ipsec key.
+ wire_data_encode_to_str(p, &base64_encode, &base64_encode_alloc);
+ if (p->ret != 0) {
+ return;
+ }
+ }
+
+ p->ret = 0;
+}
+
+static void wire_l64_to_str(rrset_dump_params_t *p)
+{
+ p->ret = -1;
+
+ // Check input size (64-bit identifier).
+ if (p->in_max != 8) {
+ return;
+ }
+
+ // Write identifier (2-byte) labels separated with a colon.
+ while (p->in_max > 0) {
+ int ret = hex_encode(p->in, 2, (uint8_t *)(p->out), p->out_max);
+ if (ret <= 0) {
+ return;
+ }
+ p->in += 2;
+ p->in_max -= 2;
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+
+ // Write separation character.
+ if (p->in_max > 0) {
+ dump_string(p, ":");
+ if (p->ret != 0) {
+ return;
+ }
+ }
+ }
+
+ p->ret = 0;
+}
+
+static void wire_eui_to_str(rrset_dump_params_t *p)
+{
+ p->ret = -1;
+
+ // Data can't have zero length.
+ if (p->in_max < 2) {
+ return;
+ }
+
+ // Write EUI hexadecimal pairs.
+ while (p->in_max > 0) {
+ int ret = hex_encode(p->in, 1, (uint8_t *)(p->out), p->out_max);
+ if (ret <= 0) {
+ return;
+ }
+ p->in++;
+ p->in_max--;
+ p->out += ret;
+ p->out_max -= ret;
+ p->total += ret;
+
+ // Write separation character.
+ if (p->in_max > 0) {
+ dump_string(p, "-");
+ if (p->ret != 0) {
+ return;
+ }
+ }
+ }
+
+ p->ret = 0;
+}
+
+static void wire_rcode_to_str(rrset_dump_params_t *p)
+{
+ uint16_t data;
+ size_t in_len = sizeof(data);
+ const char *rcode_str = "NULL";
+
+ p->ret = -1;
+
+ // Check input size.
+ if (in_len > p->in_max) {
+ return;
+ }
+
+ // Fill in input data.
+ data = knot_wire_read_u16(p->in);
+
+ // Find RCODE name.
+ knot_lookup_table_t *rcode = knot_lookup_by_id(knot_rcode_names, data);
+ if (rcode != NULL) {
+ rcode_str = rcode->name;
+ }
+
+ // Dump RCODE name.
+ dump_string(p, rcode_str);
+ if (p->ret != 0) {
+ return;
+ }
+
+ // Fill in output.
+ p->in += in_len;
+ p->in_max -= in_len;
+ p->ret = 0;
+}
+
+static void wire_unknown_to_str(rrset_dump_params_t *p)
+{
+ int ret;
+ size_t in_len = p->in_max;
+ size_t out_len = 0;
+
+ p->ret = -1;
+
+ // Write unknown length header.
+ if (in_len > 0) {
+ ret = snprintf(p->out, p->out_max, "\\# %zu ", in_len);
+ } else {
+ ret = snprintf(p->out, p->out_max, "\\# 0");
+ }
+ if (ret <= 0 || (size_t)ret >= p->out_max) {
+ return;
+ }
+ out_len = ret;
+
+ // Fill in output.
+ p->out += out_len;
+ p->out_max -= out_len;
+ p->total += out_len;
+
+ // Write hex data if any.
+ if (in_len > 0) {
+ // If wrap mode wrap line.
+ if (p->style->wrap) {
+ dump_string(p, BLOCK_INDENT);
+ if (p->ret != 0) {
+ return;
+ }
+ }
+
+ wire_data_encode_to_str(p, &hex_encode, &hex_encode_alloc);
+ if (p->ret != 0) {
+ return;
+ }
+ }
+
+ p->ret = 0;
+}
+
+#define DUMP_PARAMS const uint8_t *in, const size_t in_len, char *out, \
+ const size_t out_max, const knot_dump_style_t *style
+#define DUMP_INIT rrset_dump_params_t p = { .style = style, .in = in, \
+ .in_max = in_len, .out = out, .out_max = out_max };
+#define DUMP_END return (p.in_max == 0 ? (int)p.total : KNOT_EPARSEFAIL);
+
+#define CHECK_RET(p) if (p.ret != 0) return -1;
+
+#define WRAP_INIT dump_string(&p, "(" BLOCK_INDENT); CHECK_RET(p);
+#define WRAP_END dump_string(&p, BLOCK_INDENT ")"); CHECK_RET(p);
+#define WRAP_LINE dump_string(&p, BLOCK_INDENT); CHECK_RET(p);
+
+#define COMMENT(s) if (p.style->verbose) { dump_string(&p, "\t; " s); \
+ CHECK_RET(p); }
+
+#define DUMP_SPACE dump_string(&p, " "); CHECK_RET(p);
+#define DUMP_NUM8 wire_num8_to_str(&p); CHECK_RET(p);
+#define DUMP_NUM16 wire_num16_to_str(&p); CHECK_RET(p);
+#define DUMP_NUM32 wire_num32_to_str(&p); CHECK_RET(p);
+#define DUMP_NUM48 wire_num48_to_str(&p); CHECK_RET(p);
+#define DUMP_DNAME ptr_dname_to_str(&p); CHECK_RET(p);
+#define DUMP_TIME wire_ttl_to_str(&p); CHECK_RET(p);
+#define DUMP_TIMESTAMP wire_timestamp_to_str(&p); CHECK_RET(p);
+#define DUMP_IPV4 wire_ipv4_to_str(&p); CHECK_RET(p);
+#define DUMP_IPV6 wire_ipv6_to_str(&p); CHECK_RET(p);
+#define DUMP_TYPE wire_type_to_str(&p); CHECK_RET(p);
+#define DUMP_HEX wire_data_encode_to_str(&p, &hex_encode, \
+ &hex_encode_alloc); CHECK_RET(p);
+#define DUMP_BASE64 wire_data_encode_to_str(&p, &base64_encode, \
+ &base64_encode_alloc); CHECK_RET(p);
+#define DUMP_HASH wire_len_data_encode_to_str(&p, &base32hex_encode, \
+ 1, false, ""); CHECK_RET(p);
+#define DUMP_SALT wire_len_data_encode_to_str(&p, &hex_encode, \
+ 1, false, "-"); CHECK_RET(p);
+#define DUMP_TSIG_DGST wire_len_data_encode_to_str(&p, &base64_encode, \
+ 2, true, ""); CHECK_RET(p);
+#define DUMP_TSIG_DATA wire_len_data_encode_to_str(&p, &hex_encode, \
+ 2, true, ""); CHECK_RET(p);
+#define DUMP_TEXT wire_text_to_str(&p); CHECK_RET(p);
+#define DUMP_BITMAP wire_bitmap_to_str(&p); CHECK_RET(p);
+#define DUMP_APL wire_apl_to_str(&p); CHECK_RET(p);
+#define DUMP_LOC wire_loc_to_str(&p); CHECK_RET(p);
+#define DUMP_GATEWAY wire_gateway_to_str(&p); CHECK_RET(p);
+#define DUMP_L64 wire_l64_to_str(&p); CHECK_RET(p);
+#define DUMP_EUI wire_eui_to_str(&p); CHECK_RET(p);
+#define DUMP_RCODE wire_rcode_to_str(&p); CHECK_RET(p);
+#define DUMP_UNKNOWN wire_unknown_to_str(&p); CHECK_RET(p);
+
+static int dump_a(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_IPV4;
+
+ DUMP_END;
+}
+
+static int dump_ns(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_DNAME;
+
+ DUMP_END;
+}
+
+static int dump_soa(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_DNAME; DUMP_SPACE; WRAP_INIT;
+ DUMP_NUM32; COMMENT("serial"); WRAP_LINE;
+ DUMP_TIME; COMMENT("refresh"); WRAP_LINE;
+ DUMP_TIME; COMMENT("retry"); WRAP_LINE;
+ DUMP_TIME; COMMENT("expire"); WRAP_LINE;
+ DUMP_TIME; COMMENT("minimum"); WRAP_END;
+ } else {
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_NUM32; DUMP_SPACE;
+ DUMP_TIME; DUMP_SPACE;
+ DUMP_TIME; DUMP_SPACE;
+ DUMP_TIME; DUMP_SPACE;
+ DUMP_TIME;
+ }
+
+ DUMP_END;
+}
+
+static int dump_hinfo(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_TEXT; DUMP_SPACE;
+ DUMP_TEXT;
+
+ DUMP_END;
+}
+
+static int dump_minfo(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_DNAME;
+
+ DUMP_END;
+}
+
+static int dump_mx(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_DNAME;
+
+ DUMP_END;
+}
+
+static int dump_txt(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ // First text string.
+ DUMP_TEXT;
+
+ // Other text strings if any.
+ while (p.in_max > 0) {
+ DUMP_SPACE; DUMP_TEXT;
+ }
+
+ DUMP_END;
+}
+
+static int dump_dnskey(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE; WRAP_INIT;
+ DUMP_BASE64;
+ WRAP_END;
+ } else {
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_BASE64;
+ }
+
+ DUMP_END;
+}
+
+static int dump_aaaa(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_IPV6;
+
+ DUMP_END;
+}
+
+static int dump_loc(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_LOC;
+
+ DUMP_END;
+}
+
+static int dump_srv(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_DNAME;
+
+ DUMP_END;
+}
+
+static int dump_naptr(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_TEXT; DUMP_SPACE;
+ DUMP_TEXT; DUMP_SPACE;
+ DUMP_TEXT; DUMP_SPACE;
+ DUMP_DNAME;
+
+ DUMP_END;
+}
+
+static int dump_cert(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE; WRAP_INIT;
+ DUMP_BASE64;
+ WRAP_END;
+ } else {
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_BASE64;
+ }
+
+ DUMP_END;
+}
+
+static int dump_apl(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ // Print list of APLs (empty list is allowed).
+ while (p.in_max > 0) {
+ if (p.total > 0) {
+ DUMP_SPACE;
+ }
+ DUMP_APL;
+ }
+
+ DUMP_END;
+}
+
+static int dump_ds(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE; WRAP_INIT;
+ DUMP_HEX;
+ WRAP_END;
+ } else {
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_HEX;
+ }
+
+ DUMP_END;
+}
+
+static int dump_sshfp(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE; WRAP_INIT;
+ DUMP_HEX;
+ WRAP_END;
+ } else {
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_HEX;
+ }
+
+ DUMP_END;
+}
+
+static int dump_ipseckey(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_NUM8; DUMP_SPACE; WRAP_INIT;
+ DUMP_GATEWAY;
+ WRAP_END;
+ } else {
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_GATEWAY;
+ }
+
+ DUMP_END;
+}
+
+static int dump_rrsig(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_TYPE; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM32; DUMP_SPACE;
+ DUMP_TIMESTAMP; DUMP_SPACE; WRAP_INIT;
+ DUMP_TIMESTAMP; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_DNAME; WRAP_LINE;
+ DUMP_BASE64;
+ WRAP_END;
+ } else {
+ DUMP_TYPE; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM32; DUMP_SPACE;
+ DUMP_TIMESTAMP; DUMP_SPACE;
+ DUMP_TIMESTAMP; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_BASE64;
+ }
+
+ DUMP_END;
+}
+
+static int dump_nsec(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_BITMAP;
+
+ DUMP_END;
+}
+
+static int dump_dhcid(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ WRAP_INIT;
+ DUMP_BASE64;
+ WRAP_END;
+ } else {
+ DUMP_BASE64;
+ }
+
+ DUMP_END;
+}
+
+static int dump_nsec3(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_SALT; DUMP_SPACE; WRAP_INIT;
+ DUMP_HASH; DUMP_SPACE; WRAP_LINE;
+ DUMP_BITMAP;
+ WRAP_END;
+ } else {
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_SALT; DUMP_SPACE;
+ DUMP_HASH; DUMP_SPACE;
+ DUMP_BITMAP;
+ }
+
+ DUMP_END;
+}
+
+static int dump_nsec3param(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_SALT;
+
+ DUMP_END;
+}
+
+static int dump_tlsa(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE; WRAP_INIT;
+ DUMP_HEX;
+ WRAP_END;
+ } else {
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_NUM8; DUMP_SPACE;
+ DUMP_HEX;
+ }
+
+ DUMP_END;
+}
+
+static int dump_l64(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_L64;
+
+ DUMP_END;
+}
+
+static int dump_l32(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_IPV4;
+
+ DUMP_END;
+}
+
+static int dump_eui(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ DUMP_EUI;
+
+ DUMP_END;
+}
+
+static int dump_tsig(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_NUM48; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE; WRAP_INIT;
+ DUMP_TSIG_DGST; DUMP_SPACE; WRAP_LINE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_RCODE; DUMP_SPACE;
+ DUMP_TSIG_DATA;
+ WRAP_END;
+ } else {
+ DUMP_DNAME; DUMP_SPACE;
+ DUMP_NUM48; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_TSIG_DGST; DUMP_SPACE;
+ DUMP_NUM16; DUMP_SPACE;
+ DUMP_RCODE; DUMP_SPACE;
+ DUMP_TSIG_DATA;
+ }
+
+ DUMP_END;
+}
+
+static int dump_unknown(DUMP_PARAMS)
+{
+ DUMP_INIT;
+
+ if (p.style->wrap) {
+ WRAP_INIT;
+ DUMP_UNKNOWN;
+ WRAP_END;
+ } else {
+ DUMP_UNKNOWN;
+ }
+
+ DUMP_END;
+}
+
+int knot_rrset_txt_dump_data(const knot_rrset_t *rrset,
+ const size_t pos,
+ char *dst,
+ const size_t maxlen,
+ const knot_dump_style_t *style)
+{
+ if (rrset == NULL || dst == NULL || style == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ uint8_t *data = knot_rrset_get_rdata(rrset, pos);
+ size_t data_len = rrset_rdata_item_size(rrset, pos);
+
+ int ret = 0;
+
+ switch (knot_rrset_type(rrset)) {
+ case KNOT_RRTYPE_A:
+ ret = dump_a(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_NS:
+ case KNOT_RRTYPE_CNAME:
+ case KNOT_RRTYPE_PTR:
+ case KNOT_RRTYPE_DNAME:
+ ret = dump_ns(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_SOA:
+ ret = dump_soa(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_HINFO:
+ ret = dump_hinfo(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_MINFO:
+ case KNOT_RRTYPE_RP:
+ ret = dump_minfo(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_MX:
+ case KNOT_RRTYPE_AFSDB:
+ case KNOT_RRTYPE_RT:
+ case KNOT_RRTYPE_KX:
+ case KNOT_RRTYPE_LP:
+ ret = dump_mx(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_TXT:
+ case KNOT_RRTYPE_SPF:
+ ret = dump_txt(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_KEY:
+ case KNOT_RRTYPE_DNSKEY:
+ ret = dump_dnskey(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_AAAA:
+ ret = dump_aaaa(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_LOC:
+ ret = dump_loc(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_SRV:
+ ret = dump_srv(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_NAPTR:
+ ret = dump_naptr(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_CERT:
+ ret = dump_cert(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_APL:
+ ret = dump_apl(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_DS:
+ ret = dump_ds(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_SSHFP:
+ ret = dump_sshfp(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_IPSECKEY:
+ ret = dump_ipseckey(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_RRSIG:
+ ret = dump_rrsig(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_NSEC:
+ ret = dump_nsec(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_DHCID:
+ ret = dump_dhcid(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_NSEC3:
+ ret = dump_nsec3(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_NSEC3PARAM:
+ ret = dump_nsec3param(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_TLSA:
+ ret = dump_tlsa(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_NID:
+ case KNOT_RRTYPE_L64:
+ ret = dump_l64(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_L32:
+ ret = dump_l32(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_EUI48:
+ case KNOT_RRTYPE_EUI64:
+ ret = dump_eui(data, data_len, dst, maxlen, style);
+ break;
+ case KNOT_RRTYPE_TSIG:
+ ret = dump_tsig(data, data_len, dst, maxlen, style);
+ break;
+ default:
+ ret = dump_unknown(data, data_len, dst, maxlen, style);
+ break;
+ }
+
+ return ret;
+}
+
+int knot_rrset_txt_dump_header(const knot_rrset_t *rrset,
+ const size_t pos,
+ char *dst,
+ const size_t maxlen,
+ const knot_dump_style_t *style)
+{
+ if (rrset == NULL || dst == NULL || style == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ size_t len = 0;
+ char buf[32];
+ int ret;
+
+ // Dump rrset owner.
+ char *name = knot_dname_to_str(rrset->owner);
+ // If reduced style don't print non-first headers in rrset or rrsigs.
+ if (style->reduce && (pos > 0 || rrset->type == KNOT_RRTYPE_RRSIG)) {
+ // Fill buffer with tabs.
+ memset(buf, '\t', sizeof(buf));
+ // Compute leading number of tabs.
+ size_t tabs = (strlen(name) + TAB_WIDTH - 1) / TAB_WIDTH;
+ // Check number of tabs.
+ tabs = tabs < sizeof(buf) ? tabs : (sizeof(buf) - 1);
+ // Terminate tabs string.
+ buf[tabs] = '\0';
+
+ ret = snprintf(dst + len, maxlen - len, "%s", buf);
+ } else {
+ // Get rrset owner.
+ if (style->reduce) {
+ // If reduced style don't print extra spaces.
+ ret = snprintf(dst + len, maxlen - len, "%s\t", name);
+ } else {
+ // Set white space separation character.
+ char sep = strlen(name) < 4 * TAB_WIDTH ? '\t' : ' ';
+
+ ret = snprintf(dst + len, maxlen - len, "%-20s%c",
+ name, sep);
+ }
+ }
+ free(name);
+ if (ret < 0 || (size_t)ret >= maxlen - len) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+
+ // Set white space separation character.
+ char sep = style->wrap ? ' ' : '\t';
+
+ // Dump rrset ttl.
+ if (style->show_ttl) {
+ if (style->human_ttl) {
+ // Create human readable ttl string.
+ ret = time_to_human_str(buf, sizeof(buf), rrset->ttl);
+ if (ret < 0) {
+ return KNOT_ESPACE;
+ }
+ ret = snprintf(dst + len, maxlen - len, "%s%c",
+ buf, sep);
+ } else {
+ ret = snprintf(dst + len, maxlen - len, "%u%c",
+ rrset->ttl, sep);
+ }
+ if (ret < 0 || (size_t)ret >= maxlen - len) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+ }
+
+ // Dump rrset class.
+ if (style->show_class) {
+ if (knot_rrclass_to_string(rrset->rclass, buf, sizeof(buf)) < 0)
+ {
+ return KNOT_ESPACE;
+ }
+ ret = snprintf(dst + len, maxlen - len, "%-2s%c", buf, sep);
+ if (ret < 0 || (size_t)ret >= maxlen - len) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+ }
+
+ // Dump rrset type.
+ if (knot_rrtype_to_string(rrset->type, buf, sizeof(buf)) < 0) {
+ return KNOT_ESPACE;
+ }
+ ret = snprintf(dst + len, maxlen - len, "%s%c", buf, sep);
+ if (ret < 0 || (size_t)ret >= maxlen - len) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+
+ return len;
+}
+
+int knot_rrset_txt_dump(const knot_rrset_t *rrset,
+ char *dst,
+ const size_t maxlen,
+ const knot_dump_style_t *style)
+{
+ if (rrset == NULL || dst == NULL || style == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ size_t len = 0;
+ int ret;
+
+ // If the rrset is empty, dump header only.
+ if (rrset->rdata_count == 0) {
+ // Dump rdata owner, class, ttl and type.
+ ret = knot_rrset_txt_dump_header(rrset, 0, dst + len,
+ maxlen - len, style);
+ if (ret < 0) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+
+ // Terminate line.
+ if (len >= maxlen) {
+ return KNOT_ESPACE;
+ }
+ dst[len++] = '\n';
+ dst[len] = '\0';
+ }
+
+ // Loop over rdata in rrset.
+ for (size_t i = 0; i < rrset->rdata_count; i++) {
+ // Dump rdata owner, class, ttl and type.
+ ret = knot_rrset_txt_dump_header(rrset, i, dst + len,
+ maxlen - len, style);
+ if (ret < 0) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+
+ // Dump rdata as such.
+ ret = knot_rrset_txt_dump_data(rrset, i, dst + len,
+ maxlen - len, style);
+ if (ret < 0) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+
+ // Terminate line.
+ if (len >= maxlen) {
+ return KNOT_ESPACE;
+ }
+ dst[len++] = '\n';
+ dst[len] = '\0';
+ }
+
+ // Dump RRSIG records if any via recursion call.
+ if (rrset->rrsigs != NULL) {
+ ret = knot_rrset_txt_dump(rrset->rrsigs, dst + len,
+ maxlen - len, style);
+ if (ret < 0) {
+ return KNOT_ESPACE;
+ }
+ len += ret;
+ }
+
+ return len;
+}
diff --git a/src/libknot/rrset-dump.h b/src/libknot/rrset-dump.h
new file mode 100644
index 0000000..ece39e8
--- /dev/null
+++ b/src/libknot/rrset-dump.h
@@ -0,0 +1,109 @@
+/* Copyright (C) 2011 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 rrset-dump.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief RRset text dump facility.
+ *
+ * \addtogroup libknot
+ * @{
+ */
+
+#ifndef _KNOT_RRSETDUMP_H_
+#define _KNOT_RRSETDUMP_H_
+
+#include <stdbool.h> // bool
+
+#include "libknot/rrset.h"
+
+/*! \brief Text output settings. */
+typedef struct {
+ /*!< Wrap long records. */
+ bool wrap;
+ /*!< Show class. */
+ bool show_class;
+ /*!< Show ttl. */
+ bool show_ttl;
+ /*!< Print extra information. */
+ bool verbose;
+ /*!< Don't print header for non-first rrset records. */
+ bool reduce;
+ /*!< Format TTL as DHMS. */
+ bool human_ttl;
+ /*!< Format timestamp as YYYYMMDDHHmmSS. */
+ bool human_tmstamp;
+} knot_dump_style_t;
+
+/*! \brief Default dump style. */
+extern const knot_dump_style_t KNOT_DUMP_STYLE_DEFAULT;
+
+/*!
+ * \brief Dumps rrset header.
+ *
+ * \param rrset RRset to dump.
+ * \param pos Position of the record to dump.
+ * \param dst Output buffer.
+ * \param maxlen Otuput buffer size.
+ * \param style Output style.
+ *
+ * \retval output length if success.
+ * \retval < 0 if error.
+ */
+int knot_rrset_txt_dump_header(const knot_rrset_t *rrset,
+ const size_t pos,
+ char *dst,
+ const size_t maxlen,
+ const knot_dump_style_t *style);
+
+/*!
+ * \brief Dumps rrset data.
+ *
+ * \param rrset RRset to dump.
+ * \param pos Position of the record to dump.
+ * \param dst Output buffer.
+ * \param maxlen Otuput buffer size.
+ * \param style Output style.
+ *
+ * \retval output length if success.
+ * \retval < 0 if error.
+ */
+int knot_rrset_txt_dump_data(const knot_rrset_t *rrset,
+ const size_t pos,
+ char *dst,
+ const size_t maxlen,
+ const knot_dump_style_t *style);
+
+/*!
+ * \brief Dumps rrset.
+ *
+ * \param rrset RRset to dump.
+ * \param dst Output buffer.
+ * \param maxlen Otuput buffer size.
+ * \param style Output style.
+ *
+ * \retval output length if success.
+ * \retval < 0 if error.
+ */
+int knot_rrset_txt_dump(const knot_rrset_t *rrset,
+ char *dst,
+ const size_t maxlen,
+ const knot_dump_style_t *style);
+
+#endif // _KNOT_RRSETDUMP_H_
+
+/*! @} */
diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index f5a9f5f..24ddb88 100644
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -19,59 +19,821 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
+#include <inttypes.h>
+#include "consts.h"
#include "common.h"
+#include "common/mempattern.h"
#include "rrset.h"
-#include "util/descriptor.h"
+#include "common/descriptor.h"
#include "util/debug.h"
#include "util/utils.h"
+#include "packet/response.h"
+#include "util/wire.h"
/*----------------------------------------------------------------------------*/
/* Non-API functions */
/*----------------------------------------------------------------------------*/
-static void knot_rrset_disconnect_rdata(knot_rrset_t *rrset,
- knot_rdata_t *prev, knot_rdata_t *rdata)
+static int rrset_retain_dnames_in_rr(knot_dname_t **dname, void *data)
{
- if (prev == NULL) {
- // find the previous RDATA in the series, as its pointer must
- // be changed
- prev = rdata->next;
- while (prev->next != rdata) {
- prev = prev->next;
+ UNUSED(data);
+ if (dname == NULL || *dname == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ knot_dname_retain(*dname);
+ return KNOT_EOK;
+}
+
+static int rrset_release_dnames_in_rr(knot_dname_t **dname, void *data)
+{
+ UNUSED(data);
+ if (dname == NULL || *dname == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ knot_dname_release(*dname);
+ return KNOT_EOK;
+}
+
+static uint32_t rrset_rdata_offset(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || rrset->rdata_indices == NULL ||
+ pos >= rrset->rdata_count || pos == 0) {
+ return 0;
+ }
+
+ assert(rrset->rdata_count >= 2);
+ return rrset->rdata_indices[pos - 1];
+}
+
+static uint8_t *rrset_rdata_pointer(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || rrset->rdata == NULL
+ || pos >= rrset->rdata_count) {
+ return NULL;
+ }
+
+ return rrset->rdata + rrset_rdata_offset(rrset, pos);
+}
+
+static uint16_t rrset_rdata_naptr_bin_chunk_size(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ size_t size = 0;
+ uint8_t *rdata = rrset_rdata_pointer(rrset, pos);
+ assert(rdata);
+
+ /* Two shorts at the beginning. */
+ size += 4;
+ /* 3 binary TXTs with length in the first byte. */
+ for (int i = 0; i < 3; i++) {
+ size += *(rdata + size) + 1;
+ }
+
+ /*
+ * Dname remaning, but we usually want to get to the DNAME, so
+ * there's no need to include it in the returned size.
+ */
+
+ return size;
+}
+
+void knot_rrset_rdata_dump(const knot_rrset_t *rrset, size_t rdata_pos)
+{
+dbg_rrset_exec_detail(
+ dbg_rrset_detail(" ------- RDATA pos=%zu -------\n", rdata_pos);
+ if (rrset->rdata_count == 0) {
+ dbg_rrset_detail(" There are no rdata in this RRset!\n");
+ dbg_rrset_detail(" ------- RDATA -------\n");
+ return;
+ }
+ const rdata_descriptor_t *desc =
+ get_rdata_descriptor(knot_rrset_type(rrset));
+
+ size_t offset = 0;
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ int item = desc->block_types[i];
+ const uint8_t *rdata = rrset_rdata_pointer(rrset, rdata_pos);
+ if (descriptor_item_is_dname(item)) {
+ knot_dname_t *dname;
+ memcpy(&dname, rdata + offset, sizeof(knot_dname_t *));
+ char *name = knot_dname_to_str(dname);
+ if (dname == NULL) {
+ dbg_rrset_detail("DNAME error.\n");
+ return;
+ }
+ dbg_rrset_detail("block=%d: (%p) DNAME=%s\n",
+ i, dname, name);
+ free(name);
+ offset += sizeof(knot_dname_t *);
+ } else if (descriptor_item_is_fixed(item)) {
+ dbg_rrset_detail("block=%d Raw data (size=%d):\n",
+ i, item);
+ dbg_rrset_hex_detail((char *)(rdata + offset), item);
+ offset += item;
+ } else if (descriptor_item_is_remainder(item)) {
+ dbg_rrset_detail("block=%d Remainder (size=%zu):\n",
+ i, rrset_rdata_item_size(rrset,
+ rdata_pos) - offset);
+ dbg_rrset_hex_detail((char *)(rdata + offset),
+ rrset_rdata_item_size(rrset,
+ rdata_pos) - offset);
+ } else {
+ assert(rrset->type == KNOT_RRTYPE_NAPTR);
+ uint16_t naptr_chunk_size =
+ rrset_rdata_naptr_bin_chunk_size(rrset, rdata_pos);
+ dbg_rrset_detail("NAPTR, REGEXP block (size=%u):\n",
+ naptr_chunk_size);
+ dbg_rrset_hex_detail((char *)(rdata + offset), naptr_chunk_size);
+ offset += naptr_chunk_size;
}
}
+);
+}
- assert(prev);
- assert(prev->next == rdata);
+static size_t rrset_rdata_remainder_size(const knot_rrset_t *rrset,
+ size_t offset, size_t pos)
+{
+ assert(rrset_rdata_item_size(rrset, pos) != 0);
- prev->next = rdata->next;
+ size_t ret = rrset_rdata_item_size(rrset, pos) - offset;
+ assert(ret <= rrset_rdata_size_total(rrset));
+ return ret;
+}
- if (rrset->rdata == rdata) {
- if (rdata->next == rdata) {
- rrset->rdata = NULL;
+/* [code-review] Please document at least parameters & return values. */
+static int rrset_rdata_compare_one(const knot_rrset_t *rrset1,
+ const knot_rrset_t *rrset2,
+ size_t pos1, size_t pos2)
+{
+ /* [code-review] Just to be sure. */
+ assert(rrset1 != NULL);
+ assert(rrset2 != NULL);
+
+ uint8_t *r1 = rrset_rdata_pointer(rrset1, pos1);
+ uint8_t *r2 = rrset_rdata_pointer(rrset2, pos2);
+ assert(rrset1->type == rrset2->type);
+ const rdata_descriptor_t *desc = get_rdata_descriptor(rrset1->type);
+ int cmp = 0;
+ size_t offset = 0;
+
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ if (descriptor_item_is_dname(desc->block_types[i])) {
+ knot_dname_t *dname1 = NULL;
+ memcpy(&dname1, r1 + offset, sizeof(knot_dname_t *));
+ knot_dname_t *dname2 = NULL;
+ memcpy(&dname2, r2 + offset, sizeof(knot_dname_t *));
+ cmp = knot_dname_compare(dname1, dname2);
+ offset += sizeof(knot_dname_t *);
+ } else if (descriptor_item_is_fixed(desc->block_types[i])) {
+ cmp = memcmp(r1 + offset, r2 + offset,
+ desc->block_types[i]);
+ offset += desc->block_types[i];
+ } else if (descriptor_item_is_remainder(desc->block_types[i])) {
+ size_t size1 = rrset_rdata_remainder_size(rrset1, offset,
+ pos1);
+ size_t size2 = rrset_rdata_remainder_size(rrset2, offset,
+ pos2);
+ cmp = memcmp(r1 + offset, r2 + offset,
+ size1 <= size2 ? size1 : size2);
+ if (cmp == 0 && size1 != size2) {
+ cmp = size1 < size2 ? -1 : 1;
+ }
+ /* No need to move offset, this should be end anyway. */
+ assert(desc->block_types[i + 1] == KNOT_RDATA_WF_END);
} else {
- rrset->rdata = rdata->next;
+ assert(rrset1->type == KNOT_RRTYPE_NAPTR);
+ uint16_t naptr_chunk_size1 =
+ rrset_rdata_naptr_bin_chunk_size(rrset1, pos1);
+ uint16_t naptr_chunk_size2 =
+ rrset_rdata_naptr_bin_chunk_size(rrset2, pos2);
+ cmp = memcmp(r1, r2,
+ naptr_chunk_size1 <= naptr_chunk_size2 ?
+ naptr_chunk_size1 : naptr_chunk_size2);
+ if (cmp == 0 && naptr_chunk_size1 == naptr_chunk_size2) {
+ cmp = naptr_chunk_size1 < naptr_chunk_size2 ? -1 : 1;
+ }
+
+ /*
+ * It does not matter which one we assign. If the
+ * offsets were different, then cmp != 0, if yes,
+ * NAPTR DNAME will be on correct offset.
+ */
+ offset += naptr_chunk_size1;
+ }
+
+ if (cmp != 0) {
+ return cmp;
}
}
- rdata->next = NULL;
+ assert(cmp == 0);
+ return 0;
+}
+
+static int knot_rrset_header_to_wire(const knot_rrset_t *rrset,
+ uint8_t **pos, size_t max_size,
+ knot_compr_t *compr, size_t *size)
+{
+ // Common size of items: type, class and ttl.
+ const size_t type_cls_ttl_len = 2 * sizeof(uint16_t) + sizeof(uint32_t);
+ // Rdata length item size.
+ const size_t rrlen_len = sizeof(uint16_t);
+
+ if (rrset->owner == NULL) {
+ return KNOT_EMALF;
+ }
+
+ const uint8_t *owner;
+ uint8_t owner_len;
+
+ // Use compressed owner.
+ if (compr) {
+ owner = compr->owner.wire + compr->owner.pos;
+ owner_len = compr->owner.size;
+ // Use rrset owner.
+ } else {
+ owner = knot_dname_name(rrset->owner);
+ owner_len = knot_dname_size(rrset->owner);
+ }
+
+ dbg_response("Max size: %zu, compressed owner: %s, owner size: %u\n",
+ max_size, compr ? "yes" : "no", owner_len);
+
+ // Check wire space for header.
+ if (*size + owner_len + type_cls_ttl_len + rrlen_len > max_size) {
+ dbg_rrset_detail("Header does not fit into wire.\n");
+ return KNOT_ESPACE;
+ }
+
+ // Write owner, type, class and ttl to wire.
+ memcpy(*pos, owner, owner_len);
+ *pos += owner_len;
+
+ dbg_rrset_detail(" Type: %u\n", rrset->type);
+ knot_wire_write_u16(*pos, rrset->type);
+ *pos += sizeof(uint16_t);
+
+ dbg_rrset_detail(" Class: %u\n", rrset->rclass);
+ knot_wire_write_u16(*pos, rrset->rclass);
+ *pos += sizeof(uint16_t);
+
+ dbg_rrset_detail(" TTL: %u\n", rrset->ttl);
+ knot_wire_write_u32(*pos, rrset->ttl);
+ *pos += sizeof(uint32_t);
+
+ *size += owner_len + type_cls_ttl_len;
+
+ return KNOT_EOK;
+}
+
+/* [code-review] Split to more functions, this one's too long. */
+static int knot_rrset_rdata_to_wire_one(const knot_rrset_t *rrset,
+ size_t rdata_pos, uint8_t **pos,
+ size_t max_size, size_t *rr_size,
+ knot_compr_t *compr)
+{
+ assert(rrset);
+ assert(pos);
+
+ /* Put RR header to wire. */
+ size_t size = 0;
+ int ret = knot_rrset_header_to_wire(rrset, pos, max_size,
+ compr, &size);
+ if (ret != KNOT_EOK) {
+ dbg_response("Failed to convert RR header to wire (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+ // save space for RDLENGTH
+ uint8_t *rdlength_pos = *pos;
+ *pos += 2;
+ size += 2;
+
+ if (compr) {
+ compr->wire_pos += size;
+ }
+
+ /* Get pointer into RDATA array. */
+ uint8_t *rdata = rrset_rdata_pointer(rrset, rdata_pos);
+ assert(rdata);
+ /* Offset into one RDATA array. */
+ size_t offset = 0;
+ /* Actual RDLENGTH. */
+ uint16_t rdlength = 0;
+
+ const rdata_descriptor_t *desc = get_rdata_descriptor(rrset->type);
+
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ int item = desc->block_types[i];
+ if (compr && descriptor_item_is_compr_dname(item)) {
+ knot_dname_t *dname;
+ memcpy(&dname, rdata + offset, sizeof(knot_dname_t *));
+ assert(dname);
+ int ret = knot_response_compress_dname(dname,
+ compr, *pos,
+ max_size - size - rdlength);
+ if (ret < 0) {
+ return KNOT_ESPACE;
+ }
+ assert(ret + size + rdlength <= max_size);
+dbg_response_exec_detail(
+ char *name = knot_dname_to_str(dname);
+ dbg_response_detail("Compressed dname=%s size: %d\n",
+ name, ret);
+ free(name);
+);
+ *pos += ret;
+ rdlength += ret;
+ offset += sizeof(knot_dname_t *);
+ compr->wire_pos += ret;
+ } else if (descriptor_item_is_dname(item)) {
+ knot_dname_t *dname;
+ memcpy(&dname, rdata + offset, sizeof(knot_dname_t *));
+ assert(dname && dname->name);
+ if (size + rdlength + knot_dname_size(dname) > max_size) {
+ dbg_rrset("rr: to_wire: DNAME does not fit into RR.\n");
+ return KNOT_ESPACE;
+ }
+dbg_rrset_exec_detail(
+ char *name = knot_dname_to_str(dname);
+ dbg_rrset_detail("Saving this DNAME=%s\n", name);
+ free(name);
+);
+ // save whole domain name
+ memcpy(*pos, knot_dname_name(dname),
+ knot_dname_size(dname));
+ dbg_rrset_detail("Uncompressed dname size: %d\n",
+ knot_dname_size(dname));
+ *pos += knot_dname_size(dname);
+ rdlength += knot_dname_size(dname);
+ offset += sizeof(knot_dname_t *);
+ if (compr) {
+ compr->wire_pos += knot_dname_size(dname);
+ }
+ } else if (descriptor_item_is_fixed(item)) {
+ dbg_rrset_detail("Saving static chunk, size=%d\n",
+ item);
+ /* Fixed length chunk. */
+ if (size + rdlength + item > max_size) {
+ return KNOT_ESPACE;
+ }
+ memcpy(*pos, rdata + offset, item);
+ *pos += item;
+ rdlength += item;
+ offset += item;
+ if (compr) {
+ compr->wire_pos += item;
+ }
+ } else if (descriptor_item_is_remainder(item)) {
+ /* Check that the remainder fits to stream. */
+ size_t remainder_size =
+ rrset_rdata_remainder_size(rrset, offset,
+ rdata_pos);
+ dbg_rrset_detail("Saving remaining chunk, size=%zu, "
+ "size with remainder=%zu\n",
+ remainder_size,
+ size + rdlength + remainder_size);
+ if (size + rdlength + remainder_size > max_size) {
+ dbg_rrset("rr: to_wire: Remainder does not fit "
+ "to wire.\n");
+ return KNOT_ESPACE;
+ }
+ memcpy(*pos, rdata + offset, remainder_size);
+ *pos += remainder_size;
+ rdlength += remainder_size;
+ offset += remainder_size;
+ if (compr) {
+ compr->wire_pos += remainder_size;
+ }
+ } else {
+ assert(rrset->type == KNOT_RRTYPE_NAPTR);
+ /* Store the binary chunk. */
+ uint16_t chunk_size =
+ rrset_rdata_naptr_bin_chunk_size(rrset, rdata_pos);
+ if (size + rdlength + chunk_size > max_size) {
+ dbg_rrset("rr: to_wire: NAPTR chunk does not "
+ "fit to wire.\n");
+ return KNOT_ESPACE;
+ }
+ memcpy(*pos, rdata + offset, chunk_size);
+ *pos += chunk_size;
+ rdlength += chunk_size;
+ offset += chunk_size;
+ if (compr) {
+ compr->wire_pos += chunk_size;
+ }
+ }
+ }
+
+ knot_wire_write_u16(rdlength_pos, rdlength);
+ size += rdlength;
+
+ *rr_size = size;
+ assert(size <= max_size);
+ return KNOT_EOK;
+}
+
+static int knot_rrset_to_wire_aux(const knot_rrset_t *rrset, uint8_t **pos,
+ size_t max_size, compression_param_t *comp)
+{
+ uint8_t wf_owner[256];
+ size_t size = 0;
+
+ assert(rrset != NULL);
+ assert(rrset->owner != NULL);
+ assert(pos != NULL);
+ assert(*pos != NULL);
+
+ dbg_rrset_detail("Max size: %zu, owner: %p, owner size: %d\n",
+ max_size, rrset->owner, rrset->owner->size);
+
+ knot_compr_t compr_info;
+ if (comp) {
+ dbg_response_detail("Compressing RR owner: %s.\n",
+ rrset->owner->name);
+ compr_info.table = comp->compressed_dnames;
+ compr_info.wire = comp->wire;
+ compr_info.wire_pos = comp->wire_pos;
+ int ret = knot_response_compress_dname(rrset->owner, &compr_info,
+ wf_owner, max_size);
+ if (ret < 0) {
+ return KNOT_ESPACE;
+ }
+
+ compr_info.owner.pos = 0;
+ compr_info.owner.wire = wf_owner;
+ compr_info.owner.size = ret;
+
+ dbg_response_detail("Compressed owner has size=%d\n",
+ compr_info.owner.size);
+ }
+
+ dbg_rrset_detail("Max size: %zu, size: %zu\n", max_size, size);
+
+ // No RDATA, just save header and 0 RDLENGTH.
+ if (rrset->rdata_count == 0) {
+ size_t header_size = 0;
+ int ret = knot_rrset_header_to_wire(rrset, pos, max_size,
+ comp ? &compr_info : NULL,
+ &header_size);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ // Save zero rdata length.
+ knot_wire_write_u16(*pos, 0);
+ *pos += sizeof(uint16_t);
+ header_size += sizeof(uint16_t);
+
+ return header_size;
+ }
+
+ // Save rrset records.
+ for (uint16_t i = 0; i < rrset->rdata_count; ++i) {
+ dbg_rrset_detail("rrset: to_wire: Current max_size=%zu\n",
+ max_size);
+ size_t rr_size = 0;
+ int ret = knot_rrset_rdata_to_wire_one(rrset, i, pos, max_size,
+ &rr_size,
+ comp ? &compr_info : NULL);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rrset: to_wire: Cannot convert RR. "
+ "Reason: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ dbg_rrset_detail("Converted RR nr=%d, size=%zu\n", i, rr_size);
+ /* Change size of whole RRSet. */
+ size += rr_size;
+ /* Change max size. */
+ max_size -= rr_size;
+ }
+
+ dbg_rrset_detail("Max size: %zu, size: %zu\n", max_size, size);
+
+ return size;
+}
+
+static int knot_rrset_rdata_store_binary(uint8_t *rdata, size_t *offset,
+ size_t packet_offset,
+ const uint8_t *wire,
+ size_t *pos,
+ size_t rdlength,
+ size_t size)
+{
+ assert(rdata);
+ assert(wire);
+
+ /* Check that size is OK. */
+ if ((*pos - packet_offset) + size > rdlength) {
+ dbg_rrset("rrset: rdata_store_binary: Read of size=%zu on "
+ "position %zu exceeded RDLENGTH by %zu octets.\n", size,
+ *pos, ((*pos - packet_offset) + size) - rdlength);
+ return KNOT_ESPACE;
+ }
+
+ /* Store actual data. */
+ memcpy(rdata + *offset, wire + *pos, size);
+ *offset += size;
+ *pos += size;
+
+ return KNOT_EOK;
+}
+
+static int rrset_type_multiple_dnames(const knot_rrset_t *rrset)
+{
+ if (rrset->type == KNOT_RRTYPE_SOA || rrset->type == KNOT_RRTYPE_MINFO ||
+ rrset->type == KNOT_RRTYPE_RP) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int rrset_find_rr_pos_for_pointer(const knot_rrset_t *rrset,
+ knot_dname_t **p, size_t *pos)
+{
+ if (p == NULL) {
+ return 0;
+ }
+
+ /* [code-review] Added check of 'p' validity - whether it
+ * points to the RDATA array of 'rrset'.
+ */
+ if ((size_t)p < (size_t)rrset->rdata
+ || (size_t)p > (size_t)rrset->rdata
+ + rrset_rdata_size_total(rrset)) {
+ // 'p' is not within the RDATA array
+ return KNOT_ERANGE;
+ }
+
+ size_t offset = (size_t)p - (size_t)rrset->rdata;
+
+ if (offset < rrset_rdata_item_size(rrset, 0)) {
+ return 0;
+ }
+ for (uint16_t i = 0; i < rrset->rdata_count; ++i) {
+ if (rrset_rdata_offset(rrset, i) > offset) {
+ *pos = i - 1;
+ return KNOT_EOK;
+ } else if (rrset_rdata_offset(rrset, i) == offset) {
+ *pos = i;
+ return KNOT_EOK;
+ }
+ }
+ *pos = rrset->rdata_count - 1;
+ return KNOT_EOK;
+}
+
+static size_t rrset_binary_size_one(const knot_rrset_t *rrset,
+ size_t rdata_pos)
+{
+ const rdata_descriptor_t *desc =
+ get_rdata_descriptor(knot_rrset_type(rrset));
+
+ size_t offset = 0;
+ size_t size = 0;
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ int item = desc->block_types[i];
+ uint8_t *rdata = rrset_rdata_pointer(rrset, rdata_pos);
+ if (descriptor_item_is_dname(item)) {
+ knot_dname_t *dname;
+ memcpy(&dname, rdata + offset, sizeof(knot_dname_t *));
+ assert(dname);
+ offset += sizeof(knot_dname_t *);
+ size += knot_dname_size(dname) + 1; // extra 1 - we need a size
+ } else if (descriptor_item_is_fixed(item)) {
+ offset += item;
+ size += item;
+ } else if (descriptor_item_is_remainder(item)) {
+ size += rrset_rdata_item_size(rrset, rdata_pos) -
+ offset;
+ } else {
+ assert(rrset->type == KNOT_RRTYPE_NAPTR);
+ uint16_t naptr_chunk_size =
+ rrset_rdata_naptr_bin_chunk_size(rrset, rdata_pos);
+ /*
+ * Regular expressions in NAPTR are TXT's, so they
+ * can be upto 64k long.
+ */
+ size += naptr_chunk_size + 2;
+ offset += naptr_chunk_size;
+ }
+ }
+
+ return size;
+}
+
+static void rrset_serialize_rr(const knot_rrset_t *rrset, size_t rdata_pos,
+ uint8_t *stream, size_t *size)
+{
+ const rdata_descriptor_t *desc =
+ get_rdata_descriptor(knot_rrset_type(rrset));
+
+ size_t offset = 0;
+ *size = 0;
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ int item = desc->block_types[i];
+ uint8_t *rdata = rrset_rdata_pointer(rrset, rdata_pos);
+ if (descriptor_item_is_dname(item)) {
+ knot_dname_t *dname;
+ memcpy(&dname, rdata + offset, sizeof(knot_dname_t *));
+ assert(dname);
+ memcpy(stream + *size, &dname->size, 1);
+ *size += 1;
+ memcpy(stream + *size, dname->name, dname->size);
+ offset += sizeof(knot_dname_t *);
+ *size += dname->size;
+ } else if (descriptor_item_is_fixed(item)) {
+ memcpy(stream + *size, rdata + offset, item);
+ offset += item;
+ *size += item;
+ } else if (descriptor_item_is_remainder(item)) {
+ uint16_t remainder_size =
+ rrset_rdata_item_size(rrset,
+ rdata_pos) - offset;
+ memcpy(stream + *size, rdata + offset, remainder_size);
+ *size += remainder_size;
+ } else {
+ assert(rrset->type == KNOT_RRTYPE_NAPTR);
+ /* Copy static chunk. */
+ uint16_t naptr_chunk_size =
+ rrset_rdata_naptr_bin_chunk_size(rrset, rdata_pos);
+ /* We need a length. */
+ memcpy(stream + *size, &naptr_chunk_size,
+ sizeof(uint16_t));
+ *size += sizeof(uint16_t);
+ /* Write data. */
+ memcpy(stream + *size, rdata + offset, naptr_chunk_size);
+ }
+ }
+
+ dbg_rrset_detail("RR nr=%zu serialized, size=%zu\n", rdata_pos, *size);
+}
+
+static int rrset_deserialize_rr(knot_rrset_t *rrset, size_t rdata_pos,
+ uint8_t *stream, uint32_t rdata_size,
+ size_t *read)
+{
+ const rdata_descriptor_t *desc =
+ get_rdata_descriptor(knot_rrset_type(rrset));
+
+ size_t stream_offset = 0;
+ size_t rdata_offset = 0;
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; i++) {
+ int item = desc->block_types[i];
+ uint8_t *rdata = rrset_rdata_pointer(rrset, rdata_pos);
+ if (descriptor_item_is_dname(item)) {
+ /* Read dname size. */
+ uint8_t dname_size = 0;
+ memcpy(&dname_size, stream + stream_offset, 1);
+ stream_offset += 1;
+ knot_dname_t *dname =
+ knot_dname_new_from_wire(stream + stream_offset,
+ dname_size, NULL);
+ if (dname == NULL) {
+ return KNOT_ERROR;
+ }
+ assert(dname->size == dname_size);
+ memcpy(rdata + rdata_offset, &dname,
+ sizeof(knot_dname_t *));
+ stream_offset += dname_size;
+ rdata_offset += sizeof(knot_dname_t *);
+ } else if (descriptor_item_is_fixed(item)) {
+ memcpy(rdata + rdata_offset, stream + stream_offset, item);
+ rdata_offset += item;
+ stream_offset += item;
+ } else if (descriptor_item_is_remainder(item)) {
+ size_t remainder_size = rdata_size - stream_offset;
+ memcpy(rdata + rdata_offset, stream + stream_offset,
+ remainder_size);
+ stream_offset += remainder_size;
+ } else {
+ assert(rrset->type == KNOT_RRTYPE_NAPTR);
+ /* Read size. */
+ uint16_t naptr_chunk_size;
+ memcpy(&naptr_chunk_size, stream + stream_offset,
+ sizeof(uint16_t));
+ stream_offset += sizeof(uint16_t);
+ memcpy(rdata + rdata_offset, stream + stream_offset,
+ naptr_chunk_size);
+ stream_offset += naptr_chunk_size;
+ rdata_offset += rdata_offset;
+ }
+ }
+ *read = stream_offset;
+ return KNOT_EOK;
+}
+
+int knot_rrset_remove_rdata_pos(knot_rrset_t *rrset, size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return KNOT_EINVAL;
+ }
+
+ /* Handle DNAMEs inside RDATA. */
+ int ret = rrset_rr_dnames_apply(rrset, pos, rrset_release_dnames_in_rr,
+ NULL);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rr: remove_rdata_pos: Could not release DNAMEs "
+ "within RDATA (%s).\n", knot_strerror(ret));
+ return ret;
+ }
+
+ /* Reorganize the actual RDATA array. */
+ uint8_t *rdata_to_remove = rrset_rdata_pointer(rrset, pos);
+ dbg_rrset_detail("rr: remove_rdata_pos: Removing data=%p on "
+ "position=%zu\n", rdata_to_remove, pos);
+ assert(rdata_to_remove);
+ if (pos != rrset->rdata_count - 1) {
+ /* Not the last item in array - we need to move the data. */
+ uint8_t *next_rdata = rrset_rdata_pointer(rrset, pos + 1);
+ assert(next_rdata);
+ size_t remainder_size = rrset_rdata_size_total(rrset)
+ - rrset_rdata_offset(rrset, pos + 1);
+ /*
+ * Copy the all following RR data to where this item is.
+ * No need to worry about exceeding allocated space now.
+ */
+ memmove(rdata_to_remove, next_rdata, remainder_size);
+ }
+
+ uint32_t removed_size = rrset_rdata_item_size(rrset, pos);
+ uint32_t new_size = rrset_rdata_size_total(rrset) - removed_size;
+
+ /*! \todo Realloc might not be needed. Only if the RRSet is large. */
+ if (new_size == 0) {
+ assert(rrset->rdata_count == 1);
+ free(rrset->rdata);
+ rrset->rdata = NULL;
+ free(rrset->rdata_indices);
+ rrset->rdata_indices = NULL;
+ } else {
+ /* [code-review] Should not be done always - as said in the TODO
+ * above. But also, why here and not in the part
+ * handling the RDATA array?
+ */
+ rrset->rdata = xrealloc(rrset->rdata, new_size);
+ /*
+ * Handle RDATA indices. All indices larger than the removed one
+ * have to be adjusted. Last index will be changed later.
+ */
+ /* [code-review] The upper bound should be rdata_count - 2, it
+ * has not yet been adjusted.
+ */
+ for (uint16_t i = pos; i < rrset->rdata_count - 1; ++i) {
+ rrset->rdata_indices[i] = rrset->rdata_indices[i + 1] - removed_size;
+ }
+
+ /* Save size of the whole RDATA array. Note: probably not needed! */
+ rrset->rdata_indices[rrset->rdata_count - 2] = new_size;
+
+ /* Resize indices, might not be needed, but we'll do it to be proper. */
+ rrset->rdata_indices =
+ xrealloc(rrset->rdata_indices,
+ (rrset->rdata_count - 1) * sizeof(uint32_t));
+ }
+
+ --rrset->rdata_count;
+
+ dbg_rrset_detail("rrset: remove rdata pos: RR after removal:\n");
+ knot_rrset_dump(rrset);
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
-knot_rrset_t *knot_rrset_new(knot_dname_t *owner, uint16_t type,
- uint16_t rclass, uint32_t ttl)
+uint32_t rrset_rdata_size_total(const knot_rrset_t *rrset)
{
- knot_rrset_t *ret = malloc(sizeof(knot_rrset_t));
- if (ret == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
+ if (rrset == NULL || rrset->rdata_indices == NULL ||
+ rrset->rdata_count == 0) {
+ return 0;
}
+ /* Last index denotes end of all RRs. */
+ return (rrset->rdata_indices[rrset->rdata_count - 1]);
+}
+
+knot_rrset_t *knot_rrset_new(knot_dname_t *owner, uint16_t type,
+ uint16_t rclass, uint32_t ttl)
+{
+ knot_rrset_t *ret = xmalloc(sizeof(knot_rrset_t));
+
ret->rdata = NULL;
+ ret->rdata_count = 0;
+ ret->rdata_indices = NULL;
/* Retain reference to owner. */
knot_dname_retain(owner);
@@ -85,107 +847,73 @@ knot_rrset_t *knot_rrset_new(knot_dname_t *owner, uint16_t type,
return ret;
}
-/*----------------------------------------------------------------------------*/
-
-int knot_rrset_add_rdata(knot_rrset_t *rrset, knot_rdata_t *rdata)
+int knot_rrset_add_rdata(knot_rrset_t *rrset,
+ const uint8_t *rdata, uint16_t size)
{
- if (rrset == NULL || rdata == NULL) {
+ if (rrset == NULL || rdata == NULL || size == 0) {
return KNOT_EINVAL;
}
- if (rrset->rdata == NULL) {
- rrset->rdata = rdata;
- rrset->rdata->next = rrset->rdata;
- } else {
- knot_rdata_t *tmp;
-
- tmp = rrset->rdata;
+ uint8_t *p = knot_rrset_create_rdata(rrset, size);
+ memcpy(p, rdata, size);
- while (tmp->next != rrset->rdata) {
- tmp = tmp->next;
- }
- rdata->next = tmp->next;
- tmp->next = rdata;
- }
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-int knot_rrset_add_rdata_order(knot_rrset_t *rrset, knot_rdata_t *rdata)
+uint8_t* knot_rrset_create_rdata(knot_rrset_t *rrset, uint16_t size)
{
- if (rrset == NULL || rdata == NULL) {
- dbg_rrset("rrset: add_rdata_order: NULL arguments.\n");
- return KNOT_EINVAL;
+ if (rrset == NULL || size == 0) {
+ return NULL;
}
-
- if (rrset->rdata == NULL) {
- /* Easy peasy, just insert the first item. */
- rrset->rdata = rdata;
- rrset->rdata->next = rrset->rdata;
+
+ uint32_t total_size = rrset_rdata_size_total(rrset);
+
+ /* Realloc indices. We will allocate exact size to save space. */
+ /* TODO this sucks big time - allocation of length 1. */
+ /* But another variable holding allocated count is out of question. What now?*/
+ rrset->rdata_indices = xrealloc(rrset->rdata_indices,
+ (rrset->rdata_count + 1) * sizeof(uint32_t));
+
+ /* Realloc actual data. */
+ rrset->rdata = xrealloc(rrset->rdata, total_size + size);
+
+ /* Pointer to new memory. */
+ uint8_t *dst = rrset->rdata + total_size;
+
+ /* Update indices. */
+ if (rrset->rdata_count == 0) {
+ rrset->rdata_indices[0] = size;
} else {
- knot_rdata_t *walk = NULL;
- char found = 0;
- knot_rdata_t *insert_after = rrset->rdata;
- while (((walk = knot_rrset_rdata_get_next(rrset,
- walk)) != NULL) &&
- (!found)) {
- const knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
- assert(desc);
- int cmp = knot_rdata_compare(rdata, walk,
- desc->wireformat);
- if (cmp < 1) {
- /* We've found place for this item. */
- } else if (cmp == 0) {
- /* This item will not be inserted. */
- found = 1;
- insert_after = NULL;
- }
- assert(cmp > 1);
- /* Continue the search. */
- insert_after = walk;
- }
- if (insert_after != NULL) {
- rdata->next = insert_after->next;
- insert_after->next = rdata;
- } else {
- ;
- /* Consider returning something different than EOK. */
- }
+ rrset->rdata_indices[rrset->rdata_count - 1] = total_size;
+ rrset->rdata_indices[rrset->rdata_count] = total_size + size;
}
- return KNOT_EOK;
+
+ ++rrset->rdata_count;
+
+ return dst;
}
/*----------------------------------------------------------------------------*/
-knot_rdata_t *knot_rrset_remove_rdata(knot_rrset_t *rrset,
- const knot_rdata_t *rdata)
-{
- if (rrset == NULL || rdata == NULL) {
- return NULL;
- }
- knot_rdata_t *prev = NULL;
- knot_rdata_t *rr = rrset->rdata;
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
-
- if (desc == NULL) {
- return NULL;
+uint16_t rrset_rdata_item_size(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || rrset->rdata_indices == NULL ||
+ rrset->rdata_count == 0) {
+ //invalid case
+ return 0;
}
- while (rr != NULL) {
- /*! \todo dnames are compared case-insensitive. is it OK?*/
- if (knot_rdata_compare(rr, rdata, desc->wireformat) == 0) {
- knot_rrset_disconnect_rdata(rrset, prev, rr);
- return rr;
- }
- prev = rr;
- rr = knot_rrset_rdata_get_next(rrset, rr);
+ if (rrset->rdata_count == 1 || pos == 0) {
+ //first RR or only one RR (either size of first RR or total size)
+ return rrset->rdata_indices[0];
}
- return NULL;
+ assert(rrset->rdata_count >= 2 && pos != 0);
+ return rrset->rdata_indices[pos] - rrset->rdata_indices[pos - 1];
}
/*----------------------------------------------------------------------------*/
@@ -203,31 +931,27 @@ int knot_rrset_set_rrsigs(knot_rrset_t *rrset, knot_rrset_t *rrsigs)
/*----------------------------------------------------------------------------*/
int knot_rrset_add_rrsigs(knot_rrset_t *rrset, knot_rrset_t *rrsigs,
- knot_rrset_dupl_handling_t dupl)
+ knot_rrset_dupl_handling_t dupl)
{
if (rrset == NULL || rrsigs == NULL
- || knot_dname_compare(rrset->owner, rrsigs->owner) != 0) {
+ || knot_dname_compare_non_canon(rrset->owner, rrsigs->owner) != 0) {
return KNOT_EINVAL;
}
int rc;
if (rrset->rrsigs != NULL) {
if (dupl == KNOT_RRSET_DUPL_MERGE) {
- rc = knot_rrset_merge_no_dupl((void **)&rrset->rrsigs,
- (void **)&rrsigs);
- if (rc < 0) {
+ int merged, deleted_rrs;
+ rc = knot_rrset_merge_no_dupl(rrset->rrsigs, rrsigs,
+ &merged, &deleted_rrs);
+ if (rc != KNOT_EOK) {
return rc;
- } else {
+ } else if (merged || deleted_rrs) {
return 1;
+ } else {
+ return 0;
}
} else if (dupl == KNOT_RRSET_DUPL_SKIP) {
-// rc = knot_rrset_merge_no_dupl((void **)&rrset->rrsigs,
-// (void **)&rrsigs);
-// if (rc != KNOT_EOK) {
-// return rc;
-// } else {
-// return 1;
-// }
return 2;
} else if (dupl == KNOT_RRSET_DUPL_REPLACE) {
rrset->rrsigs = rrsigs;
@@ -236,7 +960,6 @@ int knot_rrset_add_rrsigs(knot_rrset_t *rrset, knot_rrset_t *rrsigs,
if (rrset->ttl != rrsigs->ttl) {
rrsigs->ttl = rrset->ttl;
}
-
rrset->rrsigs = rrsigs;
}
@@ -259,7 +982,7 @@ knot_dname_t *knot_rrset_get_owner(const knot_rrset_t *rrset)
/*----------------------------------------------------------------------------*/
-void knot_rrset_set_owner(knot_rrset_t *rrset, knot_dname_t* owner)
+void knot_rrset_set_owner(knot_rrset_t *rrset, knot_dname_t *owner)
{
if (rrset) {
/* Retain new owner and release old owner. */
@@ -280,15 +1003,6 @@ void knot_rrset_set_ttl(knot_rrset_t *rrset, uint32_t ttl)
/*----------------------------------------------------------------------------*/
-void knot_rrset_set_class(knot_rrset_t *rrset, uint16_t rclass)
-{
- if (rrset) {
- rrset->rclass = rclass;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
uint16_t knot_rrset_type(const knot_rrset_t *rrset)
{
return rrset->type;
@@ -310,69 +1024,20 @@ uint32_t knot_rrset_ttl(const knot_rrset_t *rrset)
/*----------------------------------------------------------------------------*/
-const knot_rdata_t *knot_rrset_rdata(const knot_rrset_t *rrset)
+uint8_t *knot_rrset_get_rdata(const knot_rrset_t *rrset, size_t rdata_pos)
{
- return rrset->rdata;
+ return rrset_rdata_pointer(rrset, rdata_pos);
}
/*----------------------------------------------------------------------------*/
-const knot_rdata_t *knot_rrset_rdata_next(const knot_rrset_t *rrset,
- const knot_rdata_t *rdata)
+uint16_t knot_rrset_rdata_rr_count(const knot_rrset_t *rrset)
{
- if (rdata == NULL) {
- return rrset->rdata;
- }
- if (rdata->next == rrset->rdata) {
- return NULL;
+ if (rrset != NULL) {
+ return rrset->rdata_count;
} else {
- return rdata->next;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-knot_rdata_t *knot_rrset_get_rdata(knot_rrset_t *rrset)
-{
- if (rrset == NULL) {
- return NULL;
- } else {
- return rrset->rdata;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-knot_rdata_t *knot_rrset_rdata_get_next(knot_rrset_t *rrset,
- knot_rdata_t *rdata)
-{
- if (!rdata || !rrset) {
- return NULL;
- }
- if (rdata->next == rrset->rdata) {
- return NULL;
- } else {
- return rdata->next;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_rrset_rdata_rr_count(const knot_rrset_t *rrset)
-{
- if (rrset == NULL) {
return 0;
}
-
- int count = 0;
- const knot_rdata_t *rdata = rrset->rdata;
-
- while (rdata != NULL) {
- ++count;
- rdata = knot_rrset_rdata_next(rrset, rdata);
- }
-
- return count;
}
/*----------------------------------------------------------------------------*/
@@ -380,7 +1045,6 @@ int knot_rrset_rdata_rr_count(const knot_rrset_t *rrset)
const knot_rrset_t *knot_rrset_rrsigs(const knot_rrset_t *rrset)
{
if (rrset == NULL) {
- assert(0);
return NULL;
} else {
return rrset->rrsigs;
@@ -392,255 +1056,268 @@ const knot_rrset_t *knot_rrset_rrsigs(const knot_rrset_t *rrset)
knot_rrset_t *knot_rrset_get_rrsigs(knot_rrset_t *rrset)
{
if (rrset == NULL) {
- assert(0);
return NULL;
} else {
return rrset->rrsigs;
}
}
-/*----------------------------------------------------------------------------*/
-
-int knot_rrset_compare_rdata(const knot_rrset_t *r1, const knot_rrset_t *r2)
+int knot_rrset_rdata_equal(const knot_rrset_t *r1, const knot_rrset_t *r2)
{
- if (r1 == NULL || r2 == NULL) {
- return KNOT_EINVAL;
- }
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(r1->type);
- if (desc == NULL) {
+ if (r1 == NULL || r2 == NULL || (r1->type != r2->type) ||
+ r1->rdata_count == 0 || r2->rdata_count == 0) {
return KNOT_EINVAL;
}
// compare RDATA sets (order is not significant)
- const knot_rdata_t *rdata1 = knot_rrset_rdata(r1);
- const knot_rdata_t *rdata2;
// find all RDATA from r1 in r2
- while (rdata1 != NULL) {
- rdata2 = knot_rrset_rdata(r2);
- while (rdata2 != NULL && knot_rdata_compare(rdata1, rdata2,
- desc->wireformat)) {
- rdata2 = knot_rrset_rdata_next(r2, rdata2);
- }
-
- if (rdata2 == NULL) {
- // RDATA from r1 not found in r2
- return 0;
- }
-
- // otherwise it was found, continue with next r1 RDATA
- rdata1 = knot_rrset_rdata_next(r1, rdata1);
+ int found = 0;
+ for (uint16_t i = 0; i < r1->rdata_count; i++) {
+ found = 0;
+ for (uint16_t j = 0; j < r2->rdata_count && !found; j++) {
+ found = !rrset_rdata_compare_one(r1, r2, i, j);
+ }
}
- // find all RDATA from r2 in r1 (this can be done in a better way)
- rdata2 = knot_rrset_rdata(r2);
- while (rdata2 != NULL) {
- rdata1 = knot_rrset_rdata(r1);
-
- while (rdata2 != NULL && rdata1 != NULL
- && knot_rdata_compare(rdata1, rdata2,
- desc->wireformat)) {
- rdata1 = knot_rrset_rdata_next(r1, rdata1);
- }
+ if (!found) {
+ return 0;
+ }
- if (rdata1 == NULL) {
- // RDATA from r2 not found in r1
- return 0;
- }
+ // other way around
+ for (uint16_t i = 0; i < r2->rdata_count; i++) {
+ found = 0;
+ for (uint16_t j = 0; j < r1->rdata_count && !found; j++) {
+ found = !rrset_rdata_compare_one(r1, r2, j, i);
+ }
+ }
- // otherwise it was found, continue with next r1 RDATA
- rdata2 = knot_rrset_rdata_next(r2, rdata2);
+ if (!found) {
+ return 0;
}
- // all RDATA found
return 1;
}
/*----------------------------------------------------------------------------*/
-static int knot_rrset_rr_to_wire(const knot_rrset_t *rrset,
- const knot_rdata_t *rdata, uint8_t **pos,
- size_t max_size)
+int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, size_t *size,
+ size_t max_size, uint16_t *rr_count, void *data)
{
- int size = 0;
-
- assert(rrset != NULL);
- assert(rrset->owner != NULL);
- assert(rdata != NULL);
- assert(pos != NULL);
- assert(*pos != NULL);
-
- dbg_rrset_detail("Max size: %zu, owner: %p, owner size: %d\n",
- max_size, rrset->owner, rrset->owner->size);
-
- // check if owner fits
- if (size + knot_dname_size(rrset->owner) + 10 > max_size) {
- return KNOT_ESPACE;
+ if (rrset == NULL || wire == NULL || size == NULL || rr_count == NULL) {
+ return KNOT_EINVAL;
}
-
- memcpy(*pos, knot_dname_name(rrset->owner),
- knot_dname_size(rrset->owner));
- *pos += knot_dname_size(rrset->owner);
- size += knot_dname_size(rrset->owner);
-
- dbg_rrset_detail("Max size: %zu, size: %d\n", max_size, size);
-
- dbg_rrset_detail("Wire format:\n");
-
- // put rest of RR 'header'
- knot_wire_write_u16(*pos, rrset->type);
- dbg_rrset_detail(" Type: %u\n", rrset->type);
- *pos += 2;
-
- knot_wire_write_u16(*pos, rrset->rclass);
- dbg_rrset_detail(" Class: %u\n", rrset->rclass);
- *pos += 2;
-
- knot_wire_write_u32(*pos, rrset->ttl);
- dbg_rrset_detail(" TTL: %u\n", rrset->ttl);
- *pos += 4;
-
- // save space for RDLENGTH
- uint8_t *rdlength_pos = *pos;
- *pos += 2;
-
- size += 10;
-
- dbg_rrset_detail("Max size: %zu, size: %d\n", max_size, size);
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
+ compression_param_t *comp_data = (compression_param_t *)data;
+ uint8_t *pos = wire;
- uint16_t rdlength = 0;
+dbg_rrset_exec_detail(
+ dbg_rrset_detail("Converting following RRSet:\n");
+ knot_rrset_dump(rrset);
+);
- for (int i = 0; i < rdata->count; ++i) {
- if (max_size < size + rdlength) {
- return KNOT_ESPACE;
- }
-
- switch (desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME: {
- knot_dname_t *dname =
- knot_rdata_item(rdata, i)->dname;
- if (size + rdlength + dname->size > max_size) {
- return KNOT_ESPACE;
- }
+ int ret = knot_rrset_to_wire_aux(rrset, &pos, max_size, comp_data);
+ if (ret < 0) {
+ // some RR didn't fit in, so no RRs should be used
+ // TODO: remove last entries from compression table
+ dbg_rrset_verb("Some RR didn't fit in.\n");
+ return KNOT_ESPACE;
+ }
- // save whole domain name
- memcpy(*pos, knot_dname_name(dname),
- knot_dname_size(dname));
- dbg_rrset_detail("Uncompressed dname size: %d\n",
- knot_dname_size(dname));
- *pos += knot_dname_size(dname);
- rdlength += knot_dname_size(dname);
- break;
- }
- default: {
- uint16_t *raw_data =
- knot_rdata_item(rdata, i)->raw_data;
+ // Check if the whole RRSet fit into packet.
+ assert(ret <= max_size);
+ assert(pos - wire == ret);
- if (size + rdlength + raw_data[0] > max_size) {
- return KNOT_ESPACE;
- }
+ *size = ret;
- // copy just the rdata item data (without size)
- memcpy(*pos, raw_data + 1, raw_data[0]);
- dbg_rrset_detail("Raw data size: %d\n", raw_data[0]);
- *pos += raw_data[0];
- rdlength += raw_data[0];
- break;
- }
- }
- }
-
- dbg_rrset_detail("Max size: %zu, size: %d\n", max_size, size);
+ dbg_rrset_detail("Size after: %zu\n", *size);
- assert(size + rdlength <= max_size);
- size += rdlength;
- knot_wire_write_u16(rdlength_pos, rdlength);
+ // If the rrset is empty set record counter to 1.
+ *rr_count = rrset->rdata_count > 0 ? rrset->rdata_count : 1;
- return size;
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, size_t *size,
- int *rr_count)
+int knot_rrset_rdata_from_wire_one(knot_rrset_t *rrset,
+ const uint8_t *wire, size_t *pos,
+ size_t total_size, size_t rdlength)
{
- // if no RDATA in RRSet, return
- if (rrset->rdata == NULL) {
- *size = 0;
- *rr_count = 0;
+ /* [code-review] Missing parameter checks. */
+
+ if (rdlength == 0) {
+ /* Nothing to parse, */
return KNOT_EOK;
}
-
-
- uint8_t *pos = wire;
- int rrs = 0;
- short rrset_size = 0;
- const knot_rdata_t *rdata = rrset->rdata;
- do {
- int ret = knot_rrset_rr_to_wire(rrset, rdata, &pos,
- *size - rrset_size);
+ dbg_rrset_detail("rr: parse_rdata_wire: Parsing RDATA of size=%zu,"
+ " wire_size=%zu, type=%d.\n", rdlength, total_size,
+ rrset->type);
- assert(ret != 0);
+ size_t extra_dname_size = 0;
+ const rdata_descriptor_t *desc = get_rdata_descriptor(rrset->type);
- if (ret < 0) {
- // some RR didn't fit in, so no RRs should be used
- // TODO: remove last entries from compression table
- dbg_rrset_verb("Some RR didn't fit in.\n");
- return KNOT_ESPACE;
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; ++i) {
+ if (descriptor_item_is_dname(desc->block_types[i])) {
+ extra_dname_size += sizeof(knot_dname_t *) - 1;
}
+ }
- dbg_rrset_verb("RR of size %d added.\n", ret);
- rrset_size += ret;
- ++rrs;
- } while ((rdata = knot_rrset_rdata_next(rrset, rdata)) != NULL);
-
- // the whole RRSet did fit in
- assert(rrset_size <= *size);
- assert(pos - wire == rrset_size);
- *size = rrset_size;
+ /* [code-review] Isn't this invalid? You cannot do static allocation
+ * with dynamic data (parameter, local variable).
+ */
+ uint8_t rdata_buffer[rdlength + extra_dname_size];
+ memset(rdata_buffer, 0, rdlength + extra_dname_size);
+ dbg_rrset_detail("rr: parse_rdata_wire: Added %zu bytes to buffer to "
+ "store RDATA DNAME pointers.\n", extra_dname_size);
+
+ size_t offset = 0; // offset within in-memory RDATA
+ size_t parsed = 0; // actual count of parsed octets
+ const size_t packet_offset = *pos;
+
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END &&
+ parsed < rdlength; ++i) {
+ size_t pos2 = 0; //used for DNAME parsing
+ const int item = desc->block_types[i];
+ if (descriptor_item_is_dname(item)) {
+ pos2 = *pos;
+ knot_dname_t *dname = knot_dname_parse_from_wire(
+ wire, &pos2, total_size, NULL, NULL);
+ if (dname == NULL) {
+ return KNOT_EMALF;
+ }
+ knot_dname_to_lower(dname);
+ memcpy(rdata_buffer + offset, &dname,
+ sizeof(knot_dname_t *));
+ parsed += pos2 - *pos;
+ dbg_rrset_detail("rr: parse_rdata_wire: Parsed DNAME, "
+ "length=%zu.\n", pos2 - *pos);
+dbg_rrset_exec_detail(
+ char *name = knot_dname_to_str(dname);
+ dbg_rrset_detail("rr: parse_rdata_wire: Parsed "
+ "DNAME=%s\n", name);
+ free(name);
+);
+ *pos = pos2;
+ offset += sizeof(knot_dname_t *);
+ } else if (descriptor_item_is_fixed(item)) {
+ dbg_rrset_detail("rr: parse_rdata_wire: Saving static "
+ "chunk of size=%u\n", item);
+ int ret = knot_rrset_rdata_store_binary(rdata_buffer,
+ &offset,
+ packet_offset,
+ wire,
+ pos,
+ rdlength,
+ item);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rrset: rdata_from_wire: "
+ "Cannot store fixed RDATA chunk. "
+ "Reason: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ parsed += item;
+ } else if (descriptor_item_is_remainder(item)) {
+ /* Item size has to be calculated. */
+ size_t remainder_size = rdlength - parsed;
+ dbg_rrset_detail("rr: parse_rdata_wire: Saving remaining "
+ "chunk of size=%zu\n", remainder_size);
+ int ret = knot_rrset_rdata_store_binary(rdata_buffer,
+ &offset,
+ packet_offset,
+ wire,
+ pos,
+ rdlength,
+ remainder_size);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rrset: rdata_from_wire: "
+ "Cannot store RDATA remainder of "
+ "size=%zu, RDLENGTH=%zu. "
+ "Reason: %s.\n", remainder_size,
+ rdlength, knot_strerror(ret));
+ return ret;
+ }
+ parsed += remainder_size;
+ } else {
+ assert(rrset->type == KNOT_RRTYPE_NAPTR);
+ /* Read fixed part - 2 shorts. */
+ const size_t naptr_fixed_part_size = 4;
+ int ret = knot_rrset_rdata_store_binary(rdata_buffer,
+ &offset,
+ packet_offset,
+ wire,
+ pos,
+ rdlength,
+ naptr_fixed_part_size);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rrset: rdata_from_wire: "
+ "Cannot store NAPTR fixed part. "
+ "Reason: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ parsed += naptr_fixed_part_size;
+ for (int j = 0; j < 3; ++j) {
+ /* Read sizes of TXT's - one byte. */
+ uint8_t txt_size = *(wire + (*pos)) + 1;
+ dbg_rrset_detail("rrset: rdata_from_wire: "
+ "Read TXT nr=%d size=%d\n", j,
+ txt_size);
+ int ret = knot_rrset_rdata_store_binary(rdata_buffer,
+ &offset,
+ packet_offset,
+ wire,
+ pos,
+ rdlength,
+ txt_size);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rrset: rdata_from_wire: "
+ "Cannot store NAPTR TXTs. "
+ "Reason: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ parsed += txt_size;
+ }
+ }
+ }
- dbg_rrset_detail("Size after: %zu\n", *size);
+ uint8_t *rdata = knot_rrset_create_rdata(rrset, offset);
+ if (rdata == NULL) {
+ return KNOT_ENOMEM;
+ }
- *rr_count = rrs;
+ memcpy(rdata, rdata_buffer, offset);
return KNOT_EOK;
}
-/*----------------------------------------------------------------------------*/
-
-int knot_rrset_match(const knot_rrset_t *r1,
- const knot_rrset_t *r2,
- knot_rrset_compare_type_t cmp)
+int knot_rrset_equal(const knot_rrset_t *r1,
+ const knot_rrset_t *r2,
+ knot_rrset_compare_type_t cmp)
{
if (cmp == KNOT_RRSET_COMPARE_PTR) {
- return (r1 == r2);
+ return r1 == r2;
}
- int res = ((r1->rclass == r2->rclass)
- && (r1->type == r2->type)
-// && (r1->ttl == r2->ttl)
- && knot_dname_compare(r1->owner, r2->owner) == 0);
+ int res = knot_dname_compare_non_canon(r1->owner, r2->owner);
+ if (res != 0) {
+ return 0;
+ }
- if (cmp == KNOT_RRSET_COMPARE_WHOLE && res) {
- res = knot_rrset_compare_rdata(r1, r2);
- if (res < 0) {
- return 0;
- }
+ if (r1->rclass == r2->rclass &&
+ r1->type == r2->type) {
+ res = 1;
+ } else {
+ res = 0;
+ }
+
+ if (cmp == KNOT_RRSET_COMPARE_WHOLE && res == 1) {
+ res = knot_rrset_rdata_equal(r1, r2);
}
return res;
}
-/*----------------------------------------------------------------------------*/
-
int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to,
int copy_rdata_dnames)
{
@@ -648,48 +1325,72 @@ int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to,
return KNOT_EINVAL;
}
- int ret;
+ dbg_rrset_detail("rr: deep_copy: Copying RRs of type %d\n",
+ from->type);
- *to = (knot_rrset_t *)calloc(1, sizeof(knot_rrset_t));
- CHECK_ALLOC_LOG(*to, KNOT_ENOMEM);
+ *to = xmalloc(sizeof(knot_rrset_t));
+
+ (*to)->owner = knot_dname_deep_copy(from->owner);
+ if ((*to)->owner == NULL) {
+ free(*to);
+ *to = NULL;
+ return KNOT_ENOMEM;
+ }
- (*to)->owner = from->owner;
- knot_dname_retain((*to)->owner);
(*to)->rclass = from->rclass;
(*to)->ttl = from->ttl;
(*to)->type = from->type;
+ (*to)->rdata_count = from->rdata_count;
if (from->rrsigs != NULL) {
- ret = knot_rrset_deep_copy(from->rrsigs, &(*to)->rrsigs,
+ int ret = knot_rrset_deep_copy(from->rrsigs, &(*to)->rrsigs,
copy_rdata_dnames);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(to, 1, 0, 0);
+ knot_rrset_deep_free(to, 1, 0);
return ret;
}
+ } else {
+ (*to)->rrsigs = NULL;
}
- assert((*to)->rrsigs == NULL || from->rrsigs != NULL);
- const knot_rdata_t *rdata = knot_rrset_rdata(from);
-
- /*! \note Order of RDATA will be reversed. */
- while (rdata != NULL) {
- knot_rdata_t *rdata_copy = knot_rdata_deep_copy(rdata,
- knot_rrset_type(from),
- copy_rdata_dnames);
+ /* Just copy arrays - actual data + indices. */
+ (*to)->rdata = xmalloc(rrset_rdata_size_total(from));
+ memcpy((*to)->rdata, from->rdata, rrset_rdata_size_total(from));
+
+ (*to)->rdata_indices = xmalloc(sizeof(uint32_t) * from->rdata_count);
+ memcpy((*to)->rdata_indices, from->rdata_indices,
+ sizeof(uint32_t) * from->rdata_count);
+ /* Here comes the hard part. */
+ if (copy_rdata_dnames) {
+ knot_dname_t **dname_from = NULL;
+ knot_dname_t **dname_to = NULL;
+ knot_dname_t *dname_copy = NULL;
+ while ((dname_from = knot_rrset_get_next_dname(from, dname_from))) {
dbg_rrset_exec_detail(
- char *name = knot_dname_to_str(knot_rrset_owner(from));
- dbg_rrset_detail("Copying RDATA from RRSet with owner: %s, type"
- ": %s. Old RDATA ptr: %p, new RDATA ptr: %p\n",
- name,
- knot_rrtype_to_string(knot_rrset_type(from)),
- rdata, rdata_copy);
- free(name);
+ char *name = knot_dname_to_str(*dname_from);
+ dbg_rrset_detail("rrset: deep_copy: copying RDATA DNAME"
+ "=%s\n", name);
+ free(name);
);
- ret = knot_rrset_add_rdata(*to, rdata_copy);
- if (ret != KNOT_EOK) {
- knot_rrset_deep_free(to, 1, 1, 1);
- return ret;
+ size_t off = (uint8_t*)dname_from - from->rdata;
+ dname_to = (knot_dname_t **)((*to)->rdata + off);
+ /* These pointers have to be the same. */
+ assert(*dname_from == *dname_to);
+ dname_copy = knot_dname_deep_copy(*dname_from);
+ if (dname_copy == NULL) {
+ dbg_rrset("rrset: deep_copy: Cannot copy RDATA"
+ " dname.\n");
+ /*! \todo This will leak. Is it worth fixing? */
+ /* [code-review] Why will it leak? */
+ knot_rrset_deep_free(&(*to)->rrsigs, 1,
+ copy_rdata_dnames);
+ free((*to)->rdata);
+ free((*to)->rdata_indices);
+ free(*to);
+ return KNOT_ENOMEM;
+ }
+
+ *dname_to = dname_copy;
}
- rdata = knot_rrset_rdata_next(from, rdata);
}
return KNOT_EOK;
@@ -701,12 +1402,12 @@ int knot_rrset_shallow_copy(const knot_rrset_t *from, knot_rrset_t **to)
{
*to = (knot_rrset_t *)malloc(sizeof(knot_rrset_t));
CHECK_ALLOC_LOG(*to, KNOT_ENOMEM);
-
+
memcpy(*to, from, sizeof(knot_rrset_t));
/* Retain owner. */
knot_dname_retain((*to)->owner);
-
+
return KNOT_EOK;
}
@@ -733,103 +1434,124 @@ void knot_rrset_free(knot_rrset_t **rrset)
*rrset = NULL;
}
-/*----------------------------------------------------------------------------*/
-
void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
- int free_rdata, int free_rdata_dnames)
+ int free_rdata_dnames)
{
if (rrset == NULL || *rrset == NULL) {
return;
}
- if (free_rdata) {
- knot_rdata_t *tmp_rdata;
- knot_rdata_t *next_rdata;
- tmp_rdata = (*rrset)->rdata;
+ if ((*rrset)->rrsigs != NULL) {
+ knot_rrset_deep_free(&(*rrset)->rrsigs, free_owner, free_rdata_dnames);
+ }
- while ((tmp_rdata != NULL)
- && (tmp_rdata->next != (*rrset)->rdata)
- && (tmp_rdata->next != NULL)) {
- next_rdata = tmp_rdata->next;
- knot_rdata_deep_free(&tmp_rdata, (*rrset)->type,
- free_rdata_dnames);
- tmp_rdata = next_rdata;
- }
+ if (free_rdata_dnames) {
+ rrset_dnames_apply(*rrset, rrset_release_dnames_in_rr,
+ NULL);
+ }
- assert(tmp_rdata == NULL
- || tmp_rdata->next == (*rrset)->rdata);
+ free((*rrset)->rdata);
+ free((*rrset)->rdata_indices);
- knot_rdata_deep_free(&tmp_rdata, (*rrset)->type,
- free_rdata_dnames);
+ if (free_owner) {
+ knot_dname_release((*rrset)->owner);
}
- // RRSIGs should have the same owner as this RRSet, so do not delete it
- if ((*rrset)->rrsigs != NULL) {
- knot_rrset_deep_free(&(*rrset)->rrsigs, 0, 1,
- free_rdata_dnames);
+ free(*rrset);
+ *rrset = NULL;
+}
+
+void knot_rrset_deep_free_no_sig(knot_rrset_t **rrset, int free_owner,
+ int free_rdata_dnames)
+{
+ if (rrset == NULL || *rrset == NULL) {
+ return;
}
- knot_dname_release((*rrset)->owner);
+ if (free_rdata_dnames) {
+ int ret = rrset_dnames_apply(*rrset, rrset_release_dnames_in_rr,
+ NULL);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rr: deep_free: Could not free DNAMEs in RDATA.\n");
+ }
+ }
+
+ free((*rrset)->rdata);
+ free((*rrset)->rdata_indices);
+
+ if (free_owner) {
+ knot_dname_release((*rrset)->owner);
+ }
free(*rrset);
*rrset = NULL;
}
-/*----------------------------------------------------------------------------*/
-
-int knot_rrset_merge(void **r1, void **r2)
+int knot_rrset_merge(knot_rrset_t *rrset1, const knot_rrset_t *rrset2)
{
- knot_rrset_t *rrset1 = (knot_rrset_t *)(*r1);
- knot_rrset_t *rrset2 = (knot_rrset_t *)(*r2);
-
- if ((knot_dname_compare(rrset1->owner, rrset2->owner) != 0)
- || rrset1->rclass != rrset2->rclass
- || rrset1->type != rrset2->type) {
+ if (rrset1 == NULL || rrset2 == NULL) {
return KNOT_EINVAL;
}
- // add all RDATAs from rrset2 to rrset1 (i.e. concatenate linked lists)
+ /* Check, that we really merge RRSets? */
+ if (rrset1->type != rrset2->type ||
+ rrset1->rclass != rrset2->rclass ||
+ (knot_dname_compare_non_canon(rrset1->owner, rrset2->owner) != 0)) {
+ return KNOT_EINVAL;
+ }
- // no RDATA in RRSet 1
- assert(rrset1 && rrset2);
- if (rrset1->rdata == NULL) {
- rrset1->rdata = rrset2->rdata;
+ /* Merging empty RRSets is OK. */
+ if (rrset1->rdata_count == 0 && rrset2->rdata_count == 0) {
return KNOT_EOK;
}
- knot_rdata_t *tmp_rdata = rrset1->rdata;
+ /* Add all RDATAs from rrset2 to rrset1 (i.e. concatenate two arrays) */
- if (!tmp_rdata) {
- return KNOT_EOK;
- }
+ /*! \note The following code should work for
+ * all the cases i.e. R1 or R2 are empty.
+ */
- while (tmp_rdata->next != rrset1->rdata) {
- tmp_rdata = tmp_rdata->next;
- }
+ /* Reallocate actual RDATA array. */
+ rrset1->rdata = xrealloc(rrset1->rdata, rrset_rdata_size_total(rrset1) +
+ rrset_rdata_size_total(rrset2));
- tmp_rdata->next = rrset2->rdata;
+ /* The space is ready, copy the actual data. */
+ memcpy(rrset1->rdata + rrset_rdata_size_total(rrset1),
+ rrset2->rdata, rrset_rdata_size_total(rrset2));
- tmp_rdata = rrset2->rdata; //maybe unnecessary, but is clearer
+ /* Indices have to be readjusted. But space has to be made first. */
+ rrset1->rdata_indices =
+ xrealloc(rrset1->rdata_indices,
+ (rrset1->rdata_count + rrset2->rdata_count) *
+ sizeof(uint32_t));
+
+ uint32_t rrset1_total_size = rrset_rdata_size_total(rrset1);
+ uint32_t rrset2_total_size = rrset_rdata_size_total(rrset2);
+
+ /*
+ * Move the indices. Discard the last item in the first array, as it
+ * contains total length of the data, which is now different.
+ */
+ memcpy(rrset1->rdata_indices + rrset1->rdata_count,
+ rrset2->rdata_indices, rrset2->rdata_count);
- while (tmp_rdata->next != rrset2->rdata) {
- tmp_rdata = tmp_rdata->next;
+ /* Go through the second part of index array and adjust offsets. */
+ for (uint16_t i = 0; i < rrset2->rdata_count - 1; i++) {
+ rrset1->rdata_indices[rrset1->rdata_count + i] +=
+ rrset1_total_size;
}
- tmp_rdata->next = rrset1->rdata;
- rrset2->rdata = rrset1->rdata;
+ rrset1->rdata_indices[rrset1->rdata_count + rrset2->rdata_count - 1] =
+ rrset1_total_size + rrset2_total_size;
+
+ rrset1->rdata_count += rrset2->rdata_count;
return KNOT_EOK;
}
-int knot_rrset_merge_no_dupl(void **r1, void **r2)
+int knot_rrset_merge_no_dupl(knot_rrset_t *rrset1, const knot_rrset_t *rrset2,
+ int *merged, int *deleted_rrs)
{
- if (r1 == NULL || r2 == NULL) {
- dbg_rrset("rrset: merge_no_dupl: NULL arguments.");
- return KNOT_EINVAL;
- }
-
- knot_rrset_t *rrset1 = (knot_rrset_t *)(*r1);
- knot_rrset_t *rrset2 = (knot_rrset_t *)(*r2);
if (rrset1 == NULL || rrset2 == NULL) {
dbg_rrset("rrset: merge_no_dupl: NULL arguments.");
return KNOT_EINVAL;
@@ -841,7 +1563,7 @@ dbg_rrset_exec_detail(
free(name);
);
- if ((knot_dname_compare(rrset1->owner, rrset2->owner) != 0)
+ if ((knot_dname_compare_non_canon(rrset1->owner, rrset2->owner) != 0)
|| rrset1->rclass != rrset2->rclass
|| rrset1->type != rrset2->type) {
dbg_rrset("rrset: merge_no_dupl: Trying to merge "
@@ -849,124 +1571,1108 @@ dbg_rrset_exec_detail(
return KNOT_EINVAL;
}
- knot_rdata_t *walk2 = rrset2->rdata;
- int deleted = 0;
+ *deleted_rrs = 0;
+ *merged = 0;
+ /* For each item in second RRSet, make sure it is not duplicated. */
+ for (uint16_t i = 0; i < rrset2->rdata_count; i++) {
+ int duplicated = 0;
+ /* Compare with all RRs in the first RRSet. */
+ for (uint16_t j = 0; j < rrset1->rdata_count && !duplicated;
+ j++) {
+ duplicated = !rrset_rdata_compare_one(rrset1, rrset2,
+ j, i);
+ }
- // no RDATA in RRSet 1
- if (rrset1->rdata == NULL && rrset2->rdata != NULL) {
- /*
- * This function has to assure that there are no duplicates in
- * second RRSet's list. This can be done by putting a first
- * item from the second list as a first item of the first list
- * and then simply continuing with inserting items from second
- * list to the first one.
- *
- * However, we must store pointer to second item in the second
- * list, as the 'next' pointer of the first item will be altered
- */
+ if (!duplicated) {
+ *merged += 1; // = need to shallow free rrset2
+ // This index goes to merged RRSet.
+ int ret = knot_rrset_add_rdata(rrset1,
+ rrset_rdata_pointer(rrset2, i),
+ rrset_rdata_item_size(rrset2, i));
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rrset: merge_no_dupl: Could not "
+ "add RDATA to RRSet. (%s)\n",
+ knot_strerror(ret));
+ return ret;
+ }
+ } else {
+ *deleted_rrs += 1; // = need to shallow free rrset2
+ }
+ }
- // Store pointer to the second item in RRSet2 RDATA so that
- // we later start from this item.
- walk2 = knot_rrset_rdata_get_next(rrset2, walk2);
- assert(walk2 == rrset2->rdata->next || walk2 == NULL);
+ return KNOT_EOK;
+}
- // Connect the first item from second list to the first list.
- rrset1->rdata = rrset2->rdata;
- // Close the cyclic list (by pointing to itself).
- rrset1->rdata->next = rrset1->rdata;
- } else if (rrset2->rdata == NULL) {
- return KNOT_EOK;
+/*----------------------------------------------------------------------------*/
+
+const knot_dname_t *knot_rrset_rdata_cname_name(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return NULL;
}
-
- /*
- * Check that rrset1 does not contain any rdata from rrset2, if so
- * such RDATA shall not be inserted.
- */
-
- /* Get last RDATA from first rrset, we'll need it for insertion. */
- knot_rdata_t *insert_after = rrset1->rdata;
- while (insert_after->next != rrset1->rdata) {
- dbg_rrset_detail("rrset: merge_dupl: first rrset rdata: %p.\n",
- insert_after);
- insert_after = insert_after->next;
- }
- assert(insert_after->next == rrset1->rdata);
-
- while (walk2 != NULL) {
- knot_rdata_t *walk1 = rrset1->rdata;
- char dupl = 0;
- while ((walk1 != NULL) &&
- !dupl) {
- const knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset1->type);
- assert(desc);
- /* If walk1 and walk2 are equal, do not insert. */
- dupl = !knot_rdata_compare(walk1, walk2,
- desc->wireformat);
- walk1 = knot_rrset_rdata_get_next(rrset1, walk1);
- dbg_rrset_detail("rrset: merge_dupl: next item: %p.\n",
- walk1);
- }
- if (!dupl) {
- dbg_rrset_detail("rrset: merge_dupl: Inserting "
- "unique item (%p).\n",
- walk2);
- knot_rdata_t *tmp = walk2;
- /*
- * We need to move this, insertion
- * will corrupt pointers.
+
+ knot_dname_t *dname;
+ memcpy(&dname, rrset->rdata, sizeof(knot_dname_t *));
+ return dname;
+}
+
+/*----------------------------------------------------------------------------*/
+
+const knot_dname_t *knot_rrset_rdata_dname_target(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+ knot_dname_t *dname;
+ memcpy(&dname, rrset->rdata, sizeof(knot_dname_t *));
+ return dname;
+}
+
+/*---------------------------------------------------------------------------*/
+
+const knot_dname_t *knot_rrset_rdata_soa_primary_ns(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+ knot_dname_t *dname;
+ memcpy(&dname, rrset->rdata, sizeof(knot_dname_t *));
+ return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_soa_mailbox(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+ knot_dname_t *dname;
+ memcpy(&dname, rrset->rdata + sizeof(knot_dname_t *),
+ sizeof(knot_dname_t *));
+ return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_rp_first_dname(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return NULL;
+ }
+
+ knot_dname_t *dname;
+ memcpy(&dname, knot_rrset_get_rdata(rrset, pos), sizeof(knot_dname_t *));
+ return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_rp_second_dname(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return NULL;
+ }
+
+ knot_dname_t *dname;
+ memcpy(&dname, knot_rrset_get_rdata(rrset, pos) + sizeof(knot_dname_t *),
+ sizeof(knot_dname_t *));
+ return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_minfo_first_dname(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ return knot_rrset_rdata_rp_first_dname(rrset, pos);
+}
+
+const knot_dname_t *knot_rrset_rdata_minfo_second_dname(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ return knot_rrset_rdata_rp_second_dname(rrset, pos);
+}
+
+uint32_t knot_rrset_rdata_soa_serial(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(rrset->rdata + sizeof(knot_dname_t *) * 2);
+}
+
+/*---------------------------------------------------------------------------*/
+
+void knot_rrset_rdata_soa_serial_set(knot_rrset_t *rrset, uint32_t serial)
+{
+ if (rrset == NULL) {
+ return;
+ }
+
+ // the number is in network byte order, transform it
+ knot_wire_write_u32(rrset->rdata + sizeof(knot_dname_t *) * 2,
+ serial);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint32_t knot_rrset_rdata_soa_refresh(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(rrset->rdata +
+ sizeof(knot_dname_t *) * 2 + 4);
+}
+
+/*---------------------------------------------------------------------------*/
+
+
+uint32_t knot_rrset_rdata_soa_retry(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(rrset->rdata +
+ sizeof(knot_dname_t *) * 2 + 8);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint32_t knot_rrset_rdata_soa_expire(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(rrset->rdata +
+ sizeof(knot_dname_t *) * 2 + 12);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint32_t knot_rrset_rdata_soa_minimum(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(rrset->rdata +
+ sizeof(knot_dname_t *) * 2 + 16);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint16_t knot_rrset_rdata_rrsig_type_covered(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return knot_wire_read_u16(rrset->rdata);
+}
+
+uint8_t knot_rrset_rdata_rrsig_algorithm(const knot_rrset_t *rrset,
+ size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return *(knot_rrset_get_rdata(rrset, rr_pos) + 2);
+}
+
+uint8_t knot_rrset_rdata_rrsig_labels(const knot_rrset_t *rrset,
+ size_t rr_pos)
+
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return *(knot_rrset_get_rdata(rrset, rr_pos) + 3);
+}
+
+uint32_t knot_rrset_rdata_rrsig_original_ttl(const knot_rrset_t *rrset,
+ size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(knot_rrset_get_rdata(rrset, rr_pos) + 4);
+}
+
+uint32_t knot_rrset_rdata_rrsig_sig_expiration(const knot_rrset_t *rrset,
+ size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(knot_rrset_get_rdata(rrset, rr_pos) + 8);
+}
+
+uint32_t knot_rrset_rdata_rrsig_sig_inception(const knot_rrset_t *rrset,
+ size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return knot_wire_read_u32(knot_rrset_get_rdata(rrset, rr_pos) + 12);
+}
+
+uint16_t knot_rrset_rdata_rrsig_key_tag(const knot_rrset_t *rrset,
+ size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return knot_wire_read_u16(knot_rrset_get_rdata(rrset, rr_pos) + 16);
+}
+
+const knot_dname_t *knot_rrset_rdata_rrsig_signer_name(const knot_rrset_t *rrset,
+ size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return NULL;
+ }
+
+ const knot_dname_t *dname = NULL;
+ memcpy(&dname, knot_rrset_get_rdata(rrset, rr_pos) + 18,
+ sizeof(knot_dname_t *));
+
+ return dname;
+}
+
+uint16_t knot_rrset_rdata_dnskey_flags(const knot_rrset_t *rrset, size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return knot_wire_read_u16(knot_rrset_get_rdata(rrset, rr_pos));
+}
+
+uint8_t knot_rrset_rdata_dnskey_proto(const knot_rrset_t *rrset, size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return *(knot_rrset_get_rdata(rrset, rr_pos) + 2);
+}
+
+uint8_t knot_rrset_rdata_dnskey_alg(const knot_rrset_t *rrset, size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return *(knot_rrset_get_rdata(rrset, rr_pos) + 3);
+}
+
+void knot_rrset_rdata_dnskey_key(const knot_rrset_t *rrset, size_t rr_pos,
+ uint8_t **key, uint16_t *key_size)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return;
+ }
+
+ *key = knot_rrset_get_rdata(rrset, rr_pos) + 4;
+ *key_size = rrset_rdata_item_size(rrset, rr_pos) - 4;
+}
+
+const knot_dname_t *knot_rrset_rdata_nsec_next(const knot_rrset_t *rrset,
+ size_t rr_pos)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+
+ const knot_dname_t *dname;
+ memcpy(&dname, rrset_rdata_pointer(rrset, rr_pos),
+ sizeof(knot_dname_t *));
+ return dname;
+}
+
+void knot_rrset_rdata_nsec_bitmap(const knot_rrset_t *rrset, size_t rr_pos,
+ uint8_t **bitmap, uint16_t *size)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return;
+ }
+
+ *bitmap = knot_rrset_get_rdata(rrset, rr_pos) + sizeof(knot_dname_t *);
+ *size = rrset_rdata_item_size(rrset, rr_pos) - sizeof(knot_dname_t *);
+}
+
+void knot_rrset_rdata_nsec3_bitmap(const knot_rrset_t *rrset, size_t rr_pos,
+ uint8_t **bitmap, uint16_t *size)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return;
+ }
+
+ /* Bitmap is last, skip all the items. */
+ size_t offset = 1; //hash alg.
+ offset += 1; //flags
+ offset += 2; //iterations
+ offset += 1; //salt lenght
+ offset += knot_rrset_rdata_nsec3_salt_length(rrset, rr_pos); //sal
+ uint8_t *next_hashed = NULL;
+ uint8_t next_hashed_size = 0;
+ knot_rrset_rdata_nsec3_next_hashed(rrset, rr_pos, &next_hashed,
+ &next_hashed_size);
+ offset += 1; //hash length
+ offset += next_hashed_size; //hash
+ *bitmap = knot_rrset_get_rdata(rrset, rr_pos) + offset;
+ *size = rrset_rdata_item_size(rrset, rr_pos) - offset;
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint8_t knot_rrset_rdata_nsec3_algorithm(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return *(rrset_rdata_pointer(rrset, pos));
+}
+
+uint8_t knot_rrset_rdata_nsec3_flags(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return *(rrset_rdata_pointer(rrset, pos) + 1);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint16_t knot_rrset_rdata_nsec3_iterations(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return knot_wire_read_u16(rrset_rdata_pointer(rrset, pos) + 2);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint8_t knot_rrset_rdata_nsec3param_flags(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return *(rrset_rdata_pointer(rrset, 0) + 1);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint8_t knot_rrset_rdata_nsec3param_algorithm(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return *(rrset_rdata_pointer(rrset, 0));
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint16_t knot_rrset_rdata_nsec3param_iterations(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return knot_wire_read_u16(rrset_rdata_pointer(rrset, 0) + 2);
+}
+
+/*---------------------------------------------------------------------------*/
+
+uint8_t knot_rrset_rdata_nsec3param_salt_length(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return 0;
+ }
+
+ return *(rrset_rdata_pointer(rrset, 0) + 4);
+}
+
+/*---------------------------------------------------------------------------*/
+
+const uint8_t *knot_rrset_rdata_nsec3param_salt(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+
+ return rrset_rdata_pointer(rrset, 0) + 5;
+}
+
+/*---------------------------------------------------------------------------*/
+
+
+uint8_t knot_rrset_rdata_nsec3_salt_length(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return 0;
+ }
+
+ return *(rrset_rdata_pointer(rrset, pos) + 4);
+}
+
+void knot_rrset_rdata_nsec3_next_hashed(const knot_rrset_t *rrset, size_t pos,
+ uint8_t **name, uint8_t *name_size)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return;
+ }
+
+ uint8_t salt_size = knot_rrset_rdata_nsec3_salt_length(rrset, pos);
+ *name_size = *(knot_rrset_get_rdata(rrset, pos) + 4 + salt_size + 1);
+ *name = knot_rrset_get_rdata(rrset, pos) + 4 + salt_size + 2;
+}
+
+/*---------------------------------------------------------------------------*/
+
+const uint8_t *knot_rrset_rdata_nsec3_salt(const knot_rrset_t *rrset,
+ size_t pos)
+{
+ if (rrset == NULL || pos >= rrset->rdata_count) {
+ return NULL;
+ }
+
+ return rrset_rdata_pointer(rrset, pos) + 5;
+}
+
+knot_dname_t **knot_rrset_get_next_rr_dname(const knot_rrset_t *rrset,
+ knot_dname_t **prev_dname,
+ size_t rr_pos)
+{
+ if (rrset == NULL || rr_pos >= rrset->rdata_count) {
+ return NULL;
+ }
+
+ uint8_t *rdata = rrset_rdata_pointer(rrset, rr_pos);
+ if (rrset_type_multiple_dnames(rrset)) {
+ if (prev_dname == NULL) {
+ /* The very first DNAME. */
+ /* [code-review] How do you know the dname is the first
+ * item in the RDATA?
*/
- walk2 = knot_rrset_rdata_get_next(rrset2, walk2);
- /* Insert this item at the end of first list. */
- tmp->next = insert_after->next;
- insert_after->next = tmp;
- insert_after = tmp;
- /*!< \todo This message has to be removed after bugfix. */
- dbg_rrset_detail("rrset: merge_no_dupl: Insert after=%p"
- ", tmp=%p, tmp->next=%p, "
- " rrset1->rdata=%p"
- "\n",
- insert_after, tmp, tmp->next,
- rrset1->rdata);
- assert(tmp->next == rrset1->rdata);
+ return (knot_dname_t **)rdata;
+ }
+ assert((size_t)prev_dname >= (size_t)rdata);
+ if ((size_t)prev_dname - (size_t)rdata == sizeof(knot_dname_t *)) {
+ /* No DNAMEs left to return. */
+ return NULL;
} else {
- dbg_rrset_detail("rrset: merge_dupl: Skipping and "
- "freeing duplicated item "
- "of type: %s (%p).\n",
- knot_rrtype_to_string(rrset1->type),
- walk2);
- /*
- * Not freeing this item will result in a leak.
- * Since this operation destroys the second
- * list, we have to free the item here.
- */
- knot_rdata_t *tmp = walk2;
- dbg_rrset_detail("rrset: merge_dupl: freeing: %p.\n",
- tmp);
- walk2 = knot_rrset_rdata_get_next(rrset2, walk2);
- knot_rdata_deep_free(&tmp, rrset1->type, 1);
- assert(tmp == NULL);
- /* Maybe caller should be warned about this. */
- ++deleted;
- }
- }
-
- assert(walk2 == NULL);
+ /* Return second DNAME from RR. */
+ assert((size_t)prev_dname == (size_t)rdata);
+ return (knot_dname_t **)(rdata + sizeof(knot_dname_t *));
+ }
+ } else {
+ /*
+ * Return DNAME from normal RR, if any.
+ * Find DNAME in blocks. No need to check remainder.
+ */
+ if (prev_dname) {
+ /* Nothing left to return. */
+ return NULL;
+ }
+ size_t offset = 0;
+ const rdata_descriptor_t *desc =
+ get_rdata_descriptor(rrset->type);
+ for (int i = 0; desc->block_types[i] != KNOT_RDATA_WF_END; ++i) {
+ if (descriptor_item_is_dname(desc->block_types[i])) {
+ return (knot_dname_t **)(rdata + offset);
+ } else if (descriptor_item_is_fixed(desc->block_types[i])) {
+ offset += desc->block_types[i];
+ } else if (!descriptor_item_is_remainder(desc->block_types[i])) {
+ assert(rrset->type == KNOT_RRTYPE_NAPTR);
+ offset +=
+ rrset_rdata_naptr_bin_chunk_size(rrset,
+ rr_pos);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+knot_dname_t **knot_rrset_get_next_dname(const knot_rrset_t *rrset,
+ knot_dname_t **prev_dname)
+{
+ if (rrset == NULL || rrset->rdata_count == 0) {
+ return NULL;
+ }
+
+ /* 1) Find in which RR is the given dname. */
+ size_t pos = 0;
+ int ret = rrset_find_rr_pos_for_pointer(rrset, prev_dname, &pos);
+ if (ret != KNOT_EOK) {
+ return NULL;
+ }
+
+ /* 2) Try to get next dname from the RR. */
+ knot_dname_t **next =
+ knot_rrset_get_next_rr_dname(rrset, prev_dname, pos);
+
+ /* 3) If not found and there is a next RR to search in, try it. */
+ if (next == NULL && pos < rrset->rdata_count - 1) {
+ // prev_dname = NULL because in this RR we haven't searched yet
+ next = knot_rrset_get_next_rr_dname(rrset, NULL, pos + 1);
+ }
+
+ return next;
+}
+
+void knot_rrset_dump(const knot_rrset_t *rrset)
+{
dbg_rrset_exec_detail(
- dbg_rrset_detail("rrset: merge_dupl: RDATA after merge:\n ");
- knot_rdata_t *walk1 = rrset1->rdata;
- while (walk1 != NULL) {
- dbg_rrset_detail("%p ->\n", walk1);
- walk1 = knot_rrset_rdata_get_next(rrset1, walk1);
- }
- dbg_rrset_detail("rrset: merge_dupl: RDATA after merge: r1:%p r2: %p\n",
- rrset1->rdata, rrset2->rdata);
+ if (rrset == NULL) {
+ return;
+ }
+
+ dbg_rrset_detail(" ------- RRSET -------\n");
+
+ char *name = knot_dname_to_str(rrset->owner);
+ dbg_rrset_detail(" owner: %s\n", name);
+ free(name);
+ dbg_rrset_detail(" type: %u\n", rrset->type);
+ dbg_rrset_detail(" class: %d\n", rrset->rclass);
+ dbg_rrset_detail(" ttl: %d\n", rrset->ttl);
+ dbg_rrset_detail(" RDATA count: %d\n", rrset->rdata_count);
+
+ dbg_rrset_detail(" RRSIGs:\n");
+ if (rrset->rrsigs != NULL) {
+ knot_rrset_dump(rrset->rrsigs);
+ } else {
+ dbg_rrset_detail(" none\n");
+ }
+
+ dbg_rrset_detail("RDATA indices (total=%d):\n",
+ rrset_rdata_size_total(rrset));
+
+ for (uint16_t i = 0; i < rrset->rdata_count; i++) {
+ dbg_rrset_detail("%d=%d ", i, rrset_rdata_offset(rrset, i));
+ }
+ dbg_rrset_detail("\n");
+
+ if (knot_rrset_rdata_rr_count(rrset) == 0) {
+ dbg_rrset_detail("NO RDATA\n");
+ }
+
+ for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rrset); i++) {
+ knot_rrset_rdata_dump(rrset, i);
+ }
);
+}
+
+uint64_t rrset_binary_size(const knot_rrset_t *rrset)
+{
+ if (rrset == NULL || rrset->rdata_count == 0) {
+ return 0;
+ }
+ uint64_t size = sizeof(uint64_t) + // size at the beginning
+ 1 + // owner size
+ knot_dname_size(knot_rrset_owner(rrset)) + // owner data
+ sizeof(uint16_t) + // type
+ sizeof(uint16_t) + // class
+ sizeof(uint32_t) + // ttl
+ sizeof(uint16_t) + //RR count
+ sizeof(uint32_t) * rrset->rdata_count; //RR indices
+ for (uint16_t i = 0; i < rrset->rdata_count; i++) {
+ /* Space to store length of one RR. */
+ size += sizeof(uint32_t);
+ /* Actual data. */
+ size += rrset_binary_size_one(rrset, i);
+ }
+
+ return size;
+}
+
+int rrset_serialize(const knot_rrset_t *rrset, uint8_t *stream, size_t *size)
+{
+ if (rrset == NULL || rrset->rdata_count == 0) {
+ return KNOT_EINVAL;
+ }
+
+ uint64_t rrset_length = rrset_binary_size(rrset);
+ dbg_rrset_detail("rr: serialize: Binary size=%"PRIu64"\n", rrset_length);
+ memcpy(stream, &rrset_length, sizeof(uint64_t));
+
+ size_t offset = sizeof(uint64_t);
+ /* Save RR indices. Size first. */
+ memcpy(stream + offset, &rrset->rdata_count, sizeof(uint16_t));
+ offset += sizeof(uint16_t);
+ memcpy(stream + offset, rrset->rdata_indices,
+ rrset->rdata_count * sizeof(uint32_t));
+ offset += sizeof(uint32_t) * rrset->rdata_count;
+ /* Save owner. Size first. */
+ memcpy(stream + offset, &rrset->owner->size, 1);
+ ++offset;
+ memcpy(stream + offset, knot_dname_name(rrset->owner),
+ knot_dname_size(rrset->owner));
+ offset += knot_dname_size(rrset->owner);
+
+ /* Save static data. */
+ memcpy(stream + offset, &rrset->type, sizeof(uint16_t));
+ offset += sizeof(uint16_t);
+ memcpy(stream + offset, &rrset->rclass, sizeof(uint16_t));
+ offset += sizeof(uint16_t);
+ memcpy(stream + offset, &rrset->ttl, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ /* Copy RDATA. */
+ for (uint16_t i = 0; i < rrset->rdata_count; i++) {
+ size_t size_one = 0;
+ /* This cannot fail, if it does, RDATA are malformed. TODO */
+ /* TODO this can be written later. */
+ uint32_t rr_size = rrset_binary_size_one(rrset, i);
+ dbg_rrset_detail("rr: serialize: RR index=%d size=%d\n",
+ i, rr_size);
+ memcpy(stream + offset, &rr_size, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+ rrset_serialize_rr(rrset, i, stream + offset, &size_one);
+ assert(size_one == rr_size);
+ offset += size_one;
+ }
+
+ *size = offset;
+ assert(*size == rrset_length);
+ dbg_rrset_detail("rr: serialize: RRSet serialized, size=%zu\n", *size);
+ return KNOT_EOK;
+}
+
+int rrset_serialize_alloc(const knot_rrset_t *rrset, uint8_t **stream,
+ size_t *size)
+{
+ /* Get the binary size. */
+ *size = rrset_binary_size(rrset);
+ if (*size == 0) {
+ /* Nothing to serialize. */
+ dbg_rrset("rrset: serialize alloc: No data to serialize.\n");
+ return KNOT_EINVAL;
+ }
+
+ /* Prepare memory. */
+ *stream = malloc(*size);
+ if (*stream == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ return rrset_serialize(rrset, *stream, size);
+}
+
+int rrset_deserialize(uint8_t *stream, size_t *stream_size,
+ knot_rrset_t **rrset)
+{
+ if (sizeof(uint64_t) > *stream_size) {
+ dbg_rrset("rr: deserialize: No space for length.\n");
+ return KNOT_ESPACE;
+ }
+ uint64_t rrset_length = 0;
+ memcpy(&rrset_length, stream, sizeof(uint64_t));
+ if (rrset_length > *stream_size) {
+ dbg_rrset("rr: deserialize: No space for whole RRSet. "
+ "(given=%zu needed=%"PRIu64")\n", *stream_size,
+ rrset_length);
+ return KNOT_ESPACE;
+ }
+
+ size_t offset = sizeof(uint64_t);
+ uint16_t rdata_count = 0;
+ memcpy(&rdata_count, stream + offset, sizeof(uint16_t));
+ offset += sizeof(uint16_t);
+ uint32_t *rdata_indices = xmalloc(rdata_count * sizeof(uint32_t));
+ memcpy(rdata_indices, stream + offset,
+ rdata_count * sizeof(uint32_t));
+ offset += rdata_count * sizeof(uint32_t);
+ /* Read owner from the stream. */
+ uint8_t owner_size = *(stream + offset);
+ offset += 1;
+ knot_dname_t *owner = knot_dname_new_from_wire(stream + offset,
+ owner_size, NULL);
+ assert(owner);
+ offset += owner_size;
+ /* Read type. */
+ uint16_t type = 0;
+ memcpy(&type, stream + offset, sizeof(uint16_t));
+ offset += sizeof(uint16_t);
+ /* Read class. */
+ uint16_t rclass = 0;
+ memcpy(&rclass, stream + offset, sizeof(uint16_t));
+ offset += sizeof(uint16_t);
+ /* Read TTL. */
+ uint32_t ttl = 0;
+ memcpy(&ttl, stream + offset, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ /* Create new RRSet. */
+ *rrset = knot_rrset_new(owner, type, rclass, ttl);
+ if (*rrset == NULL) {
+ return KNOT_ENOMEM;
+ }
+ knot_dname_release(owner);
+
+ (*rrset)->rdata_indices = rdata_indices;
+ (*rrset)->rdata_count = rdata_count;
+
+ (*rrset)->rdata = xmalloc(rdata_indices[rdata_count - 1]);
+ memset((*rrset)->rdata, 0, rdata_indices[rdata_count - 1]);
+ /* Read RRs. */
+ for (uint16_t i = 0; i < (*rrset)->rdata_count; i++) {
+ /*
+ * There's always size of rdata in the beginning.
+ * Needed because of remainders.
+ */
+ uint32_t rdata_size = 0;
+ memcpy(&rdata_size, stream + offset, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+ size_t read = 0;
+ int ret = rrset_deserialize_rr((*rrset), i, stream + offset,
+ rdata_size, &read);
+ if (ret != KNOT_EOK) {
+ free((*rrset)->rdata);
+ free(rdata_indices);
+ knot_dname_release(owner);
+ return ret;
+ }
+ /* TODO handle malformations. */
+ dbg_rrset_detail("rr: deserialaze: RR read size=%zu,"
+ "actual=%"PRIu32"\n", read, rdata_size);
+ assert(read == rdata_size);
+ offset += read;
+ }
+
+dbg_rrset_exec_detail(
+ dbg_rrset_detail("RRSet deserialized:\n");
+ knot_rrset_dump(*rrset);
+);
+ *stream_size = *stream_size - offset;
+
+ return KNOT_EOK;
+}
+
+const knot_dname_t *knot_rrset_rdata_ns_name(const knot_rrset_t *rrset,
+ size_t rdata_pos)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+
+ const knot_dname_t *dname;
+ memcpy(&dname, rrset_rdata_pointer(rrset, rdata_pos),
+ sizeof(knot_dname_t *));
+ return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_mx_name(const knot_rrset_t *rrset,
+ size_t rdata_pos)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+
+ knot_dname_t *dname;
+ memcpy(&dname, rrset_rdata_pointer(rrset, rdata_pos) + 2,
+ sizeof(knot_dname_t *));
+ return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_srv_name(const knot_rrset_t *rrset,
+ size_t rdata_pos)
+{
+ if (rrset == NULL) {
+ return NULL;
+ }
+
+ knot_dname_t *dname;
+ memcpy(&dname, rrset_rdata_pointer(rrset, rdata_pos) + 6,
+ sizeof(knot_dname_t *));
+ return dname;
+}
+
+const knot_dname_t *knot_rrset_rdata_name(const knot_rrset_t *rrset,
+ size_t rdata_pos)
+{
+ if (rrset == NULL || rrset->rdata_count <= rdata_pos) {
+ return NULL;
+ }
+
+ switch (rrset->type) {
+ case KNOT_RRTYPE_NS:
+ return knot_rrset_rdata_ns_name(rrset, rdata_pos);
+ case KNOT_RRTYPE_MX:
+ return knot_rrset_rdata_mx_name(rrset, rdata_pos);
+ case KNOT_RRTYPE_SRV:
+ return knot_rrset_rdata_srv_name(rrset, rdata_pos);
+ case KNOT_RRTYPE_CNAME:
+ return knot_rrset_rdata_cname_name(rrset);
+ }
+
+ return NULL;
+}
+
+int knot_rrset_find_rr_pos(const knot_rrset_t *rr_search_in,
+ const knot_rrset_t *rr_reference, size_t pos,
+ size_t *pos_out)
+{
+ int found = 0;
+ for (uint16_t i = 0; i < rr_search_in->rdata_count && !found; ++i) {
+ if (rrset_rdata_compare_one(rr_search_in,
+ rr_reference, i, pos) == 0) {
+ *pos_out = i;
+ found = 1;
+ }
+ }
+
+ return found ? KNOT_EOK : KNOT_ENOENT;
+}
+
+int knot_rrset_remove_rr(knot_rrset_t *rrset,
+ const knot_rrset_t *rr_from, size_t rdata_pos)
+{
+ /* [code-review] Missing parameter checks. */
/*
- * Since there is a possibility of corrupted list for second RRSet, it
- * is safer to set its list to NULL, so that it cannot be used.
+ * Position in first and second rrset can differ, we have
+ * to search for position first.
*/
- rrset2->rdata = NULL;
+ size_t pos_to_remove = 0;
+ int ret = knot_rrset_find_rr_pos(rrset, rr_from, rdata_pos,
+ &pos_to_remove);
+ if (ret == KNOT_EOK) {
+ /* Position found, can be removed. */
+ dbg_rrset_detail("rr: remove_rr: Counter position found=%zu\n",
+ pos_to_remove);
+ assert(pos_to_remove < rrset->rdata_count);
+ ret = knot_rrset_remove_rdata_pos(rrset, pos_to_remove);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("Cannot remove RDATA from RRSet (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
+ } else {
+ dbg_rrset_verb("rr: remove_rr: RDATA not found (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+ return KNOT_EOK;
+}
+
+int knot_rrset_rdata_reset(knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ rrset->rdata = NULL;
+ rrset->rdata_indices = NULL;
+ rrset->rdata_count = 0;
+
+ return KNOT_EOK;
+}
+
+int rrset_rr_dnames_apply(knot_rrset_t *rrset, size_t rdata_pos,
+ int (*func)(knot_dname_t **, void *), void *data)
+{
+ if (rrset == NULL || rdata_pos >= rrset->rdata_count || func == NULL) {
+ return KNOT_EINVAL;
+ }
+
+
+ knot_dname_t **dname = NULL;
+ while ((dname = knot_rrset_get_next_rr_dname(rrset, dname,
+ rdata_pos))) {
+ assert(dname && *dname);
+ int ret = func(dname, data);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rr: rr_dnames_apply: Function could not be"
+ "applied (%s).\n", knot_strerror(ret));
+ return ret;
+ }
+ }
- return deleted;
+ return KNOT_EOK;
+}
+
+int rrset_dnames_apply(knot_rrset_t *rrset, int (*func)(knot_dname_t **, void *),
+ void *data)
+{
+ if (rrset == NULL || rrset->rdata_count == 0 || func == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ for (uint16_t i = 0; i < rrset->rdata_count; ++i) {
+ int ret = rrset_rr_dnames_apply(rrset, i, func, data);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+ }
+
+ return KNOT_EOK;
+}
+
+int knot_rrset_add_rr_from_rrset(knot_rrset_t *dest, const knot_rrset_t *source,
+ size_t rdata_pos)
+{
+ if (dest == NULL || source == NULL ||
+ rdata_pos >= source->rdata_count) {
+ return KNOT_EINVAL;
+ }
+
+ /* Get size of RDATA to be copied. */
+ uint16_t item_size = rrset_rdata_item_size(source, rdata_pos);
+ /* Reserve space in dest RRSet. */
+ uint8_t *rdata = knot_rrset_create_rdata(dest, item_size);
+ if (rdata == NULL) {
+ dbg_rrset("rr: add_rr_from_rrset: Could not create RDATA.\n");
+ return KNOT_ERROR;
+ }
+
+ /* Copy actual data. */
+ memcpy(rdata, rrset_rdata_pointer(source, rdata_pos), item_size);
+
+ /* Retain DNAMEs inside RDATA. */
+ int ret = rrset_rr_dnames_apply((knot_rrset_t *)source, rdata_pos,
+ rrset_retain_dnames_in_rr, NULL);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("rr: add_rr_from_rrset: Could not retain DNAMEs"
+ " in RR (%s).\n", knot_strerror(ret));
+ return ret;
+ }
+
+ return KNOT_EOK;
+}
+
+int knot_rrset_remove_rr_using_rrset(knot_rrset_t *from,
+ const knot_rrset_t *what,
+ knot_rrset_t **rr_deleted, int ddns_check)
+{
+ /* [code-review] Missing parameter checks. */
+
+ knot_rrset_t *return_rr = NULL;
+ int ret = knot_rrset_shallow_copy(what, &return_rr);
+ if (ret != KNOT_EOK) {
+ dbg_rrset("remove_rr_using_rrset: Could not copy RRSet (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
+ /* Reset RDATA of returned RRSet. */
+ knot_rrset_rdata_reset(return_rr);
+ return_rr->rrsigs = NULL;
+
+ for (uint16_t i = 0; i < what->rdata_count; ++i) {
+ /*
+ * DDNS special handling - last apex NS should remain in the
+ * zone.
+ *
+ * TODO: this is not correct, the last NS from the 'what' RRSet
+ * may not even be in the zone.
+ */
+ //TODO REVIEW LS : relevant?
+ /* [code-review] Hm, it seems OK, but the variable should be
+ * documented, maybe even named differently.
+ * Setting it to 1 means: 'leave the last RR in
+ * the RRSet'. Deciding whether to leave the last
+ * there is on the caller. Thus the assert() is
+ * wrong (it MAY be used in other cases).
+ * Also there can be just break; instead of the
+ * parameter setting and return.
+ */
+ if (ddns_check && i == what->rdata_count - 1) {
+ assert(knot_rrset_type(from) == KNOT_RRTYPE_NS);
+ *rr_deleted = return_rr;
+ return KNOT_EOK;
+ }
+
+ ret = knot_rrset_remove_rr(from, what, i);
+ if (ret == KNOT_EOK) {
+ /* RR was removed, can be added to 'return' RRSet. */
+ ret = knot_rrset_add_rr_from_rrset(return_rr, what, i);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&return_rr, 0, 0);
+ dbg_xfrin("xfr: Could not add RR (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
+ dbg_rrset_detail("rrset: remove_rr_using_rrset: "
+ "Successfuly removed and returned this RR:\n");
+ knot_rrset_rdata_dump(return_rr, return_rr->rdata_count - 1);
+ } else if (ret != KNOT_ENOENT) {
+ /* NOENT is OK, but other errors are not. */
+ dbg_rrset("rrset: remove_using_rrset: "
+ "RRSet removal failed (%s).\n",
+ knot_strerror(ret));
+ knot_rrset_deep_free(&return_rr, 0, 0);
+ return ret;
+ }
+ }
+
+ *rr_deleted = return_rr;
+ return KNOT_EOK;
+}
+
+int knot_rrset_remove_rr_using_rrset_del(knot_rrset_t *from,
+ const knot_rrset_t *what)
+{
+ knot_rrset_t *rr_removed = NULL;
+ int ret = knot_rrset_remove_rr_using_rrset(from, what, &rr_removed, 0);
+ knot_rrset_deep_free(&rr_removed, 1, 1);
+ return ret;
+// for (uint16_t i = 0; i < what->rdata_count; ++i) {
+// int ret = knot_rrset_remove_rr(from, what, i);
+// if (ret != KNOT_ENOENT || ret != KNOT_EOK) {
+// /* NOENT is OK, but other errors are not. */
+// dbg_rrset("rrset: remove_rr_using_rrset: "
+// "RRSet removal failed (%s).\n",
+// knot_strerror(ret));
+// return ret;
+// }
+// }
+
+// return KNOT_EOK;
+}
+
+void knot_rrset_set_class(knot_rrset_t *rrset, uint16_t rclass)
+{
+ if (!rrset) {
+ return;
+ }
+
+ rrset->rclass = rclass;
+}
+
+int knot_rrset_ds_check(const knot_rrset_t *rrset)
+{
+ // Check if the legth of the digest corresponds to the proper size of
+ // the digest according to the given algorithm
+ for (uint16_t i = 0; i < rrset->rdata_count; ++i) {
+ /* 4 bytes before actual digest. */
+ if (rrset_rdata_item_size(rrset, i) < 4) {
+ /* Not even keytag, alg and alg type. */
+ return KNOT_EMALF;
+ }
+ uint16_t len = rrset_rdata_item_size(rrset, i) - 4;
+ uint8_t type = *(rrset_rdata_pointer(rrset, i) + 3);
+ if (type == 0 || len == 0) {
+ return KNOT_EINVAL;
+ } else if (len != knot_ds_digest_length(type)) {
+ return KNOT_EDSDIGESTLEN;
+ }
+ }
+ return KNOT_EOK;
}
diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h
index 077b067..2b0cb6b 100644
--- a/src/libknot/rrset.h
+++ b/src/libknot/rrset.h
@@ -2,6 +2,7 @@
* \file rrset.h
*
* \author Lubos Slovak <lubos.slovak@nic.cz>
+ * \author Jan Kadlec <jan.kadlec@nic.cz>
*
* \brief RRSet structure and API for manipulating it.
*
@@ -30,7 +31,6 @@
#include <stdint.h>
#include "dname.h"
-#include "rdata.h"
/*----------------------------------------------------------------------------*/
/*!
@@ -43,19 +43,25 @@
* program. Distinct Resource Records are thus represented only as distinct
* RDATA sections of corresponding RRs.
*/
+
struct knot_rrset {
/*! \brief Domain name being the owner of the RRSet. */
knot_dname_t *owner;
uint16_t type; /*!< TYPE of the RRset. */
uint16_t rclass; /*!< CLASS of the RRSet. */
uint32_t ttl; /*!< TTL of the RRSet. */
- /*!
- * \brief First item in an ordered cyclic list of RDATA items.
- *
- * \note The fact that the list is cyclic will easily allow for
- * possible round-robin rotation of RRSets.
+
+ /* [code-review] It would be fine to better describe the format of this
+ * array and the meaning of the indices. Maybe even draw some simple
+ * image :-)
+ */
+ uint8_t *rdata; /*!< RDATA array (All RRs). */
+ /*! \brief Beginnings of RRs - first one does not contain 0, last
+ * last one holds total length of all RRs together
*/
- knot_rdata_t *rdata;
+ /* [code-review] Does this have to be 32b integer? Isn't 16b enough? */
+ uint32_t *rdata_indices; /*!< Indices to beginnings of RRs (without 0)*/
+ uint16_t rdata_count; /*!< Count of RRs in this RRSet. */
struct knot_rrset *rrsigs; /*!< Set of RRSIGs covering this RRSet. */
};
@@ -76,6 +82,9 @@ typedef enum {
} knot_rrset_dupl_handling_t;
/*----------------------------------------------------------------------------*/
+
+uint32_t rrset_rdata_size_total(const knot_rrset_t *rrset);
+
/*!
* \brief Creates a new RRSet with the given properties.
*
@@ -97,31 +106,39 @@ knot_rrset_t *knot_rrset_new(knot_dname_t *owner, uint16_t type,
*
* \param rrset RRSet to add the RDATA to.
* \param rdata RDATA to add to the RRSet.
+ * \param size Size of RDATA.
*
- * \retval KNOT_EOK
- * \retval KNOT_EINVAL
- *
- * \todo Provide some function for comparing RDATAs.
+ * \retval KNOT_EINVAL on wrong arguments.
+ * \retval KNOT_EOK on success.
*/
-int knot_rrset_add_rdata(knot_rrset_t *rrset, knot_rdata_t *rdata);
+int knot_rrset_add_rdata(knot_rrset_t *rrset, const uint8_t *rdata,
+ uint16_t size);
/*!
- * \brief Adds the given RDATA to the RRSet but will not insert duplicated data.
- *
- * \warning Should be only used to insert one RDATA. (NO lists)
+ * \brief Creates RDATA memory and returns a pointer to it.
+ * If the RRSet is not empty, function will return a memory
+ * pointing to a beginning of a new RR. (Indices will be handled as well)
*
* \param rrset RRSet to add the RDATA to.
- * \param rdata RDATA to add to the RRSet.
+ * \param size Size of RR RDATA (Size in internal representation)
*
- * \retval KNOT_EOK
- * \retval KNOT_EINVAL
- *
- * \todo Provide some function for comparing RDATAs.
+ * \return Pointer to memory to be written to.
+ * \retval NULL if arguments are invalid
*/
-int knot_rrset_add_rdata_order(knot_rrset_t *rrset, knot_rdata_t *rdata);
+uint8_t* knot_rrset_create_rdata(knot_rrset_t *rrset, const uint16_t size);
-knot_rdata_t * knot_rrset_remove_rdata(knot_rrset_t *rrset,
- const knot_rdata_t *rdata);
+/*!
+ * \brief Returns size of an RR RDATA on a given position.
+ *
+ * \param rrset RRSet holding RR RDATA.
+ * \param pos RR position.
+ *
+ * \retval 0 on error.
+ * \return Item size on success.
+ */
+/* [code-review] Misleading name, maybe remove the word 'item'. */
+uint16_t rrset_rdata_item_size(const knot_rrset_t *rrset,
+ size_t pos);
/*!
* \brief Adds RRSIG signatures to this RRSet.
@@ -134,8 +151,21 @@ knot_rdata_t * knot_rrset_remove_rdata(knot_rrset_t *rrset,
*/
int knot_rrset_set_rrsigs(knot_rrset_t *rrset, knot_rrset_t *rrsigs);
+/*!
+ * \brief Adds RRSIG signatures to this RRSet.
+ *
+ * \param rrset RRSet to add the signatures into.
+ * \param rrsigs Set of RRSIGs covering this RRSet.
+ * \param dupl Merging strategy.
+ *
+ * \retval KNOT_EOK if no merge was needed.
+ * \retval 1 if merge was needed.
+ * \retval 2 if rrsig was not first, but is was skipped.
+ * \retval KNOT_EINVAL on faulty arguments or rrsig does not belong to this rrset.
+ */
+//TODO test
int knot_rrset_add_rrsigs(knot_rrset_t *rrset, knot_rrset_t *rrsigs,
- knot_rrset_dupl_handling_t dupl);
+ knot_rrset_dupl_handling_t dupl);
/*!
* \brief Returns the Owner of the RRSet.
@@ -147,7 +177,11 @@ int knot_rrset_add_rrsigs(knot_rrset_t *rrset, knot_rrset_t *rrsigs,
const knot_dname_t *knot_rrset_owner(const knot_rrset_t *rrset);
/*!
- * \todo Document me.
+ * \brief Returns the Owner of the RRSet.
+ *
+ * \param rrset RRSet to get the Owner of.
+ *
+ * \return Owner of the given RRSet.
*/
knot_dname_t *knot_rrset_get_owner(const knot_rrset_t *rrset);
@@ -161,6 +195,12 @@ knot_dname_t *knot_rrset_get_owner(const knot_rrset_t *rrset);
*/
void knot_rrset_set_owner(knot_rrset_t *rrset, knot_dname_t* owner);
+/*!
+ * \brief Sets rrset TTL to given TTL.
+ *
+ * \param rrset Specified RRSet.
+ * \param ttl New TTL.
+ */
void knot_rrset_set_ttl(knot_rrset_t *rrset, uint32_t ttl);
void knot_rrset_set_class(knot_rrset_t *rrset, uint16_t rclass);
@@ -193,43 +233,24 @@ uint16_t knot_rrset_class(const knot_rrset_t *rrset);
uint32_t knot_rrset_ttl(const knot_rrset_t *rrset);
/*!
- * \brief Returns the first RDATA in the RRSet.
- *
- * RDATAs in a RRSet are stored in a ordered cyclic list.
- *
- * \note If later a round-robin rotation of RRSets is employed, the RDATA
- * returned by this function may not be the first RDATA in canonical
- * order.
+ * \brief Returns RDATA of RR on given position.
*
* \param rrset RRSet to get the RDATA from.
+ * \param rdata_pos Position of RR to get.
*
- * \return First RDATA in the given RRSet.
+ * \retval NULL if no RDATA on rdata_pos exist.
+ * \return Pointer to RDATA on given position if successfull.
*/
-const knot_rdata_t *knot_rrset_rdata(const knot_rrset_t *rrset);
-
-const knot_rdata_t *knot_rrset_rdata_next(const knot_rrset_t *rrset,
- const knot_rdata_t *rdata);
+uint8_t *knot_rrset_get_rdata(const knot_rrset_t *rrset, size_t rdata_pos);
/*!
- * \brief Returns the first RDATA in the RRSet (non-const version).
- *
- * RDATAs in a RRSet are stored in a ordered cyclic list.
+ * \brief Returns the count of RRs in a given RRSet.
*
- * \note If later a round-robin rotation of RRSets is employed, the RDATA
- * returned by this function may not be the first RDATA in canonical
- * order.
+ * \param rrset RRSet to get the RRs count from.
*
- * \param rrset RRSet to get the RDATA from.
- *
- * \return First RDATA in the given RRSet or NULL if there is none or if no
- * rrset was provided (\a rrset is NULL).
+ * \return Count of the RRs in a given RRSet.
*/
-knot_rdata_t *knot_rrset_get_rdata(knot_rrset_t *rrset);
-
-knot_rdata_t *knot_rrset_rdata_get_next(knot_rrset_t *rrset,
- knot_rdata_t *rdata);
-
-int knot_rrset_rdata_rr_count(const knot_rrset_t *rrset);
+uint16_t knot_rrset_rdata_rr_count(const knot_rrset_t *rrset);
/*!
* \brief Returns the set of RRSIGs covering the given RRSet.
@@ -243,33 +264,26 @@ const knot_rrset_t *knot_rrset_rrsigs(const knot_rrset_t *rrset);
knot_rrset_t *knot_rrset_get_rrsigs(knot_rrset_t *rrset);
-int knot_rrset_compare_rdata(const knot_rrset_t *r1, const knot_rrset_t *r2);
-
-int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, size_t *size,
- int *rr_count);
+int knot_rrset_rdata_equal(const knot_rrset_t *r1, const knot_rrset_t *r2);
/*!
- * \brief Compares two RRSets.
- *
- * \note This function does not return 'standard' compare return values, because
- * there is no way to define which RRSet is 'larger'.
+ * \brief Compares two RRSets for equality.
*
* \param r1 First RRSet.
* \param r2 Second RRSet.
* \param cmp Type of comparison to perform.
*
- * \retval <> 0 If RRSets are equal.
+ * \retval 1 if RRSets are equal.
* \retval 0 if RRSets are not equal.
+ * \retval < 0 if error occured.
*/
-int knot_rrset_match(const knot_rrset_t *r1,
- const knot_rrset_t *r2,
- knot_rrset_compare_type_t cmp);
+int knot_rrset_equal(const knot_rrset_t *r1,
+ const knot_rrset_t *r2,
+ knot_rrset_compare_type_t cmp);
-/*! \todo Add unit test. */
int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to,
int copy_rdata_dnames);
-/*! \todo Add unit test. */
int knot_rrset_shallow_copy(const knot_rrset_t *from, knot_rrset_t **to);
/*! \brief Does round-robin rotation of the RRSet.
@@ -302,13 +316,18 @@ void knot_rrset_free(knot_rrset_t **rrset);
* \param rrset RRset to be destroyed.
* \param free_owner Set to 0 if you do not want the owner domain name to be
* destroyed also. Set to <> 0 otherwise.
- * \param free_rdata ***\todo DOCUMENT ME***
* \param free_rdata_dnames Set to <> 0 if you want to delete ALL domain names
* present in RDATA. Set to 0 otherwise. (See
* knot_rdata_deep_free().)
*/
void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
- int free_rdata, int free_rdata_dnames);
+ int free_rdata_dnames);
+
+void knot_rrset_deep_free_no_sig(knot_rrset_t **rrset, int free_owner,
+ int free_rdata_dnames);
+
+int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, size_t *size,
+ size_t max_size, uint16_t *rr_count, void *comp_data);
/*!
* \brief Merges two RRSets.
@@ -327,18 +346,11 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
* \retval KNOT_EINVAL if the RRSets could not be merged, because their
* Owner, Type, Class or TTL does not match.
*/
-int knot_rrset_merge(void **r1, void **r2);
+int knot_rrset_merge(knot_rrset_t *rrset1, const knot_rrset_t *rrset2);
/*!
- * \brief Merges two RRSets, but will discard and free any duplicates in \a r2.
- *
- * Merges \a r1 into \a r2 by concatenating the list of RDATAs in \a r2 after
- * the list of RDATAs in \a r1. You must not
- * destroy the RDATAs in \a r2 as they are now identical to RDATAs in \a r1.
- * (You may use function knot_rrset_free() though, as it does not touch RDATAs).
- *
- * \note Member \a rrsigs is preserved from the first RRSet.
+ * \brief Merges two RRSets, but will only merge unique items.
*
* \param r1 Pointer to RRSet to be merged into.
* \param r2 Poitner to RRSet to be merged.
@@ -346,11 +358,183 @@ int knot_rrset_merge(void **r1, void **r2);
* \retval KNOT_EOK
* \retval KNOT_EINVAL if the RRSets could not be merged, because their
* Owner, Type, Class or TTL does not match.
- * \retval >0 if some RDATA have been removed because they were duplicate. The
- * return value indicates number of such RDATA.
*/
-int knot_rrset_merge_no_dupl(void **r1, void **r2);
+int knot_rrset_merge_no_dupl(knot_rrset_t *rrset1, const knot_rrset_t *rrset2, int *merged, int *deleted_rrs);
+
+
+//TODO test
+const knot_dname_t *knot_rrset_rdata_cname_name(const knot_rrset_t *rrset);
+//TODO test
+const knot_dname_t *knot_rrset_rdata_dname_target(const knot_rrset_t *rrset);
+//TODO test
+void knot_rrset_rdata_set_cname_name(knot_rrset_t *rrset,
+ const knot_dname_t *name);
+//TODO test
+void knot_rrset_rdata_set_dname_target(knot_rrset_t *rrset,
+ const knot_dname_t *target);
+//TODO test
+const knot_dname_t *knot_rrset_rdata_soa_primary_ns(const knot_rrset_t *rrset);
+//TODO test
+const knot_dname_t *knot_rrset_rdata_soa_mailbox(const knot_rrset_t *rrset);
+uint32_t knot_rrset_rdata_soa_serial(const knot_rrset_t *rrset);
+//TODO test
+void knot_rrset_rdata_soa_serial_set(knot_rrset_t *rrset, uint32_t serial);
+//TODO test
+uint32_t knot_rrset_rdata_soa_refresh(const knot_rrset_t *rrset);
+//TODO test
+uint32_t knot_rrset_rdata_soa_retry(const knot_rrset_t *rrset);
+//TODO test
+uint32_t knot_rrset_rdata_soa_expire(const knot_rrset_t *rrset);
+//TODO test
+uint32_t knot_rrset_rdata_soa_minimum(const knot_rrset_t *rrset);
+//TODO test
+uint16_t knot_rrset_rdata_rrsig_type_covered(const knot_rrset_t *rrset);
+/* TODO not all of these need to have rr_pos as a parameter. */
+uint8_t knot_rrset_rdata_rrsig_algorithm(const knot_rrset_t *rrset,
+ size_t rr_pos);
+uint8_t knot_rrset_rdata_rrsig_labels(const knot_rrset_t *rrset, size_t rr_pos);
+uint32_t knot_rrset_rdata_rrsig_original_ttl(const knot_rrset_t *rrset,
+ size_t rr_pos);
+uint32_t knot_rrset_rdata_rrsig_sig_expiration(const knot_rrset_t *rrset,
+ size_t rr_pos);
+uint32_t knot_rrset_rdata_rrsig_sig_inception(const knot_rrset_t *rrset,
+ size_t rr_pos);
+uint16_t knot_rrset_rdata_rrsig_key_tag(const knot_rrset_t *rrset,
+ size_t rr_pos);
+const knot_dname_t *knot_rrset_rdata_rrsig_signer_name(const knot_rrset_t *rrset,
+ size_t rr_pos);
+
+uint16_t knot_rrset_rdata_dnskey_flags(const knot_rrset_t *rrset, size_t rr_pos);
+uint8_t knot_rrset_rdata_dnskey_proto(const knot_rrset_t *rrset, size_t rr_pos);
+uint8_t knot_rrset_rdata_dnskey_alg(const knot_rrset_t *rrset, size_t rr_pos);
+void knot_rrset_rdata_dnskey_key(const knot_rrset_t *rrset, size_t rr_pos,
+ uint8_t **key, uint16_t *key_size);
+const knot_dname_t *knot_rrset_rdata_nsec_next(const knot_rrset_t *rrset,
+ size_t rr_pos);
+void knot_rrset_rdata_nsec_bitmap(const knot_rrset_t *rrset, size_t rr_pos,
+ uint8_t **bitmap, uint16_t *size);
+
+void knot_rrset_rdata_nsec3_bitmap(const knot_rrset_t *rrset, size_t rr_pos,
+ uint8_t **bitmap, uint16_t *size);
+//TODO test
+uint8_t knot_rrset_rdata_nsec3_algorithm(const knot_rrset_t *rrset,
+ size_t pos);
+uint8_t knot_rrset_rdata_nsec3_flags(const knot_rrset_t *rrset,
+ size_t pos);
+//TODO test
+uint16_t knot_rrset_rdata_nsec3_iterations(const knot_rrset_t *rrset,
+ size_t pos);
+//TODO test
+uint8_t knot_rrset_rdata_nsec3_salt_length(const knot_rrset_t *rrset,
+ size_t pos);
+// TODO same as salt, size and data
+void knot_rrset_rdata_nsec3_next_hashed(const knot_rrset_t *rrset, size_t pos,
+ uint8_t **name, uint8_t *name_size);
+//TODO test
+const uint8_t *knot_rrset_rdata_nsec3_salt(const knot_rrset_t *rrset,
+ size_t pos);
+//TODO test
+uint8_t knot_rrset_rdata_nsec3param_algorithm(const knot_rrset_t *rrset);
+//TODO test
+uint8_t knot_rrset_rdata_nsec3param_flags(const knot_rrset_t *rrset);
+//TODO test
+uint16_t knot_rrset_rdata_nsec3param_iterations(const knot_rrset_t *rrset);
+//TODO test
+uint8_t knot_rrset_rdata_nsec3param_salt_length(const knot_rrset_t *rrset);
+//TODO test
+const uint8_t *knot_rrset_rdata_nsec3param_salt(const knot_rrset_t *rrset);
+
+const knot_dname_t *knot_rrset_rdata_rp_first_dname(const knot_rrset_t *rrset,
+ size_t pos);
+const knot_dname_t *knot_rrset_rdata_rp_second_dname(const knot_rrset_t *rrset,
+ size_t pos);
+const knot_dname_t *knot_rrset_rdata_minfo_first_dname(const knot_rrset_t *rrset,
+ size_t pos);
+const knot_dname_t *knot_rrset_rdata_minfo_second_dname(const knot_rrset_t *rrset,
+ size_t pos);
+
+/*!
+ * \brief Find next dname in rrset relative to prev.
+ *
+ * \param rrset Inspected rrset.
+ * \param prev_dname Pointer to previous dname.
+ * \return next dname or NULL.
+ */
+/* [code-review] Emphasize that the 'prev' pointer must point into the RDATA
+ * array of the given RRSet.
+ */
+knot_dname_t **knot_rrset_get_next_dname(const knot_rrset_t *rrset,
+ knot_dname_t **prev);
+
+/*!
+ * \brief Find next dname in RR relative to previous one.
+ *
+ * \param rrset Inspected rrset.
+ * \param prev_dname Previous dname. This must be a pointer to the rrset's
+ * RDATA array.
+ * \param rr_pos Position of RR.
+ * \return Next dname or NULL if there is no other dname in the RR.
+ */
+knot_dname_t **knot_rrset_get_next_rr_dname(const knot_rrset_t *rrset,
+ knot_dname_t **prev_dname,
+ size_t rr_pos);
+
+const knot_dname_t *knot_rrset_rdata_ns_name(const knot_rrset_t *rrset,
+ size_t rdata_pos);
+
+const knot_dname_t *knot_rrset_rdata_mx_name(const knot_rrset_t *rrset,
+ size_t rdata_pos);
+
+const knot_dname_t *knot_rrset_rdata_srv_name(const knot_rrset_t *rrset,
+ size_t rdata_pos);
+
+const knot_dname_t *knot_rrset_rdata_name(const knot_rrset_t *rrset,
+ size_t rdata_pos);
+
+void knot_rrset_dump(const knot_rrset_t *rrset);
+
+//TODO test
+int rrset_serialize(const knot_rrset_t *rrset, uint8_t *stream, size_t *size);
+uint64_t rrset_binary_size(const knot_rrset_t *rrset);
+
+//TODO test
+int rrset_serialize_alloc(const knot_rrset_t *rrset, uint8_t **stream,
+ size_t *size);
+
+//TODO test
+int rrset_deserialize(uint8_t *stream, size_t *stream_size,
+ knot_rrset_t **rrset);
+
+int knot_rrset_remove_rr(knot_rrset_t *dest,
+ const knot_rrset_t *source, size_t rdata_pos);
+
+int knot_rrset_rdata_reset(knot_rrset_t *rrset);
+
+int knot_rrset_add_rr_from_rrset(knot_rrset_t *dest, const knot_rrset_t *source,
+ size_t rdata_pos);
+
+int knot_rrset_remove_rr_using_rrset(knot_rrset_t *from,
+ const knot_rrset_t *what,
+ knot_rrset_t **rr_deleted, int ddns_check);
+
+int knot_rrset_remove_rr_using_rrset_del(knot_rrset_t *from,
+ const knot_rrset_t *what);
+
+int knot_rrset_find_rr_pos(const knot_rrset_t *rr_search_in,
+ const knot_rrset_t *rr_reference, size_t pos,
+ size_t *pos_out);
+
+int rrset_rr_dnames_apply(knot_rrset_t *rrset, size_t rdata_pos,
+ int (*func)(knot_dname_t **, void *), void *data);
+
+int rrset_dnames_apply(knot_rrset_t *rrset, int (*func)(knot_dname_t **, void *),
+ void *data);
+
+int knot_rrset_rdata_from_wire_one(knot_rrset_t *rrset,
+ const uint8_t *wire, size_t *pos,
+ size_t total_size, size_t rdlength);
+int knot_rrset_ds_check(const knot_rrset_t *rrset);
#endif /* _KNOT_RRSET_H_ */
/*! @} */
diff --git a/src/libknot/sign/bnutils.c b/src/libknot/sign/bnutils.c
new file mode 100644
index 0000000..c328f44
--- /dev/null
+++ b/src/libknot/sign/bnutils.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "sign/bnutils.h"
+#include "common/base64.h"
+
+/*!
+ * \brief Convert Base64 encoded number into OpenSSL BIGNUM format.
+ */
+BIGNUM *knot_b64_to_bignum(const char *input)
+{
+ size_t size = strlen(input);
+ uint8_t *decoded;
+ int32_t decoded_size;
+ BIGNUM *result;
+
+ decoded_size = base64_decode_alloc((uint8_t *)input, size, &decoded);
+ if (decoded_size < 0) {
+ return NULL;
+ }
+
+ result = BN_bin2bn((unsigned char *)decoded, (int)decoded_size, NULL);
+ free(decoded);
+
+ return result;
+}
diff --git a/src/libknot/sign/bnutils.h b/src/libknot/sign/bnutils.h
new file mode 100644
index 0000000..6eedb69
--- /dev/null
+++ b/src/libknot/sign/bnutils.h
@@ -0,0 +1,42 @@
+/* Copyright (C) 2011 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 bnutils.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief Conversion between Base64 and OpenSSL BIGNUM formats.
+ *
+ * \addtogroup dnssec
+ * @{
+ */
+
+#ifndef _KNOT_SIGN_BNUTILS_H_
+#define _KNOT_SIGN_BNUTILS_H_
+
+#include <openssl/bn.h>
+
+/*!
+ * \brief Convert Base64 encoded number into OpenSSL BIGNUM format.
+ *
+ * \param input Base64 encoded input number
+ * \return Input number represented in OpenSSL BIGNUM format.
+ */
+BIGNUM *knot_b64_to_bignum(const char *input);
+
+#endif // _KNOT_SIGN_BNUTILS_H_
+
+/*! @} */
diff --git a/src/libknot/sign/dnssec.c b/src/libknot/sign/dnssec.c
new file mode 100644
index 0000000..ed9a652
--- /dev/null
+++ b/src/libknot/sign/dnssec.c
@@ -0,0 +1,756 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "common.h"
+#include "common/descriptor.h"
+#include "common/errcode.h"
+#include "sign/bnutils.h"
+#include "sign/dnssec.h"
+#include "sign/key.h"
+#include <assert.h>
+#include <openssl/dsa.h>
+#include <openssl/opensslconf.h>
+#ifndef OPENSSL_NO_ECDSA
+#include <openssl/ecdsa.h>
+#endif
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+
+struct algorithm_functions;
+typedef struct algorithm_functions algorithm_functions_t;
+
+//! \brief Algorithm private key data and algorithm implementation.
+struct knot_dnssec_key_data {
+ const algorithm_functions_t *functions; //!< Implementation specific.
+ EVP_PKEY *private_key; //!< Private key.
+};
+
+//! \brief DNSSEC signature contextual data.
+struct knot_dnssec_sign_context {
+ const knot_dnssec_key_t *key; //!< Associated key.
+ EVP_MD_CTX *digest_context; //!< Digest computation context.
+};
+
+/*!
+ * \brief Algorithm implementation specific functions.
+ */
+struct algorithm_functions {
+ //! \brief Callback: create private key from key parameters.
+ int (*create_pkey)(const knot_key_params_t *, EVP_PKEY *);
+ //! \brief Callback: get signature size in bytes.
+ size_t (*sign_size)(const knot_dnssec_key_t *);
+ //! \brief Callback: cover supplied data with the signature.
+ int (*sign_add)(const knot_dnssec_sign_context_t *, const uint8_t *, size_t);
+ //! \brief Callback: finish the signing and write out the signature.
+ int (*sign_write)(const knot_dnssec_sign_context_t *, uint8_t *);
+};
+
+/*- Algorithm independent ----------------------------------------------------*/
+
+/*!
+ * \brief Get size of the resulting signature.
+ *
+ * \param key DNSSEC key.
+ *
+ * \return Signature size in bytes.
+ */
+static size_t any_sign_size(const knot_dnssec_key_t *key)
+{
+ assert(key);
+
+ return (size_t)EVP_PKEY_size(key->data->private_key);
+}
+
+/*!
+ * \brief Add data to be covered by the signature.
+ *
+ * \param context DNSSEC signature context.
+ * \param data Data to be signed.
+ * \param data_size Size of the data to be signed.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int any_sign_add(const knot_dnssec_sign_context_t *context,
+ const uint8_t *data, size_t data_size)
+{
+ assert(context);
+ assert(data);
+
+ if (!EVP_SignUpdate(context->digest_context, data, data_size))
+ return KNOT_DNSSEC_ESIGN;
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Finish the signing and get the RAW signature.
+ *
+ * Caller should free the memory returned via signature parameter.
+ *
+ * \param context DNSSEC signature context.
+ * \param signature Pointer to signature (output).
+ * \param signature_size Signature size (output).
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int any_sign_finish(const knot_dnssec_sign_context_t *context,
+ uint8_t **signature, size_t *signature_size)
+{
+ assert(context);
+ assert(signature);
+ assert(signature_size);
+
+ size_t max_size = (size_t)EVP_PKEY_size(context->key->data->private_key);
+ uint8_t *output = calloc(1, max_size);
+ if (!output)
+ return KNOT_ENOMEM;
+
+ unsigned int actual_size;
+ int result = EVP_SignFinal(context->digest_context, output,
+ &actual_size, context->key->data->private_key);
+ if (!result) {
+ free(output);
+ return KNOT_DNSSEC_ESIGN;
+ }
+
+ assert(actual_size <= max_size);
+
+ *signature = output;
+ *signature_size = actual_size;
+
+ return KNOT_EOK;
+}
+
+/*- RSA specific -------------------------------------------------------------*/
+
+/*!
+ * \brief Create RSA private key from key parameters.
+ *
+ * \param params Key parameters.
+ * \param key Output private key.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int rsa_create_pkey(const knot_key_params_t *params, EVP_PKEY *key)
+{
+ assert(key);
+
+ RSA *rsa = RSA_new();
+ if (rsa == NULL)
+ return KNOT_ENOMEM;
+
+ rsa->n = knot_b64_to_bignum(params->modulus);
+ rsa->e = knot_b64_to_bignum(params->public_exponent);
+ rsa->d = knot_b64_to_bignum(params->private_exponent);
+ rsa->p = knot_b64_to_bignum(params->prime_one);
+ rsa->q = knot_b64_to_bignum(params->prime_two);
+ rsa->dmp1 = knot_b64_to_bignum(params->exponent_one);
+ rsa->dmq1 = knot_b64_to_bignum(params->exponent_two);
+ rsa->iqmp = knot_b64_to_bignum(params->coefficient);
+
+ if (RSA_check_key(rsa) != 1) {
+ RSA_free(rsa);
+ return KNOT_DNSSEC_EINVALID_KEY;
+ }
+
+ if (!EVP_PKEY_assign_RSA(key, rsa)) {
+ RSA_free(rsa);
+ return KNOT_DNSSEC_EASSIGN_KEY;
+ }
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Finish the signing and write out the RSA signature.
+ *
+ * \param context DNSSEC signing context.
+ * \param signature Pointer to memory where the signature will be written.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int rsa_sign_write(const knot_dnssec_sign_context_t *context,
+ uint8_t *signature)
+{
+ assert(context);
+ assert(signature);
+
+ int result;
+ uint8_t *raw_signature;
+ size_t raw_signature_size;
+ const knot_dnssec_key_t *key = context->key;
+
+ result = any_sign_finish(context, &raw_signature, &raw_signature_size);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ if (raw_signature_size != key->data->functions->sign_size(key)) {
+ free(raw_signature);
+ return KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE;
+ }
+
+ memcpy(signature, raw_signature, raw_signature_size);
+ free(raw_signature);
+
+ return KNOT_EOK;
+}
+
+/*- DSA specific -------------------------------------------------------------*/
+
+/*!
+ * \brief Create DSA private key from key parameters.
+ * \see rsa_create_pkey
+ */
+static int dsa_create_pkey(const knot_key_params_t *params, EVP_PKEY *key)
+{
+ assert(key);
+
+ DSA *dsa = DSA_new();
+ if (dsa == NULL)
+ return KNOT_ENOMEM;
+
+ dsa->p = knot_b64_to_bignum(params->prime);
+ dsa->q = knot_b64_to_bignum(params->subprime);
+ dsa->g = knot_b64_to_bignum(params->base);
+ dsa->priv_key = knot_b64_to_bignum(params->private_value);
+ dsa->pub_key = knot_b64_to_bignum(params->public_value);
+
+ if (!EVP_PKEY_assign_DSA(key, dsa)) {
+ DSA_free(dsa);
+ return KNOT_DNSSEC_EASSIGN_KEY;
+ }
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Get size of the resulting signature for DSA algorithm.
+ * \see any_sign_size
+ */
+static size_t dsa_sign_size(const knot_dnssec_key_t *key)
+{
+ UNUSED(key);
+ // RFC 2536 (section 3 - DSA SIG Resource Record)
+ return 41;
+}
+
+/*!
+ * \brief Finish the signing and write out the DSA signature.
+ * \see rsa_sign_write
+ */
+static int dsa_sign_write(const knot_dnssec_sign_context_t *context,
+ uint8_t *signature)
+{
+ assert(context);
+ assert(signature);
+
+ int result;
+ uint8_t *raw_signature;
+ size_t raw_signature_size;
+
+ result = any_sign_finish(context, &raw_signature, &raw_signature_size);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ // decode signature, X.509 Dss-Sig-Value (RFC2459)
+
+ DSA_SIG *decoded = DSA_SIG_new();
+ if (!decoded) {
+ free(raw_signature);
+ return KNOT_ENOMEM;
+ }
+
+ const uint8_t *decode_scan = raw_signature;
+ if (!d2i_DSA_SIG(&decoded, &decode_scan, (long)raw_signature_size)) {
+ DSA_SIG_free(decoded);
+ free(raw_signature);
+ return KNOT_DNSSEC_EDECODE_RAW_SIGNATURE;
+ }
+
+ free(raw_signature);
+
+ // convert to format defined by RFC 2536 (DSA keys and SIGs in DNS)
+
+ // T (1 byte), R (20 bytes), S (20 bytes)
+ uint8_t *signature_t = signature;
+ uint8_t *signature_r = signature + 21 - BN_num_bytes(decoded->r);
+ uint8_t *signature_s = signature + 41 - BN_num_bytes(decoded->s);
+
+ *signature_t = 0x00; //! \todo How to compute T? (Only recommended.)
+ BN_bn2bin(decoded->r, signature_r);
+ BN_bn2bin(decoded->s, signature_s);
+
+ DSA_SIG_free(decoded);
+
+ return KNOT_EOK;
+}
+
+/*- EC specific --------------------------------------------------------------*/
+
+#ifndef OPENSSL_NO_ECDSA
+
+/*!
+ * \brief Create ECDSA private key from key parameters.
+ * \see rsa_create_pkey
+ */
+static int ecdsa_create_pkey(const knot_key_params_t *params, EVP_PKEY *key)
+{
+ assert(key);
+
+ int curve;
+ if (params->algorithm == KNOT_DNSSEC_ALG_ECDSAP256SHA256) {
+ curve = NID_X9_62_prime256v1; // == secp256r1
+ } else if (params->algorithm == KNOT_DNSSEC_ALG_ECDSAP384SHA384) {
+ curve = NID_secp384r1;
+ } else {
+ return KNOT_DNSSEC_ENOTSUP;
+ }
+
+ EC_KEY *ec_key = EC_KEY_new_by_curve_name(curve);
+ if (ec_key == NULL)
+ return KNOT_ENOMEM;
+
+ EC_KEY_set_private_key(ec_key, knot_b64_to_bignum(params->private_key));
+
+ // EC_KEY_check_key() could be added, but fails without public key
+
+ if (!EVP_PKEY_assign_EC_KEY(key, ec_key)) {
+ EC_KEY_free(ec_key);
+ return KNOT_DNSSEC_EASSIGN_KEY;
+ }
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Get size of the resulting signature for ECDSA algorithm.
+ * \see any_sign_size
+ */
+static size_t ecdsa_sign_size(const knot_dnssec_key_t *key)
+{
+ assert(key);
+
+ // RFC 6605 (section 4 - DNSKEY and RRSIG Resource Records for ECDSA)
+
+ switch (key->algorithm) {
+ case KNOT_DNSSEC_ALG_ECDSAP256SHA256:
+ return 2 * 32;
+ case KNOT_DNSSEC_ALG_ECDSAP384SHA384:
+ return 2 * 48;
+ default:
+ assert(0);
+ return 0;
+ }
+}
+
+/*!
+ * \brief Finish the signing and write out the ECDSA signature.
+ * \see rsa_sign_write
+ */
+static int ecdsa_sign_write(const knot_dnssec_sign_context_t *context,
+ uint8_t *signature)
+{
+ assert(context);
+ assert(signature);
+
+ int result;
+ uint8_t *raw_signature;
+ size_t raw_signature_size;
+
+ result = any_sign_finish(context, &raw_signature, &raw_signature_size);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ // decode signature
+
+ ECDSA_SIG *decoded = ECDSA_SIG_new();
+ if (!decoded) {
+ free(raw_signature);
+ return KNOT_ENOMEM;
+ }
+
+ const uint8_t *decode_scan = raw_signature;
+ if (!d2i_ECDSA_SIG(&decoded, &decode_scan, (long)raw_signature_size)) {
+ ECDSA_SIG_free(decoded);
+ free(raw_signature);
+ return KNOT_DNSSEC_EDECODE_RAW_SIGNATURE;
+ }
+
+ free(raw_signature);
+
+ // convert to format defined by RFC 6605 (EC DSA for DNSSEC)
+ // R and S parameters are encoded in halves of the output signature
+
+ uint8_t *signature_r;
+ uint8_t *signature_s;
+ size_t param_size = ecdsa_sign_size(context->key) / 2;
+
+ signature_r = signature + param_size - BN_num_bytes(decoded->r);
+ signature_s = signature + 2 * param_size - BN_num_bytes(decoded->s);
+
+ BN_bn2bin(decoded->r, signature_r);
+ BN_bn2bin(decoded->s, signature_s);
+
+ ECDSA_SIG_free(decoded);
+
+ return KNOT_EOK;
+}
+
+#endif
+
+/*- Algorithm specifications -------------------------------------------------*/
+
+static const algorithm_functions_t rsa_functions = {
+ rsa_create_pkey,
+ any_sign_size,
+ any_sign_add,
+ rsa_sign_write
+};
+
+static const algorithm_functions_t dsa_functions = {
+ dsa_create_pkey,
+ dsa_sign_size,
+ any_sign_add,
+ dsa_sign_write
+};
+
+#ifndef OPENSSL_NO_ECDSA
+static const algorithm_functions_t ecdsa_functions = {
+ ecdsa_create_pkey,
+ ecdsa_sign_size,
+ any_sign_add,
+ ecdsa_sign_write
+};
+#endif
+
+/*!
+ * \brief Get implementation specific callbacks for a given algorithm.
+ *
+ * \param algorithm Algorithm number.
+ *
+ * \return Pointer to structure with functions, NULL if not implemented.
+ */
+static const algorithm_functions_t *get_implementation(int algorithm)
+{
+ switch (algorithm) {
+ case KNOT_DNSSEC_ALG_RSAMD5:
+ case KNOT_DNSSEC_ALG_RSASHA1:
+ case KNOT_DNSSEC_ALG_RSASHA1_NSEC3_SHA1:
+ case KNOT_DNSSEC_ALG_RSASHA256:
+ case KNOT_DNSSEC_ALG_RSASHA512:
+ return &rsa_functions;
+ case KNOT_DNSSEC_ALG_DSA:
+ case KNOT_DNSSEC_ALG_DSA_NSEC3_SHA1:
+ return &dsa_functions;
+ case KNOT_DNSSEC_ALG_ECDSAP256SHA256:
+ case KNOT_DNSSEC_ALG_ECDSAP384SHA384:
+#ifndef OPENSSL_NO_ECDSA
+ return &ecdsa_functions;
+#endif
+ default:
+ return NULL;
+ }
+}
+
+/*!
+ * \brief Get message digest type for a given algorithm.
+ *
+ * \param algorithm Algorithm number.
+ *
+ * \return Pointer to digest type specification, NULL if not implemented.
+ */
+static const EVP_MD *get_digest_type(knot_dnssec_algorithm_t algorithm)
+{
+ // EVP_<digest>() functions should not fail (return NULL)
+
+ switch (algorithm) {
+ case KNOT_DNSSEC_ALG_RSASHA1:
+ case KNOT_DNSSEC_ALG_RSASHA1_NSEC3_SHA1:
+ case KNOT_DNSSEC_ALG_DSA:
+ case KNOT_DNSSEC_ALG_DSA_NSEC3_SHA1:
+ return EVP_sha1();
+ case KNOT_DNSSEC_ALG_RSAMD5:
+ return EVP_md5();
+ case KNOT_DNSSEC_ALG_RSASHA256:
+ case KNOT_DNSSEC_ALG_ECDSAP256SHA256:
+ return EVP_sha256();
+ case KNOT_DNSSEC_ALG_ECDSAP384SHA384:
+ return EVP_sha384();
+ case KNOT_DNSSEC_ALG_RSASHA512:
+ return EVP_sha512();
+ default:
+ return NULL;
+ }
+}
+
+/*- Internal init/clean functions --------------------------------------------*/
+
+/*!
+ * \brief Create private key.
+ *
+ * \param params Key parameters.
+ * \param functions Algorithm specific callbacks.
+ * \param result_key Output private key.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int create_pkey(const knot_key_params_t *params,
+ const algorithm_functions_t *functions,
+ EVP_PKEY **result_key)
+{
+ assert(result_key);
+
+ EVP_PKEY *private_key = EVP_PKEY_new();
+ if (!private_key)
+ return KNOT_ENOMEM;
+
+ int result = functions->create_pkey(params, private_key);
+ if (result != KNOT_EOK) {
+ EVP_PKEY_free(private_key);
+ return result;
+ }
+
+ *result_key = private_key;
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Create message digest context.
+ *
+ * \param key DNSSEC key.
+ * \param result_context Output message digest context.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int create_digest_context(const knot_dnssec_key_t *key,
+ EVP_MD_CTX **result_context)
+{
+ assert(result_context);
+
+ const EVP_MD *digest_type = get_digest_type(key->algorithm);
+ if (digest_type == NULL)
+ return KNOT_DNSSEC_ENOTSUP;
+
+ EVP_MD_CTX *context = EVP_MD_CTX_create();
+ if (!context)
+ return KNOT_ENOMEM;
+
+ if (!EVP_SignInit_ex(context, digest_type, NULL)) {
+ EVP_MD_CTX_destroy(context);
+ return KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT;
+ }
+
+ *result_context = context;
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Destroy message digest context.
+ *
+ * \param context Context to be freed.
+ *
+ * \return Always KNOT_EOK.
+ */
+static int destroy_digest_context(EVP_MD_CTX **context)
+{
+ assert(context);
+
+ if (*context) {
+ EVP_MD_CTX_destroy(*context);
+ *context = NULL;
+ }
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Free algorithm data.
+ *
+ * \param data Algorithm context.
+ *
+ * \return Error code, always KNOT_EOK.
+ */
+static int clean_algorithm_data(knot_dnssec_key_data_t *data)
+{
+ assert(data);
+
+ if (data->private_key) {
+ EVP_PKEY_free(data->private_key);
+ data->private_key = NULL;
+ }
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Initialize algorithm data.
+ *
+ * \param params Key parameters.
+ * \param data Algorithm context to be initialized.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int init_algorithm_data(const knot_key_params_t *params,
+ knot_dnssec_key_data_t *data)
+{
+ assert(params);
+ assert(data);
+
+ data->functions = get_implementation(params->algorithm);
+ if (!data->functions)
+ return KNOT_DNSSEC_ENOTSUP;
+
+ int result = create_pkey(params, data->functions, &data->private_key);
+ if (result != KNOT_EOK) {
+ clean_algorithm_data(data);
+ return result;
+ }
+
+ return KNOT_EOK;
+}
+
+/*- Public init/clean functions ----------------------------------------------*/
+
+/*!
+ * \brief Fill DNSSEC key structure according to key parameters.
+ */
+int knot_dnssec_key_from_params(const knot_key_params_t *params,
+ knot_dnssec_key_t *key)
+{
+ if (!key || !params)
+ return KNOT_EINVAL;
+
+ knot_dname_t *name = knot_dname_deep_copy(params->name);
+ if (!name)
+ return KNOT_ENOMEM;
+
+ knot_dnssec_key_data_t *data;
+ data = calloc(1, sizeof(knot_dnssec_key_data_t));
+ if (!data) {
+ knot_dname_release(name);
+ return KNOT_ENOMEM;
+ }
+
+ int result = init_algorithm_data(params, data);
+ if (result != KNOT_EOK) {
+ knot_dname_release(name);
+ free(data);
+ return result;
+ }
+
+ key->name = name;
+ key->keytag = params->keytag;
+ key->algorithm = params->algorithm;
+ key->data = data;
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Free DNSSEC key structure content.
+ */
+int knot_dnssec_key_free(knot_dnssec_key_t *key)
+{
+ if (!key)
+ return KNOT_EINVAL;
+
+ if (key->name)
+ knot_dname_release(key->name);
+
+ if (key->data) {
+ clean_algorithm_data(key->data);
+ free(key->data);
+ }
+
+ memset(key, '\0', sizeof(knot_dnssec_key_t));
+
+ return KNOT_EOK;
+}
+
+/*- Public low level signing interface ---------------------------------------*/
+
+/*!
+ * \brief Initialize DNSSEC signing context.
+ */
+knot_dnssec_sign_context_t *knot_dnssec_sign_init(const knot_dnssec_key_t *key)
+{
+ if (!key)
+ return NULL;
+
+ knot_dnssec_sign_context_t *context = malloc(sizeof(*context));
+ if (!context)
+ return NULL;
+
+ context->key = key;
+
+ if (create_digest_context(key, &context->digest_context) != KNOT_EOK) {
+ free(context);
+ return NULL;
+ }
+
+ return context;
+}
+
+/*!
+ * \brief Free DNSSEC signing context.
+ */
+void knot_dnssec_sign_free(knot_dnssec_sign_context_t *context)
+{
+ if (!context)
+ return;
+
+ context->key = NULL;
+ destroy_digest_context(&context->digest_context);
+ free(context);
+}
+
+/*!
+ * \brief Get DNSSEC signature size.
+ */
+size_t knot_dnssec_sign_size(knot_dnssec_key_t *key)
+{
+ if (!key)
+ return 0;
+
+ return key->data->functions->sign_size(key);
+}
+
+/*!
+ * \brief Add data into DNSSEC signature.
+ */
+int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context,
+ const uint8_t *data, size_t data_size)
+{
+ if (!context || !context->key || !data)
+ return KNOT_EINVAL;
+
+ return context->key->data->functions->sign_add(context, data, data_size);
+}
+
+/**
+ * \brief Finish DNSSEC signing and write out the signature.
+ */
+int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context, uint8_t *signature)
+{
+ if (!context || !context->key || !signature)
+ return KNOT_EINVAL;
+
+ return context->key->data->functions->sign_write(context, signature);
+}
diff --git a/src/libknot/sign/dnssec.h b/src/libknot/sign/dnssec.h
new file mode 100644
index 0000000..bb9fe22
--- /dev/null
+++ b/src/libknot/sign/dnssec.h
@@ -0,0 +1,131 @@
+/* Copyright (C) 2011 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 dnssec.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief Low level DNSSEC signing functions.
+ *
+ * \addtogroup dnssec
+ * @{
+ */
+
+#ifndef _KNOT_SIGN_DNSSEC_H_
+#define _KNOT_SIGN_DNSSEC_H_
+
+#include "sign/key.h"
+#include "common/descriptor.h"
+
+/*!
+ * \brief Algorithm private key data and algorithm implementation (internal).
+ */
+struct knot_dnssec_key_data;
+typedef struct knot_dnssec_key_data knot_dnssec_key_data_t;
+
+/*!
+ * \brief DNSSEC signature contextual data (internal).
+ */
+struct knot_dnssec_sign_context;
+typedef struct knot_dnssec_sign_context knot_dnssec_sign_context_t;
+
+/*!
+ * \brief DNSSEC key representation.
+ */
+typedef struct {
+ knot_dname_t *name; //!< Key name (identifies signer).
+ uint16_t keytag; //!< Key tag (for fast lookup).
+ knot_dnssec_algorithm_t algorithm; //!< Algorithm identification.
+ knot_dnssec_key_data_t *data; //!< Private key data.
+} knot_dnssec_key_t;
+
+/*- DNSSEC private key manipulation ------------------------------------------*/
+
+/*!
+ * \brief Fill DNSSEC key structure according to key parameters.
+ *
+ * \param params Key parameters.
+ * \param key Output structure.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+int knot_dnssec_key_from_params(const knot_key_params_t *params,
+ knot_dnssec_key_t *key);
+
+/*!
+ * \brief Free DNSSEC key structure content.
+ *
+ * \note Does not free the structure itself.
+ *
+ * \param key DNSSEC key.
+ *
+ * \return Error code, always KNOT_EOK.
+ */
+int knot_dnssec_key_free(knot_dnssec_key_t *key);
+
+
+/*- DNSSEC low level signing interface----------------------------------------*/
+
+/*!
+ * \brief Initialize DNSSEC signing context.
+ *
+ * \param key DNSSEC key.
+ * \return DNSSEC signing context.
+ */
+knot_dnssec_sign_context_t *knot_dnssec_sign_init(const knot_dnssec_key_t *key);
+
+/*!
+ * \brief Free DNSSEC signing context.
+ *
+ * \param context Context to be freed.
+ */
+void knot_dnssec_sign_free(knot_dnssec_sign_context_t *context);
+
+/*!
+ * \brief Get DNSSEC signature size.
+ *
+ * \param key Key parameters.
+ *
+ * \return DNSSEC signature size. Zero in case of error.
+ */
+size_t knot_dnssec_sign_size(knot_dnssec_key_t *key);
+
+/*!
+ * \brief Add data into DNSSEC signature.
+ *
+ * \param context DNSSEC signing context.
+ * \param data Pointer to data to be added.
+ * \param data_size Size of the data to be added.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context,
+ const uint8_t *data, size_t data_size);
+
+/**
+ * \brief Finish DNSSEC signing and write out the signature.
+ *
+ * \param context DNSSEC signing context.
+ * \param signature Pointer to signature to be written.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context,
+ uint8_t *signature);
+
+#endif // _KNOT_SIGN_DNSSEC_H_
+
+/*! @} */
diff --git a/src/libknot/sign/key.c b/src/libknot/sign/key.c
new file mode 100644
index 0000000..d721e64
--- /dev/null
+++ b/src/libknot/sign/key.c
@@ -0,0 +1,561 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "binary.h"
+#include "common.h"
+#include "common/getline.h"
+#include "dname.h"
+#include "sign/key.h"
+#include "sign/sig0.h"
+#include "tsig.h"
+#include "zscanner/scanner.h"
+
+/*!
+ * \brief Calculates keytag for RSA/MD5 algorithm.
+ */
+static uint16_t keytag_rsa_md5(const uint8_t *rdata, uint16_t rdata_len)
+{
+ uint16_t ac = 0;
+ if (rdata_len > 4) {
+ memmove(&ac, rdata + rdata_len - 3, 2);
+ }
+
+ ac = ntohs(ac);
+ return ac;
+}
+
+/*!
+ * \brief Calculates keytag from key wire.
+ */
+uint16_t knot_keytag(const uint8_t *rdata, uint16_t rdata_len)
+{
+ uint32_t ac = 0; /* assumed to be 32 bits or larger */
+
+ if (rdata[3] == 1) {
+ // different algorithm for RSA/MD5 (historical reasons)
+ return keytag_rsa_md5(rdata, rdata_len);
+ } else {
+ for(int i = 0; i < rdata_len; i++) {
+ ac += (i & 1) ? rdata[i] : rdata[i] << 8;
+ }
+
+ ac += (ac >> 16) & 0xFFFF;
+ return (uint16_t)ac & 0xFFFF;
+ }
+}
+
+/*!
+ * \brief Acts like strndup, except it adds a suffix to duplicated string.
+ */
+static char *strndup_with_suffix(const char *base, int length, char *suffix)
+{
+ int result_length = length + strlen(suffix) + 1;
+ char *result = (char *)malloc(result_length);
+ if (!result)
+ return NULL;
+
+ int ret = snprintf(result, result_length, "%.*s%s", length, base, suffix);
+ if (ret < 0 || ret >= result_length) {
+ free(result);
+ return NULL;
+ }
+
+ return result;
+}
+
+static void key_scan_noop(const scanner_t *s)
+{
+ UNUSED(s);
+}
+
+/*!
+ * \brief Reads RR in the public key file and retrieves basic key information.
+ */
+static int get_key_info_from_public_key(const char *filename,
+ knot_dname_t **name,
+ uint16_t *keytag)
+{
+ if (!filename || !name || !keytag)
+ return KNOT_EINVAL;
+
+ FILE *keyfile = fopen(filename, "r");
+ if (!keyfile)
+ return KNOT_KEY_EPUBLIC_KEY_OPEN;
+
+ scanner_t *scanner = scanner_create(filename);
+ if (!scanner) {
+ fclose(keyfile);
+ return KNOT_ENOMEM;
+ }
+
+ scanner->process_record = key_scan_noop;
+ scanner->process_error = key_scan_noop;
+ scanner->default_ttl = 0;
+ scanner->default_class = KNOT_CLASS_IN;
+ scanner->zone_origin[0] = '\0';
+ scanner->zone_origin_length = 1;
+
+ char *buffer = NULL;
+ size_t buffer_size;
+ ssize_t read = knot_getline(&buffer, &buffer_size, keyfile);
+
+ fclose(keyfile);
+
+ if (read == -1) {
+ scanner_free(scanner);
+ return KNOT_KEY_EPUBLIC_KEY_INVALID;
+ }
+
+ if (scanner_process(buffer, buffer + read, true, scanner) != 0) {
+ free(buffer);
+ scanner_free(scanner);
+ return KNOT_KEY_EPUBLIC_KEY_INVALID;
+ }
+
+ free(buffer);
+
+ knot_dname_t *owner = knot_dname_new_from_wire(scanner->r_owner,
+ scanner->r_owner_length,
+ NULL);
+ if (!owner) {
+ scanner_free(scanner);
+ return KNOT_ENOMEM;
+ }
+
+ *name = owner;
+ *keytag = knot_keytag(scanner->r_data, scanner->r_data_length);
+
+ scanner_free(scanner);
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Extract private and public key file names from input filename.
+ *
+ * If the input file name has an empty extension (ends with a dot),
+ * extension 'private', or extension 'key', the appropriate filenames are
+ * derived from the previous part of the string. Otherwise, just append the
+ * extensions.
+ */
+static int get_key_filenames(const char *input, char **pubname, char **privname)
+{
+ assert(input);
+ assert(pubname);
+ assert(privname);
+
+ char *name_end = strrchr(input, '.');
+ size_t base_length;
+
+ if (name_end && (*(name_end + 1) == '\0' ||
+ strcmp(name_end, ".key") == 0 ||
+ strcmp(name_end, ".private") == 0)
+ ) {
+ base_length = name_end - input;
+ } else {
+ base_length = strlen(input);
+ }
+
+ *pubname = strndup_with_suffix(input, base_length, ".key");
+ if (!*pubname) {
+ return KNOT_ENOMEM;
+ }
+
+ *privname = strndup_with_suffix(input, base_length, ".private");
+ if (!*privname) {
+ free(*pubname);
+ *pubname = NULL;
+ return KNOT_ENOMEM;
+ }
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Handle storing of string type key parameter.
+ */
+static int key_param_string(const void *save_to, char *value)
+{
+ char **parameter = (char **)save_to;
+
+ free(*parameter);
+ *parameter = strdup(value);
+
+ return *parameter ? KNOT_EOK : KNOT_ENOMEM;
+}
+
+/*!
+ * \brief Handle storing of algorithm type key parameter.
+ */
+static int key_param_int(const void *save_to, char *value)
+{
+ int *parameter = (int *)save_to;
+
+ char *value_end;
+ int numeric_value = strtol(value, &value_end, 10);
+
+ if (value == value_end ||
+ (*value_end != '\0' && !isspace((unsigned char)(*value_end))))
+ return KNOT_EINVAL;
+
+ *parameter = numeric_value;
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Describes private key parameter used in key_parameters.
+ */
+struct key_parameter {
+ char *name;
+ size_t offset;
+ int (*handler)(const void *, char *);
+};
+
+#define key_offset(field) offsetof(knot_key_params_t, field)
+
+/*!
+ * \brief Table of know attributes in private key file.
+ *
+ * \todo Save some space, save base64 encoded strings as binary data.
+ */
+static const struct key_parameter key_parameters[] = {
+ { "Algorithm", key_offset(algorithm), key_param_int },
+ { "Key", key_offset(secret), key_param_string },
+ { "Modulus", key_offset(modulus), key_param_string },
+ { "PublicExponent", key_offset(public_exponent), key_param_string },
+ { "PrivateExponent", key_offset(private_exponent), key_param_string },
+ { "Prime1", key_offset(prime_one), key_param_string },
+ { "Prime2", key_offset(prime_two), key_param_string },
+ { "Exponent1", key_offset(exponent_one), key_param_string },
+ { "Exponent2", key_offset(exponent_two), key_param_string },
+ { "Coefficient", key_offset(coefficient), key_param_string },
+ { "Prime(p)", key_offset(prime), key_param_string },
+ { "Subprime(q)", key_offset(subprime), key_param_string },
+ { "Generator(g)", key_offset(generator), key_param_string },
+ { "Base(g)", key_offset(base), key_param_string },
+ { "Private_value(x)",key_offset(private_value), key_param_string },
+ { "Public_value(y)", key_offset(public_value), key_param_string },
+ { "PrivateKey", key_offset(private_key), key_param_string },
+ { NULL }
+};
+
+/*!
+ * \brief Parse one line of key file.
+ *
+ * \param key_params Key parameters to write the result into.
+ * \param line Input line pointer.
+ * \param length Input line length.
+ */
+static int parse_keyfile_line(knot_key_params_t *key_params,
+ char *line, size_t length)
+{
+ // discard line termination
+ if (length > 0 && line[length - 1] == '\n') {
+ line[length - 1] = '\0';
+ length -= 1;
+ }
+
+ // extract attribute name
+ char *separator = memchr(line, ':', length);
+ if (!separator)
+ return KNOT_EOK;
+
+ // find matching attribute
+ size_t name_length = separator - line;
+ for (int i = 0; key_parameters[i].name != NULL; i++) {
+ const struct key_parameter *current = &key_parameters[i];
+ if (memcmp(current->name, line, name_length) != 0)
+ continue;
+
+ assert(current->handler);
+
+ char *value = separator + 1;
+ while (isspace((unsigned char)(*value)))
+ value++;
+
+ void *save_to = (void *)key_params + current->offset;
+ return current->handler(save_to, value);
+ }
+
+ // attribute not supported or not required
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Reads the key file and extracts key parameters.
+ */
+int knot_load_key_params(const char *filename, knot_key_params_t *key_params)
+{
+ assert(filename);
+ assert(key_params);
+
+ int result;
+ char *public_key = NULL;
+ char *private_key = NULL;
+
+ result = get_key_filenames(filename, &public_key, &private_key);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ knot_dname_t *name;
+ uint16_t keytag;
+ result = get_key_info_from_public_key(public_key, &name, &keytag);
+ if (result != KNOT_EOK) {
+ free(public_key);
+ free(private_key);
+ return result;
+ }
+
+ FILE *fp = fopen(private_key, "r");
+ if (!fp) {
+ free(public_key);
+ free(private_key);
+ knot_dname_release(name);
+ return KNOT_KEY_EPRIVATE_KEY_OPEN;
+ }
+
+ key_params->name = name;
+ key_params->keytag = keytag;
+
+ char *buffer = NULL;
+ size_t buffer_size = 0;
+ ssize_t read;
+ while((read = knot_getline(&buffer, &buffer_size, fp)) > 0) {
+ if (buffer[read - 1] == '\n') {
+ read -= 1;
+ buffer[read] = '\0';
+ }
+ result = parse_keyfile_line(key_params, buffer, read);
+ if (result != KNOT_EOK)
+ break;
+ }
+ free(buffer);
+
+ fclose(fp);
+ free(public_key);
+ free(private_key);
+
+ return result;
+}
+
+static int copy_string_if_set(const char *src, char **dst)
+{
+ if (src != NULL) {
+ *dst = strdup(src);
+
+ if (*dst == NULL) {
+ return -1;
+ }
+ } else {
+ *dst = NULL;
+ }
+
+ return 0;
+}
+
+int knot_copy_key_params(const knot_key_params_t *src, knot_key_params_t *dst)
+{
+ if (src == NULL || dst == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ int ret = 0;
+
+ if (src->name != NULL) {
+ dst->name = knot_dname_deep_copy(src->name);
+ if (dst->name == NULL) {
+ ret += -1;
+ }
+ }
+
+ dst->algorithm = src->algorithm;
+ dst->keytag = src->keytag;
+
+ ret += copy_string_if_set(src->secret, &dst->secret);
+
+ ret += copy_string_if_set(src->modulus, &dst->modulus);
+ ret += copy_string_if_set(src->public_exponent, &dst->public_exponent);
+ ret += copy_string_if_set(src->private_exponent, &dst->private_exponent);
+ ret += copy_string_if_set(src->prime_one, &dst->prime_one);
+ ret += copy_string_if_set(src->prime_two, &dst->prime_two);
+ ret += copy_string_if_set(src->exponent_one, &dst->exponent_one);
+ ret += copy_string_if_set(src->exponent_two, &dst->exponent_two);
+ ret += copy_string_if_set(src->coefficient, &dst->coefficient);
+
+ ret += copy_string_if_set(src->prime, &dst->prime);
+ ret += copy_string_if_set(src->generator, &dst->generator);
+ ret += copy_string_if_set(src->subprime, &dst->subprime);
+ ret += copy_string_if_set(src->base, &dst->base);
+ ret += copy_string_if_set(src->private_value, &dst->private_value);
+ ret += copy_string_if_set(src->public_value, &dst->public_value);
+
+ ret += copy_string_if_set(src->private_key, &dst->private_key);
+
+ if (ret < 0) {
+ knot_free_key_params(dst);
+ return KNOT_ENOMEM;
+ }
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Frees the key parameters.
+ */
+int knot_free_key_params(knot_key_params_t *key_params)
+{
+ assert(key_params);
+
+ if (key_params->name)
+ knot_dname_release(key_params->name);
+
+ free(key_params->secret);
+
+ free(key_params->modulus);
+ free(key_params->public_exponent);
+ free(key_params->private_exponent);
+ free(key_params->prime_one);
+ free(key_params->prime_two);
+ free(key_params->exponent_one);
+ free(key_params->exponent_two);
+ free(key_params->coefficient);
+
+ free(key_params->prime);
+ free(key_params->generator);
+ free(key_params->subprime);
+ free(key_params->base);
+ free(key_params->private_value);
+ free(key_params->public_value);
+
+ free(key_params->private_key);
+
+ memset(key_params, '\0', sizeof(knot_key_params_t));
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Get the type of the key.
+ */
+knot_key_type_t knot_get_key_type(const knot_key_params_t *key_params)
+{
+ assert(key_params);
+
+ if (key_params->secret) {
+ return KNOT_KEY_TSIG;
+ }
+
+ if (key_params->modulus || key_params->prime || key_params->private_key) {
+ return KNOT_KEY_DNSSEC;
+ }
+
+ //! \todo TKEY key recognition
+
+ return KNOT_KEY_UNKNOWN;
+}
+
+/*!
+ * \brief Creates TSIG key from function arguments.
+ *
+ * \param name Key name (aka owner name).
+ * \param algorithm Algorithm number.
+ * \param b64secret Shared secret encoded in Base64.
+ * \param key Output TSIG key.
+ *
+ * \return Error code, KNOT_EOK when succeeded.
+ */
+static int knot_tsig_create_key_from_args(knot_dname_t *name, int algorithm,
+ const char *b64secret,
+ knot_tsig_key_t *key)
+{
+ if (!name || !b64secret || !key)
+ return KNOT_EINVAL;
+
+ knot_binary_t secret;
+ int result = knot_binary_from_base64(b64secret, &secret);
+
+ if (result != KNOT_EOK)
+ return result;
+
+ knot_dname_retain(name);
+
+ key->name = name;
+ key->secret = secret;
+ key->algorithm = algorithm;
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Creates TSIG key.
+ */
+int knot_tsig_create_key(const char *name, int algorithm,
+ const char *b64secret, knot_tsig_key_t *key)
+{
+ knot_dname_t *dname;
+ dname = knot_dname_new_from_nonfqdn_str(name, strlen(name), NULL);
+ if (!dname)
+ return KNOT_ENOMEM;
+
+ int res;
+ res = knot_tsig_create_key_from_args(dname, algorithm, b64secret, key);
+
+ knot_dname_release(dname);
+
+ return res;
+}
+
+
+/*!
+ * \brief Creates TSIG key from key parameters.
+ */
+int knot_tsig_key_from_params(const knot_key_params_t *params,
+ knot_tsig_key_t *key)
+{
+ if (!params)
+ return KNOT_EINVAL;
+
+ return knot_tsig_create_key_from_args(params->name, params->algorithm,
+ params->secret, key);
+}
+
+/*!
+ * \brief Frees TSIG key.
+ */
+int knot_tsig_key_free(knot_tsig_key_t *key)
+{
+ if (!key)
+ return KNOT_EINVAL;
+
+ knot_dname_release(key->name);
+
+ knot_binary_free(&key->secret);
+ memset(key, '\0', sizeof(knot_tsig_key_t));
+
+ return KNOT_EOK;
+}
diff --git a/src/libknot/sign/key.h b/src/libknot/sign/key.h
new file mode 100644
index 0000000..54d1101
--- /dev/null
+++ b/src/libknot/sign/key.h
@@ -0,0 +1,168 @@
+/* Copyright (C) 2011 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 key.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief Interface for loding of keys.
+ *
+ * \addtogroup dnssec
+ * @{
+ */
+
+#ifndef _KNOT_SIGN_KEY_H_
+#define _KNOT_SIGN_KEY_H_
+
+#include <stdint.h>
+#include "dname.h"
+#include "tsig.h"
+
+/*----------------------------------------------------------------------------*/
+
+/*!
+ * \brief Key attributes loaded from keyfile.
+ */
+struct knot_key_params {
+ knot_dname_t *name;
+ int algorithm;
+ uint16_t keytag;
+ // parameters for symmetric cryptography
+ char *secret;
+ // parameters for public key cryptography
+ // RSA
+ char *modulus;
+ char *public_exponent;
+ char *private_exponent;
+ char *prime_one;
+ char *prime_two;
+ char *exponent_one;
+ char *exponent_two;
+ char *coefficient;
+ // DH, DSA
+ char *prime;
+ char *generator;
+ char *subprime;
+ char *base;
+ char *private_value;
+ char *public_value;
+ // EC
+ char *private_key;
+};
+
+typedef struct knot_key_params knot_key_params_t;
+
+enum knot_key_type {
+ KNOT_KEY_UNKNOWN = 0,
+ KNOT_KEY_DNSSEC, //!< DNSSEC key. Described in RFC 2535 and RFC 4034.
+ KNOT_KEY_TSIG, //!< Transaction Signature. Described in RFC 2845.
+ KNOT_KEY_TKEY //!< Transaction Key. Described in RFC 2930.
+};
+
+typedef enum knot_key_type knot_key_type_t;
+
+/*----------------------------------------------------------------------------*/
+
+/*!
+ * \brief Calculates keytag from key wire.
+ *
+ * \param rdata Key wireformat.
+ * \param rdata_len Wireformat size.
+ *
+ * \return Calculated keytag.
+ */
+uint16_t knot_keytag(const uint8_t *rdata, uint16_t rdata_len);
+
+/*----------------------------------------------------------------------------*/
+
+/*!
+ * \brief Reads the key files and extracts key parameters.
+ *
+ * \param filename The name of the file with stored key. It can be either
+ * the name with '.key' or '.private' suffix or without
+ * the suffix at all.
+ * \param key_params Output key parameters.
+ *
+ * \returns Error code, KNOT_EOK when succeeded.
+ */
+int knot_load_key_params(const char *filename, knot_key_params_t *key_params);
+
+/*!
+ * \brief Copies key params structure content.
+ *
+ * \param src Source structure.
+ * \param dst Destination structure.
+ *
+ * \return Error code, KNOT_EOK when succeeded.
+ */
+int knot_copy_key_params(const knot_key_params_t *src, knot_key_params_t *dst);
+
+/*!
+ * \brief Frees the key parameters.
+ *
+ * \param key_params Key parameters to be freed.
+ *
+ * \return Error code, KNOT_EOK when succeeded.
+ */
+int knot_free_key_params(knot_key_params_t *key_params);
+
+/*!
+ * \brief Get the type of the key.
+ *
+ * \param key_params Key parameters.
+ *
+ * \return Key type.
+ */
+knot_key_type_t knot_get_key_type(const knot_key_params_t *key_params);
+
+/*----------------------------------------------------------------------------*/
+
+/*!
+ * \brief Creates TSIG key.
+ *
+ * \param name Key name (aka owner name).
+ * \param algorithm Algorithm number.
+ * \param b64secret Shared secret encoded in Base64.
+ * \param key Output TSIG key.
+ *
+ * \return Error code, KNOT_EOK when succeeded.
+ */
+int knot_tsig_create_key(const char *name, int algorithm,
+ const char *b64secret, knot_tsig_key_t *key);
+
+/*!
+ * \brief Creates TSIG key from key parameters.
+ *
+ * \param params Structure with key parameters.
+ * \param key Output TSIG key.
+ *
+ * \return Error code, KNOT_EOK when succeeded.
+ */
+int knot_tsig_key_from_params(const knot_key_params_t *params,
+ knot_tsig_key_t *key);
+
+/*!
+ * \brief Frees TSIG key.
+ *
+ * \param key TSIG key structure to be freed.
+ *
+ * \return Error code, KNOT_EOK when succeeded.
+ */
+int knot_tsig_key_free(knot_tsig_key_t *key);
+
+#endif // _KNOT_SIGN_KEY_H_
+
+/*! @} */
diff --git a/src/libknot/sign/sig0.c b/src/libknot/sign/sig0.c
new file mode 100644
index 0000000..d1f1ea9
--- /dev/null
+++ b/src/libknot/sign/sig0.c
@@ -0,0 +1,231 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "sign/dnssec.h"
+#include "sign/sig0.h"
+#include "common/errcode.h"
+#include <assert.h>
+#include <time.h>
+#include "util/wire.h"
+
+/*!
+ * \brief Lifetime fudge of the SIG(0) packets in seconds.
+ *
+ * RFC recommends [now-5min, now+5min] lifetime interval.
+ */
+#define SIG0_LIFETIME_FUDGE_SECONDS 300
+
+/*- SIG(0) internals ---------------------------------------------------------*/
+
+/*!
+ * \brief Create and initialize SIG(0) RR set.
+ *
+ * \return SIG(0) RR set.
+ */
+static knot_rrset_t *sig0_create_rrset(void)
+{
+ knot_dname_t *root = knot_dname_new_from_str(".", 1, NULL);
+ uint32_t ttl = 0;
+ knot_rrset_t *sig_record = knot_rrset_new(root, KNOT_RRTYPE_SIG,
+ KNOT_CLASS_ANY, ttl);
+ knot_dname_release(root);
+
+ return sig_record;
+}
+
+/*!
+ * \brief Get size of SIG(0) RDATA field.
+ *
+ * \param key Signing key.
+ *
+ * \return Size of the SIG(0) record in bytes.
+ */
+static size_t sig0_rdata_size(knot_dnssec_key_t *key)
+{
+ assert(key);
+
+ size_t size;
+
+ // static part
+
+ size = sizeof(uint16_t) // type covered
+ + sizeof(uint8_t) // algorithm
+ + sizeof(uint8_t) // labels
+ + sizeof(uint32_t) // original TTL
+ + sizeof(uint32_t) // signature expiration
+ + sizeof(uint32_t) // signature inception
+ + sizeof(uint16_t); // key tag (footprint)
+
+ // variable part
+
+ size += sizeof(knot_dname_t *); // pointer to signer
+ size += knot_dnssec_sign_size(key);
+
+ return size;
+}
+
+/*!
+ * \brief Create and zero SIG(0) RDATA field.
+ *
+ * \param rrset SIG(0) RR set.
+ * \param key Signing key.
+ *
+ * \return SIG(0) RDATA.
+ */
+static uint8_t *sig0_create_rdata(knot_rrset_t *rrset, knot_dnssec_key_t *key)
+{
+ assert(rrset);
+ assert(key);
+
+ size_t rdata_size = sig0_rdata_size(key);
+ uint8_t *rdata = knot_rrset_create_rdata(rrset, rdata_size);
+ if (!rdata)
+ return NULL;
+
+ memset(rdata, '\0', rdata_size);
+
+ return rdata;
+}
+
+/*!
+ * \brief Fill SIG(0) RDATA field except the signature part.
+ *
+ * \param key Signing key.
+ * \param rdata RDATA to be filled.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int sig0_write_rdata(knot_dnssec_key_t *key, uint8_t *rdata)
+{
+ assert(key);
+ assert(rdata);
+
+ uint32_t incepted = (uint32_t)time(NULL) - SIG0_LIFETIME_FUDGE_SECONDS;
+ uint32_t expires = incepted + 2 * SIG0_LIFETIME_FUDGE_SECONDS;
+
+ uint8_t *w = rdata;
+
+ w += sizeof(uint16_t); // type covered
+ *w = key->algorithm; // algorithm
+ w += sizeof(uint8_t);
+ w += sizeof(uint8_t); // labels
+ w += sizeof(uint32_t); // original TTL
+ knot_wire_write_u32(w, expires); // signature expiration
+ w += sizeof(uint32_t);
+ knot_wire_write_u32(w, incepted); // signature inception
+ w += sizeof(uint32_t);
+ knot_wire_write_u16(w, key->keytag); // key footprint
+ w += sizeof(uint16_t);
+
+ assert(w == rdata + 18);
+ memcpy(w, &key->name, sizeof(knot_dname_t *)); // pointer to signer
+
+ return KNOT_EOK;
+}
+
+/*!
+ * \brief Write SIG(0) signature to a given binary wire.
+ *
+ * The signature covers SIG(0) RDATA section without signature field. And the
+ * whole preceeding request before the SIG(0) record was added (i.e. before the
+ * AR count in header was increased).
+ *
+ * \param wire Output wire to be signed.
+ * \param request_size Size of the request in the wire.
+ * \param sig_rr_size Size of the SIG(0) RR in the wire.
+ * \param key Signing key.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+static int sig0_write_signature(uint8_t* wire, size_t request_size,
+ size_t sig_rr_size, knot_dnssec_key_t *key)
+{
+ assert(key);
+ assert(key->data);
+
+ knot_dnssec_sign_context_t *ctx = knot_dnssec_sign_init(key);
+ if (!ctx)
+ return KNOT_ENOMEM;
+
+ size_t signature_size = knot_dnssec_sign_size(key);
+ size_t sig_rr_header_size = 11; // owner (== root), type, class, TTL
+ size_t sig_rdata_size = sig_rr_size - sig_rr_header_size;
+
+ uint8_t *sig_rdata = wire + request_size + sig_rr_header_size;
+ uint8_t *signature = wire + request_size + sig_rr_size - signature_size;
+
+ knot_dnssec_sign_add(ctx, sig_rdata, sig_rdata_size - signature_size);
+ knot_dnssec_sign_add(ctx, wire, request_size);
+ int result = knot_dnssec_sign_write(ctx, signature);
+
+ knot_dnssec_sign_free(ctx);
+
+ return result;
+}
+
+/*- SIG(0) public ------------------------------------------------------------*/
+
+/*!
+ * \brief Sign a packet using SIG(0) mechanism.
+ */
+int knot_sig0_sign(uint8_t *wire, size_t *wire_size, size_t wire_max_size,
+ knot_dnssec_key_t *key)
+{
+ knot_rrset_t *sig_rrset = sig0_create_rrset();
+ if (!sig_rrset) {
+ return KNOT_ENOMEM;
+ }
+
+ uint8_t *sig_rdata = sig0_create_rdata(sig_rrset, key);
+ if (!sig_rdata) {
+ knot_rrset_deep_free(&sig_rrset, 1, 0);
+ return KNOT_ENOMEM;
+ }
+
+ sig0_write_rdata(key, sig_rdata);
+
+ // convert to wire
+
+ uint8_t *wire_end = wire + *wire_size;
+ size_t wire_avail_size = wire_max_size - *wire_size;
+ size_t wire_sig_size = 0;
+ uint16_t written_rr_count = 0;
+
+ int result = knot_rrset_to_wire(sig_rrset, wire_end, &wire_sig_size,
+ wire_avail_size, &written_rr_count,
+ NULL);
+ knot_rrset_deep_free(&sig_rrset, 1, 0);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ assert(written_rr_count == 1);
+
+ // create signature
+
+ result = sig0_write_signature(wire, *wire_size, wire_sig_size, key);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ uint16_t wire_arcount = knot_wire_get_arcount(wire);
+ knot_wire_set_arcount(wire, wire_arcount + written_rr_count);
+
+ *wire_size += wire_sig_size;
+
+ return KNOT_EOK;
+}
diff --git a/src/libknot/sign/sig0.h b/src/libknot/sign/sig0.h
new file mode 100644
index 0000000..29e9d4e
--- /dev/null
+++ b/src/libknot/sign/sig0.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2011 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 sig0.h
+ *
+ * \author Jan Vcelak <jan.vcelak@nic.cz>
+ *
+ * \brief Interface for packet signing using SIG(0).
+ *
+ * \addtogroup dnssec
+ * @{
+ */
+
+#ifndef _KNOT_SIGN_SIG0_H_
+#define _KNOT_SIGN_SIG0_H_
+
+#include "sign/dnssec.h"
+
+/*!
+ * \brief Sign a packet using SIG(0) mechanism.
+ *
+ * \param wire Wire (packet content).
+ * \param wire_size Size of the wire.
+ * \param wire_max_size Capacity of the wire.
+ * \param key DNSSEC key to be used for signature.
+ *
+ * \return Error code, KNOT_EOK if succeeded.
+ */
+int knot_sig0_sign(uint8_t *wire, size_t *wire_size, size_t wire_max_size,
+ knot_dnssec_key_t *key);
+
+#endif // _KNOT_SIGN_SIG0_H_
+
+/*! @} */
diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c
index 55316a9..e6b1116 100644
--- a/src/libknot/tsig-op.c
+++ b/src/libknot/tsig-op.c
@@ -14,39 +14,38 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
#include <stdint.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <time.h>
+#include <inttypes.h>
#include "common.h"
-#include "common/base64.h"
+#include "common/descriptor.h"
#include "tsig.h"
#include "tsig-op.h"
#include "util/wire.h"
#include "util/debug.h"
#include "consts.h"
-
+#include "sign/key.h"
const int KNOT_TSIG_MAX_DIGEST_SIZE = 64; // size of HMAC-SHA512 digest
const uint16_t KNOT_TSIG_FUDGE_DEFAULT = 300; // default Fudge value
-enum b64_const {
- B64BUFSIZE = 65535
-};
static int knot_tsig_check_algorithm(const knot_rrset_t *tsig_rr)
{
if (tsig_rr == NULL) {
return KNOT_EINVAL;
}
-
+
const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig_rr);
if (!alg_name) {
return KNOT_EMALF;
}
- tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
+ knot_tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
if (alg == 0) {
/*!< \todo is this error OK? */
dbg_tsig("TSIG: unknown algorithm.\n");
@@ -57,12 +56,12 @@ static int knot_tsig_check_algorithm(const knot_rrset_t *tsig_rr)
}
static int knot_tsig_check_key(const knot_rrset_t *tsig_rr,
- const knot_key_t *tsig_key)
+ const knot_tsig_key_t *tsig_key)
{
if (tsig_rr == NULL || tsig_key == NULL) {
return KNOT_EINVAL;
}
-
+
const knot_dname_t *tsig_name = knot_rrset_owner(tsig_rr);
if (!tsig_name) {
return KNOT_EMALF;
@@ -86,7 +85,7 @@ static int knot_tsig_check_key(const knot_rrset_t *tsig_rr,
static int knot_tsig_compute_digest(const uint8_t *wire, size_t wire_len,
uint8_t *digest, size_t *digest_len,
- const knot_key_t *key)
+ const knot_tsig_key_t *key)
{
if (!wire || !digest || !digest_len || !key) {
dbg_tsig("TSIG: digest: bad args.\n");
@@ -98,29 +97,15 @@ static int knot_tsig_compute_digest(const uint8_t *wire, size_t wire_len,
return KNOT_EMALF;
}
- tsig_algorithm_t tsig_alg = key->algorithm;
+ knot_tsig_algorithm_t tsig_alg = key->algorithm;
if (tsig_alg == 0) {
dbg_tsig("TSIG: digest: unknown algorithm\n");
return KNOT_TSIG_EBADSIG;
}
- /* Decode key from Base64. */
- char decoded_key[B64BUFSIZE];
- memset(decoded_key, 0, sizeof(decoded_key));
-
- int32_t ret = base64_decode((uint8_t *)key->secret, strlen(key->secret),
- (uint8_t *)decoded_key, B64BUFSIZE);
-
- if (ret < 0) {
- dbg_tsig("TSIG: Could not decode Base64\n");
- return KNOT_ERROR;
- }
-
- size_t decoded_key_size = ret;
-
- dbg_tsig_detail("TSIG: decoded key size: %d\n", decoded_key_size);
- dbg_tsig_detail("TSIG: decoded key:\n");
- dbg_tsig_hex_detail(decoded_key, decoded_key_size);
+ dbg_tsig_detail("TSIG: key size: %zu\n", key->secret.size);
+ dbg_tsig_detail("TSIG: key:\n");
+ dbg_tsig_hex_detail((char *)key->secret.data, key->secret.size);
dbg_tsig_detail("Wire for signing is %zu bytes long.\n", wire_len);
/* Compute digest. */
@@ -128,16 +113,28 @@ static int knot_tsig_compute_digest(const uint8_t *wire, size_t wire_len,
switch (tsig_alg) {
case KNOT_TSIG_ALG_HMAC_MD5:
- HMAC_Init(&ctx, decoded_key,
- decoded_key_size, EVP_md5());
+ HMAC_Init(&ctx, key->secret.data,
+ key->secret.size, EVP_md5());
break;
case KNOT_TSIG_ALG_HMAC_SHA1:
- HMAC_Init(&ctx, decoded_key,
- decoded_key_size, EVP_sha1());
+ HMAC_Init(&ctx, key->secret.data,
+ key->secret.size, EVP_sha1());
+ break;
+ case KNOT_TSIG_ALG_HMAC_SHA224:
+ HMAC_Init(&ctx, key->secret.data,
+ key->secret.size, EVP_sha224());
break;
case KNOT_TSIG_ALG_HMAC_SHA256:
- HMAC_Init(&ctx, decoded_key,
- decoded_key_size, EVP_sha256());
+ HMAC_Init(&ctx, key->secret.data,
+ key->secret.size, EVP_sha256());
+ break;
+ case KNOT_TSIG_ALG_HMAC_SHA384:
+ HMAC_Init(&ctx, key->secret.data,
+ key->secret.size, EVP_sha384());
+ break;
+ case KNOT_TSIG_ALG_HMAC_SHA512:
+ HMAC_Init(&ctx, key->secret.data,
+ key->secret.size, EVP_sha512());
break;
default:
return KNOT_ENOTSUP;
@@ -147,7 +144,7 @@ static int knot_tsig_compute_digest(const uint8_t *wire, size_t wire_len,
HMAC_Update(&ctx, (const unsigned char *)wire, wire_len);
HMAC_Final(&ctx, digest, &tmp_dig_len);
*digest_len = tmp_dig_len;
-
+
HMAC_CTX_cleanup(&ctx);
return KNOT_EOK;
@@ -197,7 +194,7 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
dbg_tsig("TSIG: write tsig variables: NULL arguments.\n");
return KNOT_EINVAL;
}
-
+
/* Copy TSIG variables - starting with key name. */
const knot_dname_t *tsig_owner = knot_rrset_owner(tsig_rr);
if (!tsig_owner) {
@@ -210,7 +207,7 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
memcpy(wire + offset, knot_dname_name(tsig_owner),
sizeof(uint8_t) * knot_dname_size(tsig_owner));
dbg_tsig_verb("TSIG: write variables: written owner (tsig alg): \n");
- dbg_tsig_hex_verb(wire + offset, knot_dname_size(tsig_owner));
+ dbg_tsig_hex_verb((char *)(wire + offset), knot_dname_size(tsig_owner));
offset += knot_dname_size(tsig_owner);
/*!< \todo which order? */
@@ -219,14 +216,14 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
knot_wire_write_u16(wire + offset, knot_rrset_class(tsig_rr));
dbg_tsig_verb("TSIG: write variables: written CLASS: %u - \n",
knot_rrset_class(tsig_rr));
- dbg_tsig_hex_detail(wire + offset, sizeof(uint16_t));
+ dbg_tsig_hex_detail((char *)(wire + offset), sizeof(uint16_t));
offset += sizeof(uint16_t);
/* Copy TTL - always 0. */
knot_wire_write_u32(wire + offset, knot_rrset_ttl(tsig_rr));
dbg_tsig_verb("TSIG: write variables: written TTL: %u - \n",
knot_rrset_ttl(tsig_rr));
- dbg_tsig_hex_detail(wire + offset, sizeof(uint32_t));
+ dbg_tsig_hex_detail((char *)(wire + offset), sizeof(uint32_t));
offset += sizeof(uint32_t);
/* Copy alg name. */
@@ -260,9 +257,9 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
/* Time signed. */
knot_wire_write_u48(wire + offset, tsig_rdata_time_signed(tsig_rr));
offset += 6;
- dbg_tsig_verb("TSIG: write variables: time signed: %llu \n",
+ dbg_tsig_verb("TSIG: write variables: time signed: %"PRIu64" \n",
tsig_rdata_time_signed(tsig_rr));
- dbg_tsig_hex_detail(wire + offset - 6, 6);
+ dbg_tsig_hex_detail((char *)(wire + offset - 6), 6);
/* Fudge. */
knot_wire_write_u16(wire + offset, tsig_rdata_fudge(tsig_rr));
offset += sizeof(uint16_t);
@@ -301,7 +298,7 @@ static int knot_tsig_wire_write_timers(uint8_t *wire,
dbg_tsig("TSIG: write timers: NULL arguments.\n");
return KNOT_EINVAL;
}
-
+
//write time signed
knot_wire_write_u48(wire, tsig_rdata_time_signed(tsig_rr));
//write fudge
@@ -315,7 +312,7 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
size_t request_mac_len,
uint8_t *digest, size_t *digest_len,
const knot_rrset_t *tmp_tsig,
- const knot_key_t *key)
+ const knot_tsig_key_t *key)
{
if (!msg || !key || digest_len == NULL) {
dbg_tsig("TSIG: create wire: bad args.\n");
@@ -355,7 +352,7 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
dbg_tsig_verb("Copying request mac.\n");
memcpy(pos, request_mac, sizeof(uint8_t) * request_mac_len);
dbg_tsig_detail("TSIG: create wire: request mac:\n");
- dbg_tsig_hex_detail(pos, request_mac_len);
+ dbg_tsig_hex_detail((char *)pos, request_mac_len);
pos += request_mac_len;
/* Copy the original message. */
dbg_tsig_verb("Copying original message.\n");
@@ -391,7 +388,7 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
size_t prev_mac_len,
uint8_t *digest, size_t *digest_len,
const knot_rrset_t *tmp_tsig,
- const knot_key_t *key)
+ const knot_tsig_key_t *key)
{
if (!msg || !key || digest_len == NULL) {
dbg_tsig("TSIG: create wire: bad args.\n");
@@ -425,14 +422,14 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
dbg_tsig_verb("Copying request mac.\n");
memcpy(wire + 2, prev_mac, sizeof(uint8_t) * prev_mac_len);
dbg_tsig_detail("TSIG: create wire: request mac:\n");
- dbg_tsig_hex_detail(wire + 2, prev_mac_len);
+ dbg_tsig_hex_detail((char *)(wire + 2), prev_mac_len);
/* Copy the original message. */
dbg_tsig_verb("Copying original message.\n");
memcpy(wire + prev_mac_len + 2, msg, msg_len);
/* Copy TSIG variables. */
-
+
dbg_tsig_verb("Writing TSIG timers.\n");
- ret = knot_tsig_wire_write_timers(wire + prev_mac_len + msg_len + 2,
+ ret = knot_tsig_wire_write_timers(wire + prev_mac_len + msg_len + 2,
tmp_tsig);
if (ret != KNOT_EOK) {
dbg_tsig("TSIG: create wire: failed to write TSIG "
@@ -461,7 +458,7 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
size_t msg_max_len, const uint8_t *request_mac,
size_t request_mac_len,
uint8_t *digest, size_t *digest_len,
- const knot_key_t *key, uint16_t tsig_rcode,
+ const knot_tsig_key_t *key, uint16_t tsig_rcode,
uint64_t request_time_signed)
{
if (!msg || !msg_len || !key || digest == NULL || digest_len == NULL) {
@@ -485,49 +482,14 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
}
/* Create rdata for TSIG RR. */
- knot_rdata_t *rdata = knot_rdata_new();
- if (!rdata) {
- dbg_tsig("TSIG: rdata = NULL\n");
- knot_rrset_free(&tmp_tsig);
- return KNOT_ENOMEM;
- }
-
- knot_rrset_add_rdata(tmp_tsig, rdata);
-
- /* Create items for TSIG RR. */
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(KNOT_RRTYPE_TSIG);
- assert(desc);
-
- knot_rdata_item_t *items =
- malloc(sizeof(knot_rdata_item_t) * desc->length);
- if (!items) {
- dbg_tsig("TSIG: items = NULL\n");
- ERR_ALLOC_FAILED;
- knot_rrset_free(&tmp_tsig);
- knot_rdata_free(&rdata);
- return KNOT_ENOMEM;
- }
-
- memset(items, 0, sizeof(knot_rdata_item_t) * desc->length);
-
- int ret = knot_rdata_set_items(rdata, items, desc->length);
- if (ret != KNOT_EOK) {
- dbg_tsig("TSIG: rdata_set_items returned %s\n",
- knot_strerror(ret));
- free(items);
- knot_rrset_free(&tmp_tsig);
- knot_rdata_free(&rdata);
- return ret;
- }
- free(items);
-
+ tsig_create_rdata(tmp_tsig, knot_tsig_digest_length(key->algorithm),
+ (tsig_rcode == KNOT_RCODE_BADTIME)
+ ? tsig_rcode
+ : 0);
tsig_rdata_set_alg(tmp_tsig, key->algorithm);
/* Distinguish BADTIME response. */
- if (tsig_rcode == KNOT_TSIG_RCODE_BADTIME) {
- /* Set error */
- tsig_rdata_set_tsig_error(tmp_tsig, tsig_rcode);
+ if (tsig_rcode == KNOT_RCODE_BADTIME) {
/* Set client's time signed into the time signed field. */
tsig_rdata_set_time_signed(tmp_tsig, request_time_signed);
@@ -541,7 +503,6 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
tsig_rdata_set_other_data(tmp_tsig, 6, time_signed);
} else {
tsig_rdata_store_current_time(tmp_tsig);
- tsig_rdata_set_tsig_error(tmp_tsig, 0);
/* Set other len. */
tsig_rdata_set_other_data(tmp_tsig, 0, 0);
@@ -555,9 +516,12 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
size_t digest_tmp_len = 0;
+dbg_rrset_exec_detail(
dbg_tsig_detail("tmp_tsig before sign_wire():\n");
- knot_rrset_dump(tmp_tsig, 0);
+ knot_rrset_dump(tmp_tsig);
+);
+ int ret = KNOT_ERROR;
ret = knot_tsig_create_sign_wire(msg, *msg_len, /*msg_max_len,*/
request_mac, request_mac_len,
digest_tmp, &digest_tmp_len,
@@ -565,34 +529,36 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
if (ret != KNOT_EOK) {
dbg_tsig("TSIG: could not create wire or sign wire: %s\n",
knot_strerror(ret));
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
return ret;
}
/* Set the digest. */
- size_t tsig_wire_len = msg_max_len - *msg_len;
+ size_t tsig_wire_len = 0;
dbg_tsig("TSIG: msg_len=%zu, msg_max_len=%zu, tsig_max_len=%zu\n",
*msg_len, msg_max_len, tsig_wire_len);
- int rr_count = 0;
+ uint16_t rr_count = 0;
tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);
/* Write RRSet to wire */
ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len,
- &tsig_wire_len, &rr_count);
+ &tsig_wire_len, msg_max_len - *msg_len,
+ &rr_count, NULL);
if (ret != KNOT_EOK) {
dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
*digest_len = 0;
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
return ret;
}
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
+ dbg_tsig("TSIG: written TSIG RR (wire len %zu)\n", tsig_wire_len);
*msg_len += tsig_wire_len;
uint16_t arcount = knot_wire_get_arcount(msg);
knot_wire_set_arcount(msg, ++arcount);
-
+
// everything went ok, save the digest to the output parameter
memcpy(digest, digest_tmp, digest_tmp_len);
*digest_len = digest_tmp_len;
@@ -603,13 +569,13 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
const uint8_t *prev_digest, size_t prev_digest_len,
uint8_t *digest, size_t *digest_len,
- const knot_key_t *key, uint8_t *to_sign,
+ const knot_tsig_key_t *key, uint8_t *to_sign,
size_t to_sign_len)
{
if (!msg || !msg_len || !key || !key || !digest || !digest_len) {
return KNOT_EINVAL;
}
-
+
uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
size_t digest_tmp_len = 0;
@@ -619,64 +585,20 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
if (!tmp_tsig) {
return KNOT_ENOMEM;
}
-
- /* Create rdata for TSIG RR. */
- knot_rdata_t *rdata = knot_rdata_new();
- if (!rdata) {
- dbg_tsig("TSIG: rdata = NULL\n");
- knot_rrset_free(&tmp_tsig);
- return KNOT_ENOMEM;
- }
-
- int ret = 0;
-
- ret = knot_rrset_add_rdata(tmp_tsig, rdata);
- if (ret != KNOT_EOK) {
- dbg_tsig("TSIG: could not add rdata\n");
- knot_rrset_free(&tmp_tsig);
- knot_rdata_free(&rdata);
- return ret;
- }
-
- /* Create items for TSIG RR. */
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(KNOT_RRTYPE_TSIG);
- assert(desc);
-
- knot_rdata_item_t *items =
- malloc(sizeof(knot_rdata_item_t) * desc->length);
- if (!items) {
- dbg_tsig("TSIG: items = NULL\n");
- ERR_ALLOC_FAILED;
- knot_rrset_free(&tmp_tsig);
- knot_rdata_free(&rdata);
- return KNOT_ENOMEM;
- }
-
- memset(items, 0, sizeof(knot_rdata_item_t) * desc->length);
-
- ret = knot_rdata_set_items(rdata, items, desc->length);
- if (ret != KNOT_EOK) {
- dbg_tsig("TSIG: rdata_set_items returned %s\n",
- knot_strerror(ret));
- knot_rrset_free(&tmp_tsig);
- knot_rdata_free(&rdata);
- free(items);
- return ret;
- }
- free(items);
+ /* Create rdata for TSIG RR. */
+ tsig_create_rdata(tmp_tsig, knot_tsig_digest_length(key->algorithm), 0);
+ tsig_rdata_set_alg(tmp_tsig, key->algorithm);
tsig_rdata_store_current_time(tmp_tsig);
tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
-
+
/* Create wire to be signed. */
size_t wire_len = prev_digest_len + to_sign_len
+ KNOT_TSIG_TIMERS_LENGTH + 2;
uint8_t *wire = malloc(wire_len);
if (!wire) {
ERR_ALLOC_FAILED;
- knot_rrset_free(&tmp_tsig);
- knot_rdata_deep_free(&rdata, KNOT_RRTYPE_TSIG, 0);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
return KNOT_ENOMEM;
}
memset(wire, 0, wire_len);
@@ -692,69 +614,65 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
tmp_tsig);
dbg_tsig_detail("Previous digest: \n");
- dbg_tsig_hex_detail(prev_digest, prev_digest_len);
+ dbg_tsig_hex_detail((char *)prev_digest, prev_digest_len);
dbg_tsig_detail("Timers: \n");
- dbg_tsig_hex_detail(wire + prev_digest_len + *msg_len,
+ dbg_tsig_hex_detail((char *)(wire + prev_digest_len + *msg_len),
KNOT_TSIG_TIMERS_LENGTH);
+ int ret = KNOT_ERROR;
ret = knot_tsig_compute_digest(wire, wire_len,
digest_tmp, &digest_tmp_len, key);
-
+
/* No matter how the function did, this data is no longer needed. */
free(wire);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
*digest_len = 0;
return ret;
}
-
+
if (digest_tmp_len > *digest_len) {
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
*digest_len = 0;
return KNOT_ESPACE;
}
/* Set the MAC. */
tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);
-
- /* Set algorithm. */
- tsig_rdata_set_alg(tmp_tsig, key->algorithm);
-
+
/* Set original id. */
tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
- /* Set TSIG error. */
- tsig_rdata_set_tsig_error(tmp_tsig, 0);
-
/* Set other data. */
tsig_rdata_set_other_data(tmp_tsig, 0, NULL);
dbg_tsig_verb("Message max length: %zu, message length: %zu\n",
msg_max_len, *msg_len);
- size_t tsig_wire_size = msg_max_len - *msg_len;
- int rr_count = 0;
+ size_t tsig_wire_size = 0;
+ uint16_t rr_count = 0;
ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len,
- &tsig_wire_size, &rr_count);
+ &tsig_wire_size, msg_max_len - *msg_len,
+ &rr_count, NULL);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
*digest_len = 0;
return ret;
}
/* This should not happen, at least one rr has to be converted. */
if (rr_count == 0) {
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
return KNOT_EINVAL;
}
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
*msg_len += tsig_wire_size;
uint16_t arcount = knot_wire_get_arcount(msg);
knot_wire_set_arcount(msg, ++arcount);
-
+
memcpy(digest, digest_tmp, digest_tmp_len);
*digest_len = digest_tmp_len;
@@ -765,7 +683,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
const uint8_t *request_mac,
size_t request_mac_len,
- const knot_key_t *tsig_key,
+ const knot_tsig_key_t *tsig_key,
uint64_t prev_time_signed,
int use_times)
{
@@ -812,7 +730,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
memset(wire_to_sign, 0, sizeof(uint8_t) * size);
memcpy(wire_to_sign, wire, size);
-
+
/* Restore message id. */
knot_wire_set_id(wire_to_sign, tsig_rdata_orig_id(tsig_rr));
@@ -823,16 +741,16 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
size_t digest_tmp_len = 0;
assert(tsig_rr->rdata);
-
+
if (use_times) {
- ret = knot_tsig_create_sign_wire_next(wire_to_sign, size,
+ ret = knot_tsig_create_sign_wire_next(wire_to_sign, size,
request_mac, request_mac_len,
- digest_tmp, &digest_tmp_len,
+ digest_tmp, &digest_tmp_len,
tsig_rr, tsig_key);
} else {
- ret = knot_tsig_create_sign_wire(wire_to_sign, size,
+ ret = knot_tsig_create_sign_wire(wire_to_sign, size,
request_mac, request_mac_len,
- digest_tmp, &digest_tmp_len,
+ digest_tmp, &digest_tmp_len,
tsig_rr, tsig_key);
}
@@ -851,23 +769,23 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
/*!< \todo move to function. */
const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig_rr);
- tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
+ knot_tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
/*! \todo [TSIG] TRUNCATION */
uint16_t mac_length = tsig_rdata_mac_length(tsig_rr);
const uint8_t *tsig_mac = tsig_rdata_mac(tsig_rr);
- if (mac_length != tsig_alg_digest_length(alg)) {
+ if (mac_length != knot_tsig_digest_length(alg)) {
dbg_tsig("TSIG: calculated digest length and given length do "
"not match!\n");
return KNOT_TSIG_EBADSIG;
}
dbg_tsig_verb("TSIG: calc digest :\n");
- dbg_tsig_hex_verb(digest_tmp, digest_tmp_len);
+ dbg_tsig_hex_verb((char *)digest_tmp, digest_tmp_len);
dbg_tsig_verb("TSIG: given digest:\n");
- dbg_tsig_hex_verb(tsig_mac, mac_length);
+ dbg_tsig_hex_verb((char *)tsig_mac, mac_length);
if (strncasecmp((char *)(tsig_mac), (char *)digest_tmp,
mac_length) != 0) {
@@ -879,7 +797,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
int knot_tsig_server_check(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
- const knot_key_t *tsig_key)
+ const knot_tsig_key_t *tsig_key)
{
dbg_tsig("tsig_server_check()\n");
return knot_tsig_check_digest(tsig_rr, wire, size, NULL, 0, tsig_key,
@@ -889,7 +807,7 @@ int knot_tsig_server_check(const knot_rrset_t *tsig_rr,
int knot_tsig_client_check(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
const uint8_t *request_mac, size_t request_mac_len,
- const knot_key_t *tsig_key,
+ const knot_tsig_key_t *tsig_key,
uint64_t prev_time_signed)
{
dbg_tsig("tsig_client_check()\n");
@@ -902,14 +820,13 @@ int knot_tsig_client_check_next(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
const uint8_t *prev_digest,
size_t prev_digest_len,
- const knot_key_t *tsig_key,
+ const knot_tsig_key_t *tsig_key,
uint64_t prev_time_signed)
{
dbg_tsig("tsig_client_check_next()\n");
return knot_tsig_check_digest(tsig_rr, wire, size, prev_digest,
prev_digest_len, tsig_key,
prev_time_signed, 1);
- return KNOT_ENOTSUP;
}
int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
@@ -936,52 +853,31 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
knot_dname_free(&key_name);
return KNOT_ENOMEM;
}
-
+
/* Already referenced in tmp_tsig, release. */
knot_dname_release(key_name);
- /* Create rdata for TSIG RR. */
- knot_rdata_t *rdata = knot_rdata_new();
- if (!rdata) {
- dbg_tsig("TSIG: rdata = NULL\n");
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
- return KNOT_ENOMEM;
- }
-
- knot_rrset_add_rdata(tmp_tsig, rdata);
-
- /* Create items for TSIG RR. */
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(KNOT_RRTYPE_TSIG);
- assert(desc);
-
- knot_rdata_item_t *items =
- malloc(sizeof(knot_rdata_item_t) * desc->length);
- if (items == NULL) {
- dbg_tsig("TSIG: items = NULL\n");
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
- return KNOT_ENOMEM;
- }
-
- memset(items, 0, sizeof(knot_rdata_item_t) * desc->length);
-
- int ret = knot_rdata_set_items(rdata, items, desc->length);
- free(items);
- if (ret != KNOT_EOK) {
- dbg_tsig("TSIG: rdata_set_items returned %s\n",
- knot_strerror(ret));
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
- return ret;
- }
-
knot_dname_t *alg_name =
knot_dname_deep_copy(tsig_rdata_alg_name(tsig_rr));
if (alg_name == NULL) {
dbg_tsig("TSIG: failed to copy alg name\n");
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
+ return KNOT_ERROR;
+ }
+
+
+ /* Create rdata for TSIG RR. */
+ knot_tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
+ if (alg == KNOT_TSIG_ALG_NULL) {
+ dbg_tsig("TSIG: refusing to use NULL algorithm\n");
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
+ knot_dname_free(&alg_name);
return KNOT_ERROR;
}
+ assert(tsig_rcode != KNOT_RCODE_BADTIME);
+ tsig_create_rdata(tmp_tsig, 0, tsig_rcode); /* No digest. */
+
tsig_rdata_set_alg_name(tmp_tsig, alg_name);
tsig_rdata_set_time_signed(tmp_tsig, tsig_rdata_time_signed(tsig_rr));
@@ -995,27 +891,26 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
/* Set original ID */
tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
- /* Set error */
- tsig_rdata_set_tsig_error(tmp_tsig, tsig_rcode);
- assert(tsig_rcode != KNOT_TSIG_RCODE_BADTIME);
/* Set other len. */
tsig_rdata_set_other_data(tmp_tsig, 0, 0);
- size_t tsig_wire_len = msg_max_len - *msg_len;
- int rr_count = 0;
+ size_t tsig_wire_len = 0;
+ uint16_t rr_count = 0;
/* Write RRSet to wire */
+ int ret = KNOT_ERROR;
ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len,
- &tsig_wire_len, &rr_count);
+ &tsig_wire_len, msg_max_len - *msg_len,
+ &rr_count, NULL);
if (ret != KNOT_EOK) {
dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
return ret;
}
/* key_name already referenced in RRSet, no need to free separately. */
- knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tmp_tsig, 1, 1);
*msg_len += tsig_wire_len;
@@ -1024,4 +919,3 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
return KNOT_EOK;
}
-
diff --git a/src/libknot/tsig-op.h b/src/libknot/tsig-op.h
index 07a84a8..812aebf 100644
--- a/src/libknot/tsig-op.h
+++ b/src/libknot/tsig-op.h
@@ -31,6 +31,7 @@
#include "tsig.h"
#include "rrset.h"
+#include "sign/key.h"
/*!
* \brief Generate TSIG signature of a message.
@@ -63,7 +64,7 @@
int knot_tsig_sign(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
const uint8_t *request_mac, size_t request_mac_len,
uint8_t *digest, size_t *digest_len,
- const knot_key_t *key, uint16_t tsig_rcode,
+ const knot_tsig_key_t *key, uint16_t tsig_rcode,
uint64_t request_time_signed);
/*!
@@ -97,7 +98,7 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
const uint8_t *prev_digest, size_t prev_digest_len,
uint8_t *digest, size_t *digest_len,
- const knot_key_t *key, uint8_t *to_sign,
+ const knot_tsig_key_t *key, uint8_t *to_sign,
size_t to_sign_len);
/*!
@@ -115,7 +116,7 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
*/
int knot_tsig_server_check(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
- const knot_key_t *tsig_key);
+ const knot_tsig_key_t *tsig_key);
/*!
* \brief Checks incoming response.
@@ -135,7 +136,7 @@ int knot_tsig_server_check(const knot_rrset_t *tsig_rr,
int knot_tsig_client_check(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
const uint8_t *request_mac, size_t request_mac_len,
- const knot_key_t *key,
+ const knot_tsig_key_t *key,
uint64_t prev_time_signed);
/*!
@@ -157,7 +158,7 @@ int knot_tsig_client_check_next(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
const uint8_t *prev_digest,
size_t prev_digest_len,
- const knot_key_t *key,
+ const knot_tsig_key_t *key,
uint64_t prev_time_signed);
int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
diff --git a/src/libknot/tsig.c b/src/libknot/tsig.c
index a4a8f1b..fd59709 100644
--- a/src/libknot/tsig.c
+++ b/src/libknot/tsig.c
@@ -14,9 +14,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
+#include <inttypes.h>
#include <assert.h>
#include <time.h>
@@ -25,296 +27,225 @@
#include "common.h"
#include "util/utils.h"
#include "rrset.h"
-#include "rdata.h"
#include "dname.h"
-
-/*! \brief TSIG algorithms table. */
-#define TSIG_ALG_TABLE_SIZE 8
-static knot_lookup_table_t tsig_alg_table[TSIG_ALG_TABLE_SIZE] = {
- { KNOT_TSIG_ALG_NULL, "gss-tsig." },
- { KNOT_TSIG_ALG_HMAC_MD5, "hmac-md5.sig-alg.reg.int." },
- { KNOT_TSIG_ALG_HMAC_SHA1, "hmac-sha1." },
- { KNOT_TSIG_ALG_HMAC_SHA224, "hmac-sha224." },
- { KNOT_TSIG_ALG_HMAC_SHA256, "hmac-sha256." },
- { KNOT_TSIG_ALG_HMAC_SHA384, "hmac-sha384." },
- { KNOT_TSIG_ALG_HMAC_SHA512, "hmac-sha512." },
- { KNOT_TSIG_ALG_NULL, NULL }
-};
-
-int tsig_rdata_init(knot_rrset_t *tsig)
+#include "consts.h"
+
+/*! \brief TSIG field offsets. */
+typedef enum tsig_off_t {
+ TSIG_ALGNAME_O = 0,
+ TSIG_TSIGNED_O,
+ TSIG_FUDGE_O,
+ TSIG_MACLEN_O,
+ TSIG_MAC_O,
+ TSIG_ORIGID_O,
+ TSIG_ERROR_O,
+ TSIG_OLEN_O,
+ TSIG_OTHER_O
+} tsig_off_t;
+
+/* Helpers for r offset calculation. */
+#define TSIG_NAMELEN (sizeof(knot_dname_t*))
+#define TSIG_OTHER_MAXLEN (3 * sizeof(uint16_t))
+#define TSIG_OFF_MACLEN (TSIG_NAMELEN + 4 * sizeof(uint16_t))
+#define TSIG_FIXED_RDLEN (TSIG_NAMELEN + 11 * sizeof(uint16_t))
+
+/*!
+ * \brief Seek offset of a TSIG RR field.
+ *
+ * \param rr TSIG RR.
+ * \param id Field index.
+ * \param nb Required number of bytes after the offset (for boundaries check).
+ * \return pointer to field on wire or NULL.
+ */
+static uint8_t* tsig_rdata_seek(const knot_rrset_t *rr, tsig_off_t id, size_t nb)
{
- if (!tsig) {
- return KNOT_EINVAL;
+ uint8_t *rd = knot_rrset_get_rdata(rr, 0);
+ if (rd == NULL) {
+ return NULL;
}
- /* Initializes rdata. */
- tsig->rdata = knot_rdata_new();
- if (!tsig->rdata) {
- return KNOT_ENOMEM;
+ /* Check if fixed part is readable. */
+ uint16_t lim = rrset_rdata_item_size(rr, 0);
+ if (lim < TSIG_NAMELEN + 5 * sizeof(uint16_t)) {
+ dbg_tsig("TSIG: rdata: not enough items "
+ "(has %"PRIu16", min %zu).\n",
+ lim, TSIG_NAMELEN + 5 * sizeof(uint16_t));
+ return NULL;
}
- tsig->rdata->items =
- malloc(sizeof(knot_rdata_item_t) * KNOT_TSIG_ITEM_COUNT);
- if (!tsig->rdata->items) {
- return KNOT_ENOMEM;
+ /* Not pretty, but fast. */
+ uint8_t *bp = rd;
+ switch(id) {
+ case TSIG_ALGNAME_O: break;
+ case TSIG_TSIGNED_O: rd += TSIG_NAMELEN; break;
+ case TSIG_FUDGE_O: rd += TSIG_NAMELEN + 3 * sizeof(uint16_t); break;
+ case TSIG_MACLEN_O: rd += TSIG_NAMELEN + 4 * sizeof(uint16_t); break;
+ case TSIG_MAC_O: rd += TSIG_NAMELEN + 5 * sizeof(uint16_t); break;
+ case TSIG_ORIGID_O:
+ rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
+ rd += knot_wire_read_u16(rd) + sizeof(uint16_t);
+ break;
+
+ case TSIG_ERROR_O:
+ rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
+ rd += knot_wire_read_u16(rd) + 2 * sizeof(uint16_t);
+ break;
+ case TSIG_OLEN_O:
+ rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
+ rd += knot_wire_read_u16(rd) + 3 * sizeof(uint16_t);
+ break;
+ case TSIG_OTHER_O:
+ rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
+ rd += knot_wire_read_u16(rd) + 4 * sizeof(uint16_t);
+ break;
+ }
+
+ /* Check remaining bytes. */
+ if (rd + nb > bp + lim) {
+ dbg_tsig("TSIG: rdata: not enough items (needs %zu, has %u).\n",
+ (rd-bp)+nb, lim);
+ return NULL;
}
- memset(tsig->rdata->items, 0,
- sizeof(knot_rdata_item_t) * KNOT_TSIG_ITEM_COUNT);
+ return rd;
+}
+
+static int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error)
+{
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ERROR_O, sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
+ }
+ knot_wire_write_u16(rd, tsig_error);
return KNOT_EOK;
}
-int tsig_rdata_set_alg_name(knot_rrset_t *tsig, knot_dname_t *alg_name)
+int tsig_create_rdata(knot_rrset_t *rr, uint16_t maclen, uint16_t tsig_err)
{
- if (!tsig) {
+ if (!rr) {
return KNOT_EINVAL;
}
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
+ /* We already checked rr and know rdlen > 0, no need to check rets. */
+ size_t rdlen = TSIG_FIXED_RDLEN + maclen;
+ if (tsig_err != KNOT_RCODE_BADTIME) {
+ rdlen -= TSIG_OTHER_MAXLEN;
}
- assert(knot_rdata_item_count(rdata) >= 1);
+ uint8_t *rd = knot_rrset_create_rdata(rr, rdlen);
+ memset(rd, 0, rdlen);
- knot_dname_t *alg_name_copy = knot_dname_deep_copy(alg_name);
- if (!alg_name_copy) {
- return KNOT_ENOMEM;
- }
+ /* Set MAC variable length in advance. */
+ rd += TSIG_OFF_MACLEN;
+ knot_wire_write_u16(rd, maclen);
- knot_rdata_item_set_dname(rdata, 0, alg_name_copy);
-
- /* Release the dname. We want it to have 1 reference only. */
- knot_dname_release(alg_name_copy);
+ /* Set error. */
+ tsig_rdata_set_tsig_error(rr, tsig_err);
return KNOT_EOK;
}
-int tsig_rdata_set_alg(knot_rrset_t *tsig, tsig_algorithm_t alg)
+int tsig_rdata_set_alg_name(knot_rrset_t *tsig, knot_dname_t *alg_name)
{
- if (!tsig) {
- return KNOT_EINVAL;
- }
-
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
- }
- assert(knot_rdata_item_count(rdata) >= 1);
-
- const char *alg_str = tsig_alg_to_str(alg);
- knot_dname_t *alg_name_copy = knot_dname_new_from_str(alg_str,
- strlen(alg_str),
- NULL);
- if (!alg_name_copy) {
- return KNOT_ENOMEM;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ALGNAME_O, TSIG_NAMELEN);
+ if (!rd) {
+ return KNOT_ERROR;
}
-
- knot_rdata_item_set_dname(rdata, 0, alg_name_copy);
-
- /* Release the dname. We want it to have 1 reference only. */
- knot_dname_release(alg_name_copy);
+ memcpy(rd, &alg_name, sizeof(knot_dname_t*));
+ knot_dname_retain(alg_name);
return KNOT_EOK;
}
-int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time)
+int tsig_rdata_set_alg(knot_rrset_t *tsig, knot_tsig_algorithm_t alg)
{
- if (!tsig) {
- return KNOT_EINVAL;
- }
-
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
- }
- assert(knot_rdata_item_count(rdata) >= 2);
+ const char *s = tsig_alg_to_str(alg);
+ knot_dname_t *alg_name = knot_dname_new_from_str(s, strlen(s), NULL);
+ int ret = tsig_rdata_set_alg_name(tsig, alg_name);
+ knot_dname_release(alg_name);
+ return ret;
+}
- /* Create the wire format. */
- uint16_t *wire = malloc(sizeof(uint8_t) * 6 + sizeof(uint16_t));
- if (!wire) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
+int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time)
+{
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_TSIGNED_O, 3*sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
}
- /* Write the length - 6. */
- wire[0] = 6;
- knot_wire_write_u48((uint8_t *)(wire + 1), time);
-
- knot_rdata_item_set_raw_data(rdata, 1, wire);
-
+ knot_wire_write_u48(rd, time);
return KNOT_EOK;
}
int tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge)
{
- if (!tsig) {
- return KNOT_EINVAL;
- }
-
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_FUDGE_O, sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
}
- assert(knot_rdata_item_count(rdata) >= 3);
-
- /* Create the wire format. */
- uint16_t *wire = malloc(sizeof(uint8_t) * 2 + sizeof(uint16_t));
- if (!wire) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
- }
-
- /* Write the length - 2. */
- wire[0] = sizeof(uint16_t);
- knot_wire_write_u16((uint8_t *)(wire + 1), fudge);
-
- knot_rdata_item_set_raw_data(rdata, 2, wire);
+ knot_wire_write_u16(rd, fudge);
return KNOT_EOK;
}
int tsig_rdata_set_mac(knot_rrset_t *tsig, uint16_t length, const uint8_t *mac)
{
- if (!tsig) {
- return KNOT_EINVAL;
- }
-
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_MAC_O, length);
+ if (!rd) {
+ return KNOT_ERROR;
}
- assert(knot_rdata_item_count(rdata) >= 4);
- /* Create the wire format. */
- uint16_t *wire = malloc(sizeof(uint8_t) * length + 2 * sizeof(uint16_t));
- if (!wire) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
- }
+ /*! \note Cannot change length, as rdata is already preallocd. */
- /* Write the length. */
- wire[0] = length + sizeof(uint16_t);
- knot_wire_write_u16((uint8_t *)(wire + 1), length);
/* Copy the actual MAC. */
- memcpy((uint8_t *)(wire + 2), mac, sizeof(uint8_t) * length);
- knot_rdata_item_set_raw_data(rdata, 3, wire);
-
+ memcpy(rd, mac, length);
return KNOT_EOK;
}
int tsig_rdata_set_orig_id(knot_rrset_t *tsig, uint16_t id)
{
- if (!tsig) {
- return KNOT_EINVAL;
- }
-
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
- }
- assert(knot_rdata_item_count(rdata) >= 5);
-
- /* Create the wire format. */
- uint16_t *wire = malloc(sizeof(uint8_t) * 2 + sizeof(uint16_t));
- if (!wire) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ORIGID_O, sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
}
/* Write the length - 2. */
- wire[0] = sizeof(uint16_t);
- knot_wire_write_u16((uint8_t *)(wire + 1), id);
-
- knot_rdata_item_set_raw_data(rdata, 4, wire);
-
+ knot_wire_write_u16(rd, id);
return KNOT_EOK;
}
-int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error)
-{
- if (!tsig) {
- return KNOT_EINVAL;
- }
-
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
- }
- assert(knot_rdata_item_count(rdata) >= 6);
-
- /* Create the wire format. */
- uint16_t *wire = malloc(sizeof(uint8_t) * 2 + sizeof(uint16_t));
- if (!wire) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
- }
-
- /* Write the length - 2. */
- wire[0] = sizeof(uint16_t);
- knot_wire_write_u16((uint8_t *)(wire + 1), tsig_error);
-
- knot_rdata_item_set_raw_data(rdata, 5, wire);
-
- return KNOT_EOK;
-}
-
-int tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t length,
+int tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t len,
const uint8_t *other_data)
{
- if (!tsig) {
+ if (len > TSIG_OTHER_MAXLEN) {
+ dbg_tsig("TSIG: rdata: other len > %zu B\n", TSIG_OTHER_MAXLEN);
return KNOT_EINVAL;
}
- knot_rdata_t *rdata = knot_rrset_get_rdata(tsig);
- if (!rdata) {
- return KNOT_EINVAL;
- }
- assert(knot_rdata_item_count(rdata) >= 6);
-
- /* Create the wire format. */
- uint16_t *wire = malloc(sizeof(uint8_t) * length + 2 * sizeof(uint16_t));
- if (!wire) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_OLEN_O, len+sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
}
/* Write the length. */
- wire[0] = length + 2;
- knot_wire_write_u16((uint8_t *)(wire + 1), length);
- /* Copy the actual data. */
- memcpy(wire + 2, other_data, sizeof(uint8_t) * length);
- knot_rdata_item_set_raw_data(rdata, 6, wire);
+ knot_wire_write_u16(rd, len);
+ /* Copy the actual data. */
+ memcpy(rd + sizeof(uint16_t), other_data, len);
return KNOT_EOK;
}
const knot_dname_t *tsig_rdata_alg_name(const knot_rrset_t *tsig)
{
- if (!tsig) {
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ALGNAME_O, TSIG_NAMELEN);
+ if (!rd) {
return NULL;
}
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
- dbg_tsig("TSIG: rdata: alg name: no rdata.\n");
- return NULL;
- }
-
- if (knot_rdata_item_count(rdata) < 1) {
- dbg_tsig("TSIG: rdata: alg name: not enough items.\n");
- return NULL;
- }
-
- return knot_rdata_item(rdata, 0)->dname;
+ return *((knot_dname_t**)rd);
}
-tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
+knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
{
- if (!tsig) {
- return KNOT_TSIG_ALG_NULL;
- }
-
/* Get the algorithm name. */
const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig);
if (!alg_name) {
@@ -329,183 +260,87 @@ tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
return KNOT_TSIG_ALG_NULL;
}
- knot_lookup_table_t *item = knot_lookup_by_name(tsig_alg_table, name);
+ knot_lookup_table_t *item = knot_lookup_by_name(
+ knot_tsig_alg_domain_names, name);
free(name);
if (!item) {
dbg_tsig("TSIG: rdata: unknown algorithm.\n");
return KNOT_TSIG_ALG_NULL;
}
-
return item->id;
}
uint64_t tsig_rdata_time_signed(const knot_rrset_t *tsig)
{
- /*! \note How about assert. Or maybe change API??? */
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
+ /*! \todo How to return invalid value? */
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_TSIGNED_O, 3*sizeof(uint16_t));
+ if (!rd) {
return 0;
}
-
- if (knot_rdata_item_count(rdata) < 2) {
- return 0;
- }
-
- uint16_t *wire = knot_rdata_item(rdata, 1)->raw_data;
- assert(wire[0] == 6);
- /* Skip the size. */
- wire++;
-
- return knot_wire_read_u48((uint8_t *)wire);
+ return knot_wire_read_u48(rd);
}
uint16_t tsig_rdata_fudge(const knot_rrset_t *tsig)
{
- /*! \note How about assert. Or maybe change API??? */
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
- return 0;
- }
-
- if (knot_rdata_item_count(rdata) < 3) {
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_FUDGE_O, sizeof(uint16_t));
+ if (!rd) {
return 0;
}
-
- uint16_t *wire = knot_rdata_item(rdata, 2)->raw_data;
- assert(wire[0] == 2);
- /* Skip the size. */
- wire++;
-
- return knot_wire_read_u16((uint8_t *)wire);
+ return knot_wire_read_u16(rd);
}
const uint8_t *tsig_rdata_mac(const knot_rrset_t *tsig)
{
- /*! \note How about assert. Or maybe change API??? */
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
- return 0;
- }
-
- if (knot_rdata_item_count(rdata) < 4) {
- return 0;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_MAC_O, 0);
+ if (!rd) {
+ return NULL;
}
-
- return (uint8_t*)(knot_rdata_item(rdata, 3)->raw_data + 2);
+ return rd;
}
size_t tsig_rdata_mac_length(const knot_rrset_t *tsig)
{
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata || knot_rdata_item_count(rdata) < 4) {
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_MACLEN_O, sizeof(uint16_t));
+ if (!rd) {
return 0;
}
-
- return knot_wire_read_u16(
- (uint8_t *)(knot_rdata_item(rdata, 3)->raw_data + 1));
+ return knot_wire_read_u16(rd);
}
uint16_t tsig_rdata_orig_id(const knot_rrset_t *tsig)
{
- /*! \note How about assert. Or maybe change API??? */
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
- return 0;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ORIGID_O, sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
}
-
- if (knot_rdata_item_count(rdata) < 5) {
- return 0;
- }
-
- uint16_t *wire = knot_rdata_item(rdata, 4)->raw_data;
- assert(wire[0] == 2);
- /* Skip the size. */
- wire++;
-
- return knot_wire_read_u16((uint8_t *)wire);
+ return knot_wire_read_u16(rd);
}
uint16_t tsig_rdata_error(const knot_rrset_t *tsig)
{
- /*! \note How about assert. Or maybe change API??? */
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
- return 0;
- }
-
- if (knot_rdata_item_count(rdata) < 6) {
- return 0;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ERROR_O, sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
}
-
- uint16_t *wire = knot_rdata_item(rdata, 5)->raw_data;
- assert(wire[0] == 2);
- /* Skip the size. */
- wire++;
-
- return knot_wire_read_u16((uint8_t *)wire);
+ return knot_wire_read_u16(rd);
}
const uint8_t *tsig_rdata_other_data(const knot_rrset_t *tsig)
{
- /*! \note How about assert. Or maybe change API??? */
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
- return 0;
- }
-
- if (knot_rdata_item_count(rdata) < 7) {
- return 0;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_OTHER_O, 0);
+ if (!rd) {
+ return NULL;
}
-
- return (uint8_t *)(knot_rdata_item(rdata, 6)->raw_data + 2);
+ return rd;
}
uint16_t tsig_rdata_other_data_length(const knot_rrset_t *tsig)
{
- /*! \note How about assert. Or maybe change API??? */
- if (!tsig) {
- return 0;
- }
-
- const knot_rdata_t *rdata = knot_rrset_rdata(tsig);
- if (!rdata) {
- return 0;
- }
-
- if (knot_rdata_item_count(rdata) < 7) {
- return 0;
+ uint8_t *rd = tsig_rdata_seek(tsig, TSIG_OLEN_O, sizeof(uint16_t));
+ if (!rd) {
+ return KNOT_ERROR;
}
-
- return knot_wire_read_u16((uint8_t *)
- (knot_rdata_item(rdata, 6)->raw_data + 1));
+ return knot_wire_read_u16(rd);
}
int tsig_alg_from_name(const knot_dname_t *alg_name)
@@ -520,7 +355,7 @@ int tsig_alg_from_name(const knot_dname_t *alg_name)
}
knot_lookup_table_t *found =
- knot_lookup_by_name(tsig_alg_table, name);
+ knot_lookup_by_name(knot_tsig_alg_domain_names, name);
if (!found) {
dbg_tsig("Unknown algorithm: %s \n", name);
@@ -533,28 +368,6 @@ int tsig_alg_from_name(const knot_dname_t *alg_name)
return found->id;
}
-uint16_t tsig_alg_digest_length(tsig_algorithm_t alg)
-{
- switch (alg) {
- case KNOT_TSIG_ALG_GSS_TSIG:
- return KNOT_TSIG_ALG_DIG_LENGTH_GSS_TSIG;
- case KNOT_TSIG_ALG_HMAC_MD5:
- return KNOT_TSIG_ALG_DIG_LENGTH_HMAC_MD5;
- case KNOT_TSIG_ALG_HMAC_SHA1:
- return KNOT_TSIG_ALG_DIG_LENGTH_SHA1;
- case KNOT_TSIG_ALG_HMAC_SHA224:
- return KNOT_TSIG_ALG_DIG_LENGTH_SHA224;
- case KNOT_TSIG_ALG_HMAC_SHA256:
- return KNOT_TSIG_ALG_DIG_LENGTH_SHA256;
- case KNOT_TSIG_ALG_HMAC_SHA384:
- return KNOT_TSIG_ALG_DIG_LENGTH_SHA384;
- case KNOT_TSIG_ALG_HMAC_SHA512:
- return KNOT_TSIG_ALG_DIG_LENGTH_SHA512;
- default:
- return 0;
- } /* switch(alg) */
-}
-
size_t tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig)
{
if (tsig == NULL) {
@@ -579,6 +392,7 @@ size_t tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig)
size_t tsig_rdata_tsig_timers_length()
{
+ /*! \todo Cleanup */
return KNOT_TSIG_TIMERS_LENGTH;
}
@@ -594,25 +408,24 @@ int tsig_rdata_store_current_time(knot_rrset_t *tsig)
return KNOT_EOK;
}
-const char* tsig_alg_to_str(tsig_algorithm_t alg)
+const char* tsig_alg_to_str(knot_tsig_algorithm_t alg)
{
- for (unsigned i = 0; i < TSIG_ALG_TABLE_SIZE; ++i) {
- if (tsig_alg_table[i].id == alg) {
- return tsig_alg_table[i].name;
- }
- }
+ knot_lookup_table_t *item;
+
+ item = knot_lookup_by_id(knot_tsig_alg_domain_names, alg);
- return "";
+ if (item != NULL) {
+ return item->name;
+ } else {
+ return "";
+ }
}
-size_t tsig_wire_maxsize(const knot_key_t* key)
+size_t tsig_wire_maxsize(const knot_tsig_key_t *key)
{
- if (key == NULL) {
- return 0;
- }
-
size_t alg_name_size = strlen(tsig_alg_to_str(key->algorithm)) + 1;
+ /*! \todo Used fixed size as a base. */
return knot_dname_size(key->name) +
sizeof(uint16_t) + /* TYPE */
sizeof(uint16_t) + /* CLASS */
@@ -622,7 +435,7 @@ size_t tsig_wire_maxsize(const knot_key_t* key)
6 * sizeof(uint8_t) + /* Time signed */
sizeof(uint16_t) + /* Fudge */
sizeof(uint16_t) + /* MAC size */
- tsig_alg_digest_length(key->algorithm) + /* MAC */
+ knot_tsig_digest_length(key->algorithm) + /* MAC */
sizeof(uint16_t) + /* Original ID */
sizeof(uint16_t) + /* Error */
sizeof(uint16_t) + /* Other len */
@@ -634,7 +447,8 @@ size_t tsig_wire_actsize(const knot_rrset_t *tsig)
if (tsig == NULL) {
return 0;
}
-
+
+ /*! \todo Used fixed size as a base. */
return knot_dname_size(knot_rrset_owner(tsig)) +
sizeof(uint16_t) + /* TYPE */
sizeof(uint16_t) + /* CLASS */
@@ -653,10 +467,10 @@ size_t tsig_wire_actsize(const knot_rrset_t *tsig)
int tsig_rdata_is_ok(const knot_rrset_t *tsig)
{
+ /*! \todo Check size, needs to check variable-length fields. */
return (tsig
- && knot_rrset_rdata(tsig) != NULL
- && knot_rdata_item_count(knot_rrset_rdata(tsig)) >= 7
+ && knot_rrset_get_rdata(tsig, 0) != NULL
+ && tsig_rdata_seek(tsig, TSIG_OTHER_O, 0) != NULL
&& tsig_rdata_alg_name(tsig) != NULL
&& tsig_rdata_time_signed(tsig) != 0);
}
-
diff --git a/src/libknot/tsig.h b/src/libknot/tsig.h
index cd5910f..258513e 100644
--- a/src/libknot/tsig.h
+++ b/src/libknot/tsig.h
@@ -30,41 +30,17 @@
#include <stdint.h>
#include "rrset.h"
+#include "binary.h"
#include "util/utils.h"
+#include "libknot/consts.h"
-/* The assigned numbers should not begin with 0 - reserved for error. */
-enum tsig_algorithm {
- KNOT_TSIG_ALG_NULL = 0,
- KNOT_TSIG_ALG_GSS_TSIG = 128, /*!< \brief gss-tsig. */
- KNOT_TSIG_ALG_HMAC_MD5, /*!< \brief HMAC-MD5.SIG-ALG.REG.INT. */
- KNOT_TSIG_ALG_HMAC_SHA1, /*!< \brief hmac-sha1. */
- KNOT_TSIG_ALG_HMAC_SHA224, /*!< \brief hmac-sha224. */
- KNOT_TSIG_ALG_HMAC_SHA256, /*!< \brief hmac-sha256. */
- KNOT_TSIG_ALG_HMAC_SHA384, /*!< \brief hmac-sha384. */
- KNOT_TSIG_ALG_HMAC_SHA512 /*!< \brief hmac-sha512. */
+struct knot_tsig_key {
+ knot_dname_t *name;
+ knot_tsig_algorithm_t algorithm;
+ knot_binary_t secret;
};
-typedef enum tsig_algorithm tsig_algorithm_t;
-
-struct knot_key {
- knot_dname_t *name; /*!< Key name. */
- tsig_algorithm_t algorithm; /*!< Key algorithm. */
- char *secret; /*!< Key data. */
- size_t secret_size; /*!< Key length. */
-};
-
-typedef struct knot_key knot_key_t;
-
-/*!< \todo FIND ALG LENGTHS */
-enum tsig_algorithm_digest_length {
- KNOT_TSIG_ALG_DIG_LENGTH_GSS_TSIG = 0,
- KNOT_TSIG_ALG_DIG_LENGTH_HMAC_MD5 = 16,
- KNOT_TSIG_ALG_DIG_LENGTH_SHA1 = 20,
- KNOT_TSIG_ALG_DIG_LENGTH_SHA224 = 0,
- KNOT_TSIG_ALG_DIG_LENGTH_SHA256 = 32,
- KNOT_TSIG_ALG_DIG_LENGTH_SHA384 = 0,
- KNOT_TSIG_ALG_DIG_LENGTH_SHA512 = 0
-};
+typedef struct knot_tsig_key knot_tsig_key_t;
enum tsig_consts {
KNOT_TSIG_ITEM_COUNT = 7,
@@ -78,32 +54,24 @@ enum tsig_consts {
+ 6 // time signed
};
-/*! TSIG errors are defined in common/errcode.h
- * and present negative value of the TSIG error to
- * comply with other parts of the library.
- *
- * KNOT_TSIG_EBADSIG = -16
- * KNOT_TSIG_EBADKEY = -17
- * KNOT_TSIG_EBADTIME = -18
- */
-
/*!
* \note Uses the given domain name, do not deallocate it!
*/
+int tsig_create_rdata(knot_rrset_t *rr, uint16_t maclen, uint16_t tsig_err);
int tsig_rdata_set_alg_name(knot_rrset_t *tsig, knot_dname_t *alg_name);
-int tsig_rdata_set_alg(knot_rrset_t *tsig, tsig_algorithm_t alg);
+int tsig_rdata_set_alg(knot_rrset_t *tsig, knot_tsig_algorithm_t alg);
int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time);
int tsig_rdata_store_current_time(knot_rrset_t *tsig);
int tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge);
int tsig_rdata_set_mac(knot_rrset_t *tsig, uint16_t length,
const uint8_t *mac);
int tsig_rdata_set_orig_id(knot_rrset_t *tsig, uint16_t id);
-int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error);
+//int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error);
int tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t length,
const uint8_t *other_data);
const knot_dname_t *tsig_rdata_alg_name(const knot_rrset_t *tsig);
-tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig);
+knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig);
uint64_t tsig_rdata_time_signed(const knot_rrset_t *tsig);
uint16_t tsig_rdata_fudge(const knot_rrset_t *tsig);
const uint8_t *tsig_rdata_mac(const knot_rrset_t *tsig);
@@ -126,9 +94,7 @@ int tsig_alg_from_name(const knot_dname_t *name);
* \retval TSIG algorithm string name.
* \retval Empty string if undefined.
*/
-const char* tsig_alg_to_str(tsig_algorithm_t alg);
-
-uint16_t tsig_alg_digest_length(tsig_algorithm_t alg);
+const char* tsig_alg_to_str(knot_tsig_algorithm_t alg);
/*!
* \brief Return TSIG RRSET maximum wire size for given algorithm.
@@ -137,7 +103,7 @@ uint16_t tsig_alg_digest_length(tsig_algorithm_t alg);
*
* \return RRSET wire size.
*/
-size_t tsig_wire_maxsize(const knot_key_t *key);
+size_t tsig_wire_maxsize(const knot_tsig_key_t *key);
size_t tsig_wire_actsize(const knot_rrset_t *tsig);
int tsig_rdata_is_ok(const knot_rrset_t *tsig);
diff --git a/src/libknot/updates/changesets.c b/src/libknot/updates/changesets.c
index 5405726..1f7997c 100644
--- a/src/libknot/updates/changesets.c
+++ b/src/libknot/updates/changesets.c
@@ -14,13 +14,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "updates/changesets.h"
#include "libknot/common.h"
+#include "common/descriptor.h"
#include "rrset.h"
+#include "util/debug.h"
static const size_t KNOT_CHANGESET_COUNT = 5;
static const size_t KNOT_CHANGESET_STEP = 5;
@@ -41,21 +44,16 @@ static int knot_changeset_check_count(knot_rrset_t ***rrsets, size_t count,
size_t extra = (count - *allocated) % KNOT_CHANGESET_RRSET_STEP;
extra = (extra + 1) * KNOT_CHANGESET_RRSET_STEP;
- /* Allocate new memory block. */
+ /* Reallocate memory block. */
const size_t item_len = sizeof(knot_rrset_t *);
const size_t new_count = *allocated + extra;
- knot_rrset_t **rrsets_new = malloc(new_count * item_len);
- if (rrsets_new == NULL) {
+ void *tmp = realloc(*rrsets, new_count * item_len);
+ if (tmp == NULL) {
return KNOT_ENOMEM;
}
-
- /* Clear old memory block and copy old data. */
- memset(rrsets_new, 0, new_count * item_len);
- memcpy(rrsets_new, *rrsets, (*allocated) * item_len);
-
- /* Replace old rrsets. */
- free(*rrsets);
- *rrsets = rrsets_new;
+ *rrsets = tmp;
+ /* Init new data. */
+ memset(*rrsets + *allocated, 0, extra * item_len);
*allocated = new_count;
return KNOT_EOK;
@@ -66,12 +64,10 @@ static int knot_changeset_check_count(knot_rrset_t ***rrsets, size_t count,
static int knot_changeset_rrsets_match(const knot_rrset_t *rrset1,
const knot_rrset_t *rrset2)
{
- return knot_rrset_match(rrset1, rrset2, KNOT_RRSET_COMPARE_HEADER)
+ return knot_rrset_equal(rrset1, rrset2, KNOT_RRSET_COMPARE_HEADER)
&& (knot_rrset_type(rrset1) != KNOT_RRTYPE_RRSIG
- || knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(rrset1))
- == knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(rrset2)));
+ || knot_rrset_rdata_rrsig_type_covered(rrset1)
+ == knot_rrset_rdata_rrsig_type_covered(rrset2));
}
/*----------------------------------------------------------------------------*/
@@ -93,7 +89,7 @@ int knot_changeset_allocate(knot_changesets_t **changesets,
*changesets = NULL;
return KNOT_ENOMEM;
}
-
+
return KNOT_EOK;
}
@@ -130,12 +126,12 @@ int knot_changeset_add_rr(knot_rrset_t ***rrsets, size_t *count,
&& knot_changeset_rrsets_match((*rrsets)[*count - 1], rr)) {
// Create changesets exactly as they came, with possibly
// duplicate records
- if (knot_rrset_merge((void **)&(*rrsets)[*count - 1],
- (void **)&rr) != KNOT_EOK) {
+ if (knot_rrset_merge((*rrsets)[*count - 1],
+ rr) != KNOT_EOK) {
return KNOT_ERROR;
}
- knot_rrset_free(&rr);
+ knot_rrset_deep_free(&rr, 1, 0);
return KNOT_EOK;
} else {
return knot_changeset_add_rrset(rrsets, count, allocated, rr);
@@ -208,7 +204,7 @@ void knot_changeset_store_soa(knot_rrset_t **chg_soa,
uint32_t *chg_serial, knot_rrset_t *soa)
{
*chg_soa = soa;
- *chg_serial = knot_rdata_soa_serial(knot_rrset_rdata(soa));
+ *chg_serial = knot_rrset_rdata_soa_serial(soa);
}
/*----------------------------------------------------------------------------*/
@@ -308,17 +304,17 @@ void knot_free_changeset(knot_changeset_t **changeset)
int j;
for (j = 0; j < (*changeset)->add_count; ++j) {
- knot_rrset_deep_free(&(*changeset)->add[j], 1, 1, 1);
+ knot_rrset_deep_free(&(*changeset)->add[j], 1, 1);
}
free((*changeset)->add);
for (j = 0; j < (*changeset)->remove_count; ++j) {
- knot_rrset_deep_free(&(*changeset)->remove[j], 1, 1, 1);
+ knot_rrset_deep_free(&(*changeset)->remove[j], 1, 1);
}
free((*changeset)->remove);
- knot_rrset_deep_free(&(*changeset)->soa_from, 1, 1, 1);
- knot_rrset_deep_free(&(*changeset)->soa_to, 1, 1, 1);
+ knot_rrset_deep_free(&(*changeset)->soa_from, 1, 1);
+ knot_rrset_deep_free(&(*changeset)->soa_to, 1, 1);
free((*changeset)->data);
@@ -342,9 +338,9 @@ void knot_free_changesets(knot_changesets_t **changesets)
}
free((*changesets)->sets);
-
- knot_rrset_deep_free(&(*changesets)->first_soa, 1, 1, 1);
-
+
+ knot_rrset_deep_free(&(*changesets)->first_soa, 1, 1);
+
assert((*changesets)->changes == NULL);
free(*changesets);
@@ -361,7 +357,7 @@ int knot_changes_rrsets_reserve(knot_rrset_t ***rrsets,
if (rrsets == NULL || count == NULL || allocated == NULL) {
return KNOT_EINVAL;
}
-
+
if (*count + to_add <= *allocated) {
return KNOT_EOK;
}
@@ -397,7 +393,7 @@ int knot_changes_nodes_reserve(knot_node_t ***nodes,
if (nodes == NULL || count == NULL || allocated == NULL) {
return KNOT_EINVAL;
}
-
+
if (*count + 2 <= *allocated) {
return KNOT_EOK;
}
@@ -425,13 +421,13 @@ int knot_changes_nodes_reserve(knot_node_t ***nodes,
/*----------------------------------------------------------------------------*/
-int knot_changes_rdata_reserve(knot_rdata_t ***rdatas, uint16_t **types,
- int count, int *allocated, int to_add)
+int knot_changes_rdata_reserve(knot_rrset_t ***rdatas,
+ int count, int *allocated, int to_add)
{
- if (rdatas == NULL || types == NULL || allocated == NULL) {
+ if (rdatas == NULL || allocated == NULL) {
return KNOT_EINVAL;
}
-
+
if (count + to_add <= *allocated) {
return KNOT_EOK;
}
@@ -442,29 +438,19 @@ int knot_changes_rdata_reserve(knot_rdata_t ***rdatas, uint16_t **types,
}
/* Allocate new memory block. */
- knot_rdata_t **rdatas_new = malloc(new_count * sizeof(knot_rdata_t *));
+ knot_rrset_t **rdatas_new = malloc(new_count * sizeof(knot_rrset_t *));
if (rdatas_new == NULL) {
- return KNOT_ENOMEM;
- }
-
- uint16_t *types_new = malloc(new_count * sizeof(uint));
- if (types_new == NULL) {
- free(rdatas_new);
+ ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
}
/* Initialize new memory and copy old data. */
- memset(rdatas_new, 0, new_count * sizeof(knot_rdata_t *));
- memcpy(rdatas_new, *rdatas, (*allocated) * sizeof(knot_rdata_t *));
-
- memset(types_new, 0, new_count * sizeof(uint));
- memcpy(types_new, *types, (*allocated) * sizeof(uint));
+ memset(rdatas_new, 0, new_count * sizeof(knot_rrset_t *));
+ memcpy(rdatas_new, *rdatas, (*allocated) * sizeof(knot_rrset_t *));
/* Free old rdatas and switch pointers. */
free(*rdatas);
- free(*types);
*rdatas = rdatas_new;
- *types = types_new;
*allocated = new_count;
return KNOT_EOK;
@@ -472,24 +458,16 @@ int knot_changes_rdata_reserve(knot_rdata_t ***rdatas, uint16_t **types,
/*----------------------------------------------------------------------------*/
-void knot_changes_add_rdata(knot_rdata_t **rdatas, uint16_t *types,
- int *count, knot_rdata_t *rdata, uint16_t type)
+/*!< \note Always adds the whole RRSet = all rdata. */
+void knot_changes_add_rdata(knot_rrset_t **rdatas, int *count,
+ knot_rrset_t *rrset)
{
- if (rdatas == NULL || types == NULL || count == NULL || rdata == NULL) {
+ if (rdatas == NULL || count == NULL || rrset == NULL || rrset->rdata_count == 0) {
return;
}
- // Add all RDATAs from the chain!!
-
- knot_rdata_t *r = rdata;
- do {
-// dbg_xfrin_detail("Adding RDATA to RDATA list: %p\n", r);
- rdatas[*count] = r;
- types[*count] = type;
- ++*count;
-
- r = r->next;
- } while (r != NULL && r != rdata);
+ rdatas[*count] = rrset;
+ *count += 1;
}
/*----------------------------------------------------------------------------*/
@@ -522,25 +500,22 @@ int knot_changes_add_old_rrsets(knot_rrset_t **rrsets, int count,
if (rrsets[i] == NULL) {
continue;
}
-
+
knot_rrset_t *rrsigs = knot_rrset_get_rrsigs(rrsets[i]);
-
+
if (add_rdata) {
-
+
/* RDATA count in the RRSet. */
- int rdata_count = knot_rrset_rdata_rr_count(rrsets[i]);
-
+ int rdata_count = 1;
+
if (rrsigs != NULL) {
- /* Increment the RDATA count by the count of
+ /* Increment the RDATA count by the count of
* RRSIGs. */
- rdata_count += knot_rrset_rdata_rr_count(
- rrsigs);
+ rdata_count += 1;
}
-
+
/* Remove old RDATA. */
-
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
changes->old_rdata_count,
&changes->old_rdata_allocated,
rdata_count);
@@ -550,22 +525,20 @@ int knot_changes_add_old_rrsets(knot_rrset_t **rrsets, int count,
}
knot_changes_add_rdata(changes->old_rdata,
- changes->old_rdata_types,
&changes->old_rdata_count,
- knot_rrset_get_rdata(rrsets[i]),
- knot_rrset_type(rrsets[i]));
-
+ rrsets[i]);
+
knot_changes_add_rdata(changes->old_rdata,
- changes->old_rdata_types,
&changes->old_rdata_count,
- knot_rrset_get_rdata(rrsigs),
- KNOT_RRTYPE_RRSIG);
+ rrsigs);
}
-
+
/* Disconnect RRsigs from rrset. */
knot_rrset_set_rrsigs(rrsets[i], NULL);
changes->old_rrsets[changes->old_rrsets_count++] = rrsets[i];
- changes->old_rrsets[changes->old_rrsets_count++] = rrsigs;
+ if (rrsigs) {
+ changes->old_rrsets[changes->old_rrsets_count++] = rrsigs;
+ }
}
return KNOT_EOK;
@@ -597,25 +570,21 @@ int knot_changes_add_new_rrsets(knot_rrset_t **rrsets, int count,
if (rrsets[i] == NULL) {
continue;
}
-
+
if (add_rdata) {
- int rdata_count = knot_rrset_rdata_rr_count(rrsets[i]);
ret = knot_changes_rdata_reserve(&changes->new_rdata,
- &changes->new_rdata_types,
changes->new_rdata_count,
&changes->new_rdata_allocated,
- rdata_count);
+ 1);
if (ret != KNOT_EOK) {
return ret;
}
-
+
knot_changes_add_rdata(changes->new_rdata,
- changes->new_rdata_types,
&changes->new_rdata_count,
- knot_rrset_get_rdata(rrsets[i]),
- knot_rrset_type(rrsets[i]));
- }
-
+ rrsets[i]);
+ }
+
changes->new_rrsets[changes->new_rrsets_count++] = rrsets[i];
}
diff --git a/src/libknot/updates/changesets.h b/src/libknot/updates/changesets.h
index 4585abc..4edc387 100644
--- a/src/libknot/updates/changesets.h
+++ b/src/libknot/updates/changesets.h
@@ -76,10 +76,9 @@ typedef struct {
int old_rrsets_allocated;
/*!
- * Deleted after successful update.
+ * Deleted after successful update. Contains only relevant RDATA.
*/
- knot_rdata_t **old_rdata;
- uint16_t *old_rdata_types;
+ knot_rrset_t **old_rdata;
int old_rdata_count;
int old_rdata_allocated;
@@ -93,10 +92,9 @@ typedef struct {
int new_rrsets_allocated;
/*!
- * Deleted after failed update.
+ * Deleted after failed update. Contains only relevant RDATA.
*/
- knot_rdata_t **new_rdata;
- uint16_t *new_rdata_types;
+ knot_rrset_t **new_rdata;
int new_rdata_count;
int new_rdata_allocated;
@@ -174,11 +172,11 @@ int knot_changes_rrsets_reserve(knot_rrset_t ***rrsets,
int knot_changes_nodes_reserve(knot_node_t ***nodes,
int *count, int *allocated);
-int knot_changes_rdata_reserve(knot_rdata_t ***rdatas, uint16_t **types,
+int knot_changes_rdata_reserve(knot_rrset_t ***rdatas,
int count, int *allocated, int to_add);
-void knot_changes_add_rdata(knot_rdata_t **rdatas, uint16_t *types,
- int *count, knot_rdata_t *rdata, uint16_t type);
+void knot_changes_add_rdata(knot_rrset_t **rdatas, int *count,
+ knot_rrset_t *rrset);
/*!
* \note Also processes RRSIGs. May be switched by a parameter later, if needed.
diff --git a/src/libknot/updates/ddns.c b/src/libknot/updates/ddns.c
index 79b28fb..7f4f14f 100644
--- a/src/libknot/updates/ddns.c
+++ b/src/libknot/updates/ddns.c
@@ -14,16 +14,21 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
#include "updates/ddns.h"
#include "updates/changesets.h"
#include "util/debug.h"
#include "packet/packet.h"
+#include "common.h"
#include "consts.h"
#include "common/mempattern.h"
#include "nameserver/name-server.h" // ns_serial_compare() - TODO: extract
#include "updates/xfr-in.h"
+#include "common/descriptor.h"
/*----------------------------------------------------------------------------*/
// Copied from XFR - maybe extract somewhere else
@@ -37,7 +42,7 @@ static int knot_ddns_prereq_check_rrsets(knot_rrset_t ***rrsets,
if (ret < 0) {
return KNOT_ENOMEM;
}
-
+
*rrsets = (knot_rrset_t**)arr;
return KNOT_EOK;
@@ -55,7 +60,7 @@ static int knot_ddns_prereq_check_dnames(knot_dname_t ***dnames,
if (ret < 0) {
return KNOT_ENOMEM;
}
-
+
*dnames = (knot_dname_t**)arr;
return KNOT_EOK;
@@ -70,10 +75,9 @@ static int knot_ddns_add_prereq_rrset(const knot_rrset_t *rrset,
// check if such RRSet is not already there and merge if needed
int ret;
for (int i = 0; i < *count; ++i) {
- if (knot_rrset_match(rrset, (*rrsets)[i],
+ if (knot_rrset_equal(rrset, (*rrsets)[i],
KNOT_RRSET_COMPARE_HEADER) == 1) {
- ret = knot_rrset_merge((void **)&((*rrsets)[i]),
- (void **)&rrset);
+ ret = knot_rrset_merge((*rrsets)[i], rrset);
if (ret != KNOT_EOK) {
return ret;
} else {
@@ -132,13 +136,15 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs,
assert(rrset != NULL);
if (knot_rrset_ttl(rrset) != 0) {
+ dbg_ddns("ddns: add_prereq: Wrong TTL.\n");
return KNOT_EMALF;
}
int ret;
if (knot_rrset_class(rrset) == KNOT_CLASS_ANY) {
- if (knot_rrset_rdata(rrset) != NULL) {
+ if (knot_rrset_rdata_rr_count(rrset)) {
+ dbg_ddns("ddns: add_prereq: Extra data\n");
return KNOT_EMALF;
}
if (knot_rrset_type(rrset) == KNOT_RRTYPE_ANY) {
@@ -153,7 +159,8 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs,
&prereqs->exist_allocd);
}
} else if (knot_rrset_class(rrset) == KNOT_CLASS_NONE) {
- if (knot_rrset_rdata(rrset) != NULL) {
+ if (knot_rrset_rdata_rr_count(rrset)) {
+ dbg_ddns("ddns: add_prereq: Extra data\n");
return KNOT_EMALF;
}
if (knot_rrset_type(rrset) == KNOT_RRTYPE_ANY) {
@@ -173,6 +180,7 @@ static int knot_ddns_add_prereq(knot_ddns_prereq_t *prereqs,
&prereqs->exist_full_count,
&prereqs->exist_full_allocd);
} else {
+ dbg_ddns("ddns: add_prereq: Bad class.\n");
return KNOT_EMALF;
}
@@ -202,8 +210,8 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
&changeset->add_count, i);
dbg_ddns_detail("Removed RRSet from "
"chgset:\n");
- knot_rrset_dump(remove, 0);
- knot_rrset_deep_free(&remove, 1, 1, 1);
+ knot_rrset_dump(remove);
+ knot_rrset_deep_free(&remove, 1, 1);
}
} else if (knot_rrset_type(rr)
== knot_rrset_type(changeset->add[i])){
@@ -213,15 +221,14 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
assert(knot_rrset_class(rr) == KNOT_CLASS_NONE);
// Removing specific RR from a RRSet
- knot_rdata_t *rdata = knot_rrset_remove_rdata(
- changeset->add[i],
- knot_rrset_rdata(rr));
-
- dbg_ddns_detail("Removed RR from chgset: \n");
- knot_rdata_dump(rdata, knot_rrset_type(rr), 0);
+ int ret =
+ knot_rrset_remove_rr_using_rrset_del(changeset->add[i], rr);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("ddns: Could not remove RDATA from RRSet (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
- knot_rdata_deep_free(&rdata,
- knot_rrset_type(changeset->add[i]), 1);
// if the RRSet is empty, remove from changeset
if (knot_rrset_rdata_rr_count(changeset->add[i])
== 0) {
@@ -231,7 +238,7 @@ static int knot_ddns_check_remove_rr(knot_changeset_t *changeset,
&changeset->add_count, i);
dbg_ddns_detail("RRSet empty, removing."
"\n");
- knot_rrset_deep_free(&remove, 1, 1, 1);
+ knot_rrset_deep_free(&remove, 1, 1);
}
}
}
@@ -257,7 +264,7 @@ static int knot_ddns_add_update(knot_changeset_t *changeset,
* copy.
*/
*rrset_copy = NULL;
- ret = knot_rrset_deep_copy(rrset, rrset_copy, 0);
+ ret = knot_rrset_deep_copy(rrset, rrset_copy, 1);
if (ret != KNOT_EOK) {
return ret;
}
@@ -286,7 +293,7 @@ static int knot_ddns_add_update(knot_changeset_t *changeset,
ret = knot_ddns_check_remove_rr(changeset, *rrset_copy);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(rrset_copy, 1, 1);
return ret;
}
@@ -307,7 +314,7 @@ static int knot_ddns_check_exist(const knot_zone_contents_t *zone,
assert(zone != NULL);
assert(rrset != NULL);
assert(rcode != NULL);
- assert(knot_rrset_rdata(rrset) == NULL);
+ assert(knot_rrset_rdata_rr_count(rrset) == 0);
assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY);
assert(knot_rrset_ttl(rrset) == 0);
assert(knot_rrset_class(rrset) == KNOT_CLASS_ANY);
@@ -334,13 +341,13 @@ static int knot_ddns_check_exist(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_exist_full(const knot_zone_contents_t *zone,
- const knot_rrset_t *rrset,
+ const knot_rrset_t *rrset,
knot_rcode_t *rcode)
{
assert(zone != NULL);
assert(rrset != NULL);
assert(rcode != NULL);
- assert(knot_rrset_rdata(rrset) == NULL);
+ assert(knot_rrset_rdata_rr_count(rrset) == 0);
assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY);
assert(knot_rrset_ttl(rrset) == 0);
assert(knot_rrset_class(rrset) == KNOT_CLASS_ANY);
@@ -367,7 +374,7 @@ static int knot_ddns_check_exist_full(const knot_zone_contents_t *zone,
assert(knot_rrset_type(found) == knot_rrset_type(rrset));
assert(knot_dname_compare(knot_rrset_owner(found),
knot_rrset_owner(rrset)) == 0);
- if (knot_rrset_compare_rdata(found, rrset) <= 0) {
+ if (knot_rrset_rdata_equal(found, rrset) <= 0) {
*rcode = KNOT_RCODE_NXRRSET;
return KNOT_EPREREQ;
}
@@ -379,13 +386,13 @@ static int knot_ddns_check_exist_full(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_not_exist(const knot_zone_contents_t *zone,
- const knot_rrset_t *rrset,
+ const knot_rrset_t *rrset,
knot_rcode_t *rcode)
{
assert(zone != NULL);
assert(rrset != NULL);
assert(rcode != NULL);
- assert(knot_rrset_rdata(rrset) == NULL);
+ assert(knot_rrset_rdata_rr_count(rrset) == 0);
assert(knot_rrset_type(rrset) != KNOT_RRTYPE_ANY);
assert(knot_rrset_ttl(rrset) == 0);
assert(knot_rrset_class(rrset) == KNOT_CLASS_NONE);
@@ -404,7 +411,7 @@ static int knot_ddns_check_not_exist(const knot_zone_contents_t *zone,
} else if (knot_node_rrset(node, knot_rrset_type(rrset)) == NULL) {
return KNOT_EOK;
}
-
+
/* RDATA is always empty for simple RRset checks. */
*rcode = KNOT_RCODE_YXRRSET;
@@ -414,7 +421,7 @@ static int knot_ddns_check_not_exist(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_in_use(const knot_zone_contents_t *zone,
- const knot_dname_t *dname,
+ const knot_dname_t *dname,
knot_rcode_t *rcode)
{
assert(zone != NULL);
@@ -444,7 +451,7 @@ static int knot_ddns_check_in_use(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_not_in_use(const knot_zone_contents_t *zone,
- const knot_dname_t *dname,
+ const knot_dname_t *dname,
knot_rcode_t *rcode)
{
assert(zone != NULL);
@@ -474,7 +481,7 @@ static int knot_ddns_check_not_in_use(const knot_zone_contents_t *zone,
/* API functions */
/*----------------------------------------------------------------------------*/
-int knot_ddns_check_zone(const knot_zone_contents_t *zone,
+int knot_ddns_check_zone(const knot_zone_contents_t *zone,
const knot_packet_t *query, knot_rcode_t *rcode)
{
if (zone == NULL || query == NULL || rcode == NULL) {
@@ -511,7 +518,7 @@ int knot_ddns_process_prereqs(const knot_packet_t *query,
if (query == NULL || prereqs == NULL || rcode == NULL) {
return KNOT_EINVAL;
}
-
+
dbg_ddns("Processing prerequisities.\n");
// allocate space for the prerequisities
@@ -523,6 +530,8 @@ int knot_ddns_process_prereqs(const knot_packet_t *query,
for (int i = 0; i < knot_packet_answer_rrset_count(query); ++i) {
// we must copy the RRSets, because all those stored in the
// packet will be destroyed
+ dbg_ddns_detail("Creating prereqs from following RRSet:\n");
+ knot_rrset_dump(knot_packet_answer_rrset(query, i));
ret = knot_ddns_add_prereq(*prereqs,
knot_packet_answer_rrset(query, i),
knot_packet_qclass(query));
@@ -545,7 +554,7 @@ int knot_ddns_check_prereqs(const knot_zone_contents_t *zone,
knot_ddns_prereq_t **prereqs, knot_rcode_t *rcode)
{
int i, ret;
-
+
dbg_ddns("Checking 'exist' prerequisities.\n");
for (i = 0; i < (*prereqs)->exist_count; ++i) {
@@ -599,7 +608,7 @@ int knot_ddns_check_prereqs(const knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
static int knot_ddns_check_update(const knot_rrset_t *rrset,
- const knot_packet_t *query,
+ const knot_packet_t *query,
knot_rcode_t *rcode)
{
/* Accept both subdomain and dname match. */
@@ -618,7 +627,7 @@ static int knot_ddns_check_update(const knot_rrset_t *rrset,
return KNOT_EMALF;
}
} else if (knot_rrset_class(rrset) == KNOT_CLASS_ANY) {
- if (knot_rrset_rdata(rrset) != NULL
+ if (knot_rrset_rdata_rr_count(rrset)
|| (knot_rrtype_is_metatype(knot_rrset_type(rrset))
&& knot_rrset_type(rrset) != KNOT_RRTYPE_ANY)) {
*rcode = KNOT_RCODE_FORMERR;
@@ -658,7 +667,7 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
KNOT_RRTYPE_SOA);
knot_rrset_t *soa_begin = NULL;
knot_rrset_t *soa_end = NULL;
- ret = knot_rrset_deep_copy(soa, &soa_begin, 0);
+ ret = knot_rrset_deep_copy(soa, &soa_begin, 1);
if (ret == KNOT_EOK) {
knot_changeset_store_soa(&changeset->soa_from,
&changeset->serial_from, soa_begin);
@@ -668,7 +677,7 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
}
/* Current SERIAL */
- int64_t sn = knot_rdata_soa_serial(knot_rrset_rdata(soa_begin));
+ int64_t sn = knot_rrset_rdata_soa_serial(soa_begin);
int64_t sn_new;
/* Incremented SERIAL
* We must set it now to be able to compare SERIAL from SOAs in the
@@ -721,10 +730,9 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
* RRSet. This should be handled somehow.
*/
if (knot_rrset_type(rrset) == KNOT_RRTYPE_SOA
- && ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(rrset)),
+ && ns_serial_compare(knot_rrset_rdata_soa_serial(rrset),
sn_new) > 0) {
- sn_new = knot_rdata_soa_serial(knot_rrset_rdata(rrset));
+ sn_new = knot_rrset_rdata_soa_serial(rrset);
soa_end = (knot_rrset_t *)rrset_copy;
}
}
@@ -734,8 +742,12 @@ int knot_ddns_process_update(const knot_zone_contents_t *zone,
/* If not set */
assert(sn_new == (uint32_t)sn + 1);
ret = knot_rrset_deep_copy(soa, &soa_end, 1);
- knot_rdata_t *rd = knot_rrset_get_rdata(soa_end);
- knot_rdata_soa_serial_set(rd, sn_new);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("ddns: Could not copy SOA RRSet (%s).\n ",
+ knot_strerror(ret));
+ return ret;
+ }
+ knot_rrset_rdata_soa_serial_set(soa_end, sn_new);
}
knot_changeset_store_soa(&changeset->soa_to,
@@ -754,17 +766,17 @@ void knot_ddns_prereqs_free(knot_ddns_prereq_t **prereq)
int i;
for (i = 0; i < (*prereq)->exist_count; ++i) {
- knot_rrset_deep_free(&(*prereq)->exist[i], 1, 1, 1);
+ knot_rrset_deep_free(&(*prereq)->exist[i], 1, 1);
}
free((*prereq)->exist);
for (i = 0; i < (*prereq)->exist_full_count; ++i) {
- knot_rrset_deep_free(&(*prereq)->exist_full[i], 1, 1, 1);
+ knot_rrset_deep_free(&(*prereq)->exist_full[i], 1, 1);
}
free((*prereq)->exist_full);
for (i = 0; i < (*prereq)->not_exist_count; ++i) {
- knot_rrset_deep_free(&(*prereq)->not_exist[i], 1, 1, 1);
+ knot_rrset_deep_free(&(*prereq)->not_exist[i], 1, 1);
}
free((*prereq)->not_exist);
@@ -788,7 +800,7 @@ void knot_ddns_prereqs_free(knot_ddns_prereq_t **prereq)
static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
const knot_dname_t *owner,
- uint16_t type, const knot_rdata_t *rdata,
+ const knot_rrset_t *rr,
knot_rrset_t ***removed,
size_t *removed_count)
{
@@ -800,6 +812,7 @@ static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
*removed = (knot_rrset_t **)malloc(changeset->add_count
* sizeof(knot_rrset_t *));
if (*removed == NULL) {
+ ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
}
@@ -814,27 +827,30 @@ static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
dbg_ddns_verb("Removing possible redundant RRs from changeset.\n");
for (int i = 0; i < changeset->add_count; ++i) {
// Removing RR(s) from this owner
- if (knot_dname_compare(knot_rrset_owner(changeset->add[i]),
- owner) == 0) {
+dbg_ddns_exec_detail(
+ char *name = knot_dname_to_str(changeset->add[i]->owner);
+ dbg_ddns_detail("ddns: remove_rr2: Removing RR of type=%u owned by %s\n",
+ knot_rrset_type(changeset->add[i]), name);
+ free(name);
+);
+ if (knot_dname_compare_non_canon(knot_rrset_owner(changeset->add[i]),
+ owner) == 0) {
// Removing one or all RRSets
- if (rdata == NULL
- && (type == knot_rrset_type(changeset->add[i])
- || type == KNOT_RRTYPE_ANY)) {
+ if ((knot_rrset_rdata_rr_count(rr) == 0)
+ && (knot_rrset_type(rr) == knot_rrset_type(changeset->add[i])
+ || knot_rrset_type(rr) == KNOT_RRTYPE_ANY)) {
dbg_ddns_detail("Removing one or all RRSets\n");
- remove = knot_changeset_remove_rr(
- changeset->add,
- &changeset->add_count, i);
- } else if (type == knot_rrset_type(changeset->add[i])) {
+ remove = knot_changeset_remove_rr(
+ changeset->add,
+ &changeset->add_count, i);
+ } else if (knot_rrset_type(rr) ==
+ knot_rrset_type(changeset->add[i])) {
// Removing specific RR
- assert(rdata != NULL);
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
+ assert(knot_rrset_rdata_rr_count(rr) != 0);
// We must check if the RDATA match
- if (knot_rdata_compare(rdata,
- knot_rrset_rdata(changeset->add[i]),
- desc->wireformat)) {
+ if (knot_rrset_rdata_equal(rr,
+ changeset->add[i])) {
remove = knot_changeset_remove_rr(
changeset->add,
&changeset->add_count, i);
@@ -842,7 +858,7 @@ static int knot_ddns_check_remove_rr2(knot_changeset_t *changeset,
}
dbg_ddns_detail("Removed RRSet from chgset:\n");
- knot_rrset_dump(remove, 0);
+ knot_rrset_dump(remove);
(*removed)[(*removed_count)++] = remove;
}
}
@@ -861,19 +877,19 @@ static void knot_ddns_check_add_rr(knot_changeset_t *changeset,
assert(removed != NULL);
*removed = NULL;
-
+
dbg_ddns_verb("Removing possible redundant RRs from changeset.\n");
for (int i = 0; i < changeset->remove_count; ++i) {
- /* Just check exact match, the changeset contains only
+ /* Just check exact match, the changeset contains only
* whole RRs that have been removed.
*/
- if (knot_rrset_match(rr, changeset->remove[i],
+ if (knot_rrset_equal(rr, changeset->remove[i],
KNOT_RRSET_COMPARE_WHOLE) == 1) {
*removed = knot_changeset_remove_rr(
changeset->remove,
&changeset->remove_count, i);
dbg_ddns_detail("Removed RRSet from chgset:\n");
- knot_rrset_dump(*removed, 0);
+ knot_rrset_dump(*removed);
break;
}
}
@@ -887,8 +903,8 @@ static int knot_ddns_rr_is_nsec3(const knot_rrset_t *rr)
if ((knot_rrset_type(rr) == KNOT_RRTYPE_NSEC3)
|| (knot_rrset_type(rr) == KNOT_RRTYPE_RRSIG
- && knot_rrset_rdata(rr)
- && knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr))
+ && knot_rrset_rdata_rr_count(rr)
+ && knot_rrset_rdata_rrsig_type_covered(rr)
== KNOT_RRTYPE_NSEC3))
{
dbg_ddns_detail("This is NSEC3-related RRSet.\n");
@@ -917,9 +933,9 @@ static knot_node_t *knot_ddns_add_new_node(knot_zone_contents_t *zone,
// insert the node into zone structures and create parents if
// necessary
if (is_nsec3) {
- ret = knot_zone_contents_add_nsec3_node(zone, node, 1, 0, 1);
+ ret = knot_zone_contents_add_nsec3_node(zone, node, 1, 0);
} else {
- ret = knot_zone_contents_add_node(zone, node, 1, 0, 1);
+ ret = knot_zone_contents_add_node(zone, node, 1, 0);
}
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new node to zone contents.\n");
@@ -961,7 +977,7 @@ static knot_node_t *knot_ddns_get_node(knot_zone_contents_t *zone,
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_add_cname(knot_node_t *node,
+static int knot_ddns_process_add_cname(knot_node_t *node,
const knot_rrset_t *rr,
knot_changeset_t *changeset,
knot_changes_t *changes)
@@ -970,29 +986,29 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
assert(rr != NULL);
assert(changeset != NULL);
assert(changes != NULL);
-
+
dbg_ddns_detail("Adding CNAME RR.\n");
-
+
int ret = 0;
-
+
/* Get the current CNAME RR from the node. */
knot_rrset_t *removed = knot_node_get_rrset(node, KNOT_RRTYPE_CNAME);
-
+
if (removed != NULL) {
/* If they are identical, ignore. */
- if (knot_rrset_match(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
+ if (knot_rrset_equal(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
== 1) {
dbg_ddns_verb("CNAME identical to one in the node.\n");
return 1;
}
-
+
/*! \note
* Together with the removed CNAME we remove also its RRSIGs as
* they would not be valid for the new CNAME anyway.
*
* \todo Document!!
*/
-
+
/* b) Store it to 'changes', together with its RRSIGs. */
ret = knot_changes_add_old_rrsets(&removed, 1, changes, 1);
if (ret != KNOT_EOK) {
@@ -1002,41 +1018,40 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
}
/* c) And remove it from the node. */
- (void)knot_node_remove_rrset(node, KNOT_RRTYPE_CNAME);
-
+ UNUSED(knot_node_remove_rrset(node, KNOT_RRTYPE_CNAME));
+
/* d) Check if this CNAME was not previously added by
- * the UPDATE. If yes, remove it from the ADD
+ * the UPDATE. If yes, remove it from the ADD
* section and do not add it to the REMOVE section.
*/
knot_rrset_t **from_chgset = NULL;
size_t from_chgset_count = 0;
ret = knot_ddns_check_remove_rr2(
changeset, knot_rrset_owner(removed),
- KNOT_RRTYPE_CNAME, knot_rrset_rdata(removed),
- &from_chgset, &from_chgset_count);
+ removed, &from_chgset, &from_chgset_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove possible redundant "
- "RRs from ADD section: %s.\n",
+ "RRs from ADD section: %s.\n",
knot_strerror(ret));
free(from_chgset);
return ret;
}
-
+
assert(from_chgset_count <= 1);
-
+
if (from_chgset_count == 1) {
/* Just delete the RRSet. */
- knot_rrset_deep_free(&(from_chgset[0]), 1, 1, 1);
+ knot_rrset_deep_free(&(from_chgset[0]), 1, 1);
/* Okay, &(from_chgset[0]) is basically equal to just
* from_chgset, but it's more clear this way that we are
* deleting the first RRSet in the array ;-)
*/
} else {
- /* Otherwise copy the removed CNAME and add it
+ /* Otherwise copy the removed CNAME and add it
* to the REMOVE section.
*/
knot_rrset_t *removed_copy;
- ret = knot_rrset_deep_copy(removed,
+ ret = knot_rrset_deep_copy(removed,
&removed_copy, 1);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to copy removed RRSet:"
@@ -1044,15 +1059,15 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
free(from_chgset);
return ret;
}
-
+
ret = knot_changeset_add_rrset(
&changeset->remove,
&changeset->remove_count,
&changeset->remove_allocated,
removed_copy);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&removed_copy,
- 1, 1, 1);
+ knot_rrset_deep_free(&removed_copy,
+ 1, 1);
dbg_ddns("Failed to add removed CNAME "
"to changeset: %s\n",
knot_strerror(ret));
@@ -1065,50 +1080,48 @@ static int knot_ddns_process_add_cname(knot_node_t *node,
/* 2) Other occupied node => ignore. */
return 1;
}
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_add_soa(knot_node_t *node,
+static int knot_ddns_process_add_soa(knot_node_t *node,
const knot_rrset_t *rr,
knot_changes_t *changes)
{
assert(node != NULL);
assert(rr != NULL);
assert(changes != NULL);
-
+
dbg_ddns_detail("Adding SOA RR.\n");
-
+
int ret = 0;
-
+
/*
- * Just remove the SOA from the node, together with its RRSIGs.
+ * Just remove the SOA from the node, together with its RRSIGs.
* Adding the RR is done in the caller function. Note that only SOA
* with larger SERIAL than the current one will get to these functions,
* so we don't have to check the SERIALS again. But an assert won't
* hurt.
*/
-
+
/* Get the current SOA RR from the node. */
knot_rrset_t *removed = knot_node_get_rrset(node, KNOT_RRTYPE_SOA);
-
+
if (removed != NULL) {
dbg_ddns_detail("Found SOA in the node.\n");
/* If they are identical, ignore. */
- if (knot_rrset_match(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
+ if (knot_rrset_equal(removed, rr, KNOT_RRSET_COMPARE_WHOLE)
== 1) {
dbg_ddns_detail("Old and new SOA identical.\n");
return 1;
}
-
+
/* Check that the serial is indeed larger than the current one*/
- assert(ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(removed)),
- knot_rdata_soa_serial(
- knot_rrset_rdata(rr))) < 0);
-
+ assert(ns_serial_compare(knot_rrset_rdata_soa_serial(removed),
+ knot_rrset_rdata_soa_serial(rr)) < 0);
+
/* 1) Store it to 'changes', together with its RRSIGs. */
ret = knot_changes_add_old_rrsets(
&removed, 1, changes, 1);
@@ -1119,15 +1132,15 @@ static int knot_ddns_process_add_soa(knot_node_t *node,
}
/* 2) And remove it from the node. */
- (void)knot_node_remove_rrset(node, KNOT_RRTYPE_SOA);
-
+ UNUSED(knot_node_remove_rrset(node, KNOT_RRTYPE_SOA));
+
/* No changeset processing needed in this case. */
} else {
dbg_ddns_detail("No SOA in node, ignoring.\n");
/* If there is no SOA in the node, ignore. */
return 1;
}
-
+
return KNOT_EOK;
}
@@ -1139,40 +1152,40 @@ static int knot_ddns_add_rr_new_normal(knot_node_t *node, knot_rrset_t *rr_copy,
assert(node != NULL);
assert(rr_copy != NULL);
assert(changes != NULL);
-
+
dbg_ddns_verb("Adding normal RR.\n");
-
+
/* Add the RRSet to 'changes'. */
int ret = knot_changes_add_new_rrsets(&rr_copy, 1, changes, 1);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
dbg_ddns("Failed to store copy of the added RR: "
"%s\n", knot_strerror(ret));
return ret;
}
-
+
/* Add the RRSet to the node. */
- ret = knot_node_add_rrset(node, rr_copy, 0);
+ ret = knot_node_add_rrset_no_merge(node, rr_copy);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add RR to node: %s\n", knot_strerror(ret));
return ret;
}
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
static int knot_ddns_add_rr_new_rrsig(knot_node_t *node, knot_rrset_t *rr_copy,
- knot_changes_t *changes,
+ knot_changes_t *changes,
uint16_t type_covered)
{
assert(node != NULL);
assert(rr_copy != NULL);
assert(changes != NULL);
-
+
dbg_ddns_verb("Adding RRSIG RR.\n");
-
+
/* Create RRSet to be covered by the RRSIG. */
knot_rrset_t *covered_rrset = knot_rrset_new(
knot_rrset_get_owner(rr_copy), type_covered,
@@ -1181,47 +1194,47 @@ static int knot_ddns_add_rr_new_rrsig(knot_node_t *node, knot_rrset_t *rr_copy,
if (covered_rrset == NULL) {
dbg_ddns("Failed to create RRSet to be covered"
" by the UPDATE RRSIG RR.\n");
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
return KNOT_ENOMEM;
}
-
+
/* Add the RRSet to the node. */
- int ret = knot_node_add_rrset(node, covered_rrset, 0);
+ int ret = knot_node_add_rrset_no_merge(node, covered_rrset);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add the RRSet to be covered to the node: %s"
".\n", knot_strerror(ret));
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
- knot_rrset_deep_free(&covered_rrset, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
+ knot_rrset_deep_free(&covered_rrset, 1, 1);
return KNOT_ENOMEM;
}
-
+
/* Add the RRSet to 'changes'. */
ret = knot_changes_add_new_rrsets(&covered_rrset, 1, changes, 0);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RRSet (covered) to list: %s.\n",
knot_strerror(ret));
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
- knot_rrset_deep_free(&covered_rrset, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
+ knot_rrset_deep_free(&covered_rrset, 1, 1);
return ret;
}
/* Add the RRSIG RRSet to 'changes'. */
ret = knot_changes_add_new_rrsets(&rr_copy, 1, changes, 1);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&rr_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rr_copy, 1, 1);
dbg_ddns("Failed to store copy of the added RRSIG: %s\n",
knot_strerror(ret));
return ret;
}
-
+
/* Add the RRSIG RRSet to the covered RRSet. */
- ret = knot_rrset_add_rrsigs(covered_rrset, rr_copy,
+ ret = knot_rrset_add_rrsigs(covered_rrset, rr_copy,
KNOT_RRSET_DUPL_SKIP);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add RRSIG RR to the covered RRSet.\n");
return ret;
}
-
+
return KNOT_EOK;
}
@@ -1233,42 +1246,44 @@ static int knot_ddns_add_rr_merge_normal(knot_rrset_t *node_rrset_copy,
assert(node_rrset_copy != NULL);
assert(rr_copy != NULL);
assert(*rr_copy != NULL);
-
+
dbg_ddns_verb("Merging normal RR to existing RRSet.\n");
-
- /* In case the RRSet is empty (and only remained there because
- * of the RRSIGs) it may happen that the TTL may be different
- * than that of he new RRs. Update the TTL according to the
+
+ /* In case the RRSet is empty (and only remained there because
+ * of the RRSIGs) it may happen that the TTL may be different
+ * than that of he new RRs. Update the TTL according to the
* first RR.
- */
- if (knot_rrset_rdata(node_rrset_copy) == NULL
- && knot_rrset_ttl(node_rrset_copy)
+ */
+ if (knot_rrset_rdata_rr_count(node_rrset_copy) == 0
+ && knot_rrset_ttl(node_rrset_copy)
!= knot_rrset_ttl(*rr_copy)) {
- knot_rrset_set_ttl(node_rrset_copy,
+ knot_rrset_set_ttl(node_rrset_copy,
knot_rrset_ttl(*rr_copy));
}
int rdata_in_copy = knot_rrset_rdata_rr_count(*rr_copy);
- int ret = knot_rrset_merge_no_dupl((void **)&node_rrset_copy,
- (void **)rr_copy);
+ int merged, deleted_rrs;
+ int ret = knot_rrset_merge_no_dupl(node_rrset_copy, *rr_copy, &merged,
+ &deleted_rrs);
dbg_ddns_detail("Merge returned: %d\n", ret);
- if (ret < 0) {
+ if (ret != KNOT_EOK) {
dbg_ddns("Failed to merge UPDATE RR to node RRSet: %s."
"\n", knot_strerror(ret));
return ret;
}
- knot_rrset_free(rr_copy);
+ knot_rrset_deep_free(rr_copy, 1, 0);
+
- if (rdata_in_copy == ret) {
+ if (rdata_in_copy == deleted_rrs) {
/* All RDATA have been removed, because they were duplicates
* or there were none (0). In general this means, that no
* change was made.
*/
return 1;
}
-
+
return KNOT_EOK;
}
@@ -1282,12 +1297,12 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
assert(rr_copy != NULL);
assert(*rr_copy != NULL);
assert(changes != NULL);
-
+
dbg_ddns_verb("Adding RRSIG RR to existing RRSet.\n");
-
+
knot_rrset_t *rrsigs_old = knot_rrset_get_rrsigs(node_rrset_copy);
int ret = 0;
-
+
if (rrsigs_old != NULL) {
/* If there is an RRSIG RRSet already, copy it too. */
knot_rrset_t *rrsigs_copy = NULL;
@@ -1298,33 +1313,34 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
"%s\n", knot_strerror(ret));
return ret;
}
-
+
/* Replace the RRSIGs by the copy. */
ret = knot_rrset_set_rrsigs(node_rrset_copy, rrsigs_copy);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to replace RRSIGs in "
- "the RRSet: %s\n",
+ "the RRSet: %s\n",
knot_strerror(ret));
return ret;
}
-
+
/* Merge the UPDATE RR to the copied RRSIG
* RRSet.
*/
dbg_ddns_detail("Merging RRSIG to the one in the RRSet.\n");
int rdata_in_copy = knot_rrset_rdata_rr_count(*rr_copy);
- ret = knot_rrset_merge_no_dupl(
- (void **)&rrsigs_copy, (void **)rr_copy);
+ int merged, deleted_rrs;
+ ret = knot_rrset_merge_no_dupl(rrsigs_copy, *rr_copy, &merged,
+ &deleted_rrs);
if (ret < 0) {
dbg_xfrin("Failed to merge UPDATE RRSIG to copy: %s.\n",
knot_strerror(ret));
return KNOT_ERROR;
}
-
- knot_rrset_free(rr_copy);
+ knot_rrset_deep_free(rr_copy, 1, 0);
+
- if (rdata_in_copy == ret) {
+ if (rdata_in_copy == deleted_rrs) {
/* All RDATA have been removed, because they were
* duplicates or there were none (0). In general this
* means, that no change was made.
@@ -1342,7 +1358,7 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
knot_strerror(ret));
return ret;
}
-
+
/* Add the RRSet to the covered RRSet. */
ret = knot_rrset_add_rrsigs(node_rrset_copy, *rr_copy,
KNOT_RRSET_DUPL_SKIP);
@@ -1352,7 +1368,7 @@ static int knot_ddns_add_rr_merge_rrsig(knot_rrset_t *node_rrset_copy,
return ret;
}
}
-
+
return KNOT_EOK;
}
@@ -1371,7 +1387,7 @@ static int knot_ddns_add_rr(knot_node_t *node, const knot_rrset_t *rr,
assert(rr != NULL);
assert(changes != NULL);
assert(rr_copy != NULL);
-
+
/* Copy the RRSet from the packet. */
//knot_rrset_t *rr_copy;
int ret = knot_rrset_deep_copy(rr, rr_copy, 1);
@@ -1379,45 +1395,46 @@ static int knot_ddns_add_rr(knot_node_t *node, const knot_rrset_t *rr,
dbg_ddns("Failed to copy RR: %s\n", knot_strerror(ret));
return ret;
}
-
+
uint16_t type = knot_rrset_type(rr);
- uint16_t type_covered = (type == KNOT_RRTYPE_RRSIG)
- ? knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr))
+ uint16_t type_covered = (type == KNOT_RRTYPE_RRSIG)
+ ? knot_rrset_rdata_rrsig_type_covered(rr)
: type;
-
+
/* If the RR belongs to a RRSet already present in the node, we must
* take this RRSet from the node, copy it, and merge this RR into it.
*
* This code is more or less copied from xfr-in.c.
*/
knot_rrset_t *node_rrset_copy = NULL;
- ret = xfrin_copy_rrset(node, type_covered, &node_rrset_copy, changes,
+ ret = xfrin_copy_rrset(node, type_covered, &node_rrset_copy, changes,
0);
-
+
if (node_rrset_copy == NULL) {
/* No such RRSet in the node. Add the whole UPDATE RRSet. */
dbg_ddns_detail("Adding whole UPDATE RR to the zone.\n");
if (type_covered != type) {
/* Adding RRSIG. */
- ret = knot_ddns_add_rr_new_rrsig(node, *rr_copy,
+ ret = knot_ddns_add_rr_new_rrsig(node, *rr_copy,
changes, type_covered);
} else {
- ret = knot_ddns_add_rr_new_normal(node, *rr_copy,
+ ret = knot_ddns_add_rr_new_normal(node, *rr_copy,
changes);
}
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add new RR to node.\n");
return ret;
}
+ dbg_ddns_detail("RRSet added successfully.\n");
} else {
/* We have copied the RRSet from the node. */
dbg_ddns_exec_detail(
dbg_ddns_detail("Merging RR to an existing RRSet.\n");
- knot_rrset_dump(node_rrset_copy, 1);
+ knot_rrset_dump(node_rrset_copy);
dbg_ddns_detail("New RR:\n");
- knot_rrset_dump(*rr_copy, 0);
+ knot_rrset_dump(*rr_copy);
);
-
+
if (type_covered != type) {
/* Adding RRSIG. */
ret = knot_ddns_add_rr_merge_rrsig(node_rrset_copy,
@@ -1429,27 +1446,27 @@ dbg_ddns_exec_detail(
dbg_ddns_exec_detail(
dbg_ddns_detail("After merge:\n");
- knot_rrset_dump(node_rrset_copy, 1);
+ knot_rrset_dump(node_rrset_copy);
);
if (ret < KNOT_EOK) {
dbg_ddns("Failed to merge UPDATE RR to node RRSet.\n");
- knot_rrset_deep_free(rr_copy, 1, 1, 1);
- knot_rrset_deep_free(&node_rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(rr_copy, 1, 1);
+ knot_rrset_deep_free(&node_rrset_copy, 1, 1);
return ret;
}
-
+
// save the new RRSet together with the new RDATA to 'changes'
// do not overwrite 'ret', it have to be returned
int r = knot_changes_add_new_rrsets(&node_rrset_copy, 1,
changes, 1);
if (r != KNOT_EOK) {
dbg_ddns("Failed to store RRSet copy to 'changes'\n");
- knot_rrset_deep_free(&node_rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(&node_rrset_copy, 1, 1);
return r;
}
}
-
+
assert(ret >= 0);
return ret;
}
@@ -1461,7 +1478,7 @@ static int knot_ddns_final_soa_to_chgset(const knot_rrset_t *soa,
{
assert(soa != NULL);
assert(changeset != NULL);
-
+
knot_rrset_t *soa_copy = NULL;
int ret = knot_rrset_deep_copy(soa, &soa_copy, 1);
if (ret != KNOT_EOK) {
@@ -1469,11 +1486,11 @@ static int knot_ddns_final_soa_to_chgset(const knot_rrset_t *soa,
"%s\n", knot_strerror(ret));
return ret;
}
-
+
knot_changeset_store_soa(&changeset->soa_to,
&changeset->serial_to,
soa_copy);
-
+
return KNOT_EOK;
}
@@ -1484,7 +1501,7 @@ static int knot_ddns_add_rr_to_chgset(const knot_rrset_t *rr,
{
assert(rr != NULL);
assert(changeset != NULL);
-
+
int ret = 0;
knot_rrset_t *chgset_rr = NULL;
knot_ddns_check_add_rr(changeset, rr, &chgset_rr);
@@ -1501,15 +1518,15 @@ static int knot_ddns_add_rr_to_chgset(const knot_rrset_t *rr,
&changeset->add_allocated,
chgset_rr);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&chgset_rr, 1, 1, 1);
+ knot_rrset_deep_free(&chgset_rr, 1, 1);
dbg_ddns("Failed to add RR to changeset: %s.\n",
knot_strerror(ret));
return ret;
}
} else {
- knot_rrset_deep_free(&chgset_rr, 1, 1, 1);
+ knot_rrset_deep_free(&chgset_rr, 1, 1);
}
-
+
return KNOT_EOK;
}
@@ -1527,7 +1544,7 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
assert(changeset != NULL);
assert(changes != NULL);
assert(rr_copy != NULL);
-
+
dbg_ddns_verb("Adding RR.\n");
if (node == NULL) {
@@ -1541,11 +1558,11 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
return KNOT_ERROR;
}
}
-
+
uint16_t type = knot_rrset_type(rr);
*rr_copy = NULL;
int ret = 0;
-
+
/*
* First, rule out special cases: CNAME, SOA and adding to CNAME node.
*/
@@ -1564,7 +1581,7 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
*/
return KNOT_EOK;
}
-
+
if (ret == 1) {
dbg_ddns_detail("Ignoring the added RR.\n");
// Ignore
@@ -1573,11 +1590,11 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
dbg_ddns_detail("Adding RR failed.\n");
return ret;
}
-
+
/*
* In all other cases, the RR should just be added to the node.
*/
-
+
/* Add the RRSet to the node (RRSIGs handled in the function). */
dbg_ddns_detail("Adding RR to the node.\n");
ret = knot_ddns_add_rr(node, rr, changes, rr_copy);
@@ -1585,7 +1602,7 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
dbg_ddns("Failed to add RR to the node.\n");
return ret;
}
-
+
/*
* If adding SOA, it should not be stored in the changeset.
* (This is done in the calling function, and the SOA is stored in the
@@ -1594,9 +1611,9 @@ static int knot_ddns_process_add(const knot_rrset_t *rr,
if (type == KNOT_RRTYPE_SOA) {
return KNOT_EOK;
}
-
+
/* Add the RR to ADD section of the changeset. */
- /* If the RR was previously removed, do not add it to the
+ /* If the RR was previously removed, do not add it to the
* changeset, and remove the entry from the REMOVE section.
*
* If there was no change (i.e. all RDATA were duplicates), do not add
@@ -1655,7 +1672,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
assert(type != KNOT_RRTYPE_SOA);
int is_apex = knot_node_rrset(node, KNOT_RRTYPE_SOA) != NULL;
-
+
/* If removing NS from an apex and there is only one NS left, ignore
* this removal right away. We do not have to check if the RRs match:
* - if they don't match, the removal will be ignored
@@ -1670,7 +1687,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
* 1) Copy the RRSet.
*/
uint16_t type_to_copy = (type != KNOT_RRTYPE_RRSIG) ? type
- : knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr));
+ : knot_rrset_rdata_rrsig_type_covered(rr);
knot_rrset_t *rrset_copy = NULL;
int ret = xfrin_copy_rrset(node, type_to_copy, &rrset_copy, changes, 1);
if (ret < 0) {
@@ -1683,31 +1700,29 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
dbg_ddns_verb("RRSet not found.\n");
return KNOT_EOK;
}
-
+
/*
* Set some variables needed, according to the modified RR type.
*/
-
- int rdata_count;
+
+ int rdata_count = 0;
knot_rrset_t *to_modify;
if (type == KNOT_RRTYPE_RRSIG) {
- rdata_count = knot_rrset_rdata_rr_count(
- knot_rrset_rrsigs(rrset_copy));
+ rdata_count = knot_rrset_rdata_rr_count(knot_rrset_rrsigs(rrset_copy));
to_modify = knot_rrset_get_rrsigs(rrset_copy);
} else {
rdata_count = knot_rrset_rdata_rr_count(rrset_copy);
to_modify = rrset_copy;
}
-
+
/*
* 1.5) Prepare place for the removed RDATA.
* We don't know if there are some, but if this fails, at least we
* haven't removed them yet.
*/
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
changes->old_rdata_count,
- &changes->old_rdata_allocated,
+ &changes->old_rdata_allocated,
rdata_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to reserve place for RDATA.\n");
@@ -1717,32 +1732,39 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
/*
* 2) Remove the proper RDATA from the RRSet copy, or its RRSIGs.
*/
- knot_rdata_t *removed = knot_rrset_remove_rdata(to_modify,
- knot_rrset_rdata(rr));
+ knot_rrset_t *rr_remove = NULL;
+ ret = knot_rrset_remove_rr_using_rrset(to_modify, rr, &rr_remove, 0);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("ddns: proces_rem_rr: Could not remove RDATA from"
+ " RRSet (%s).\n", knot_strerror(ret));
+ return ret;
+ }
/* No such RR in the RRSet. */
- if (removed == NULL) {
+ if (knot_rrset_rdata_rr_count(rr_remove) == 0) {
+ knot_rrset_free(&rr_remove);
dbg_ddns_detail("No such RR found to be removed.\n");
return KNOT_EOK;
}
/* If we removed NS from apex, there should be at least one more. */
- assert(!is_apex || type != KNOT_RRTYPE_NS
- || knot_rrset_rdata(rrset_copy) != NULL);
+ assert(!is_apex || type != KNOT_RRTYPE_NS
+ || knot_rrset_rdata_rr_count(rrset_copy));
/*
* 3) Store the removed RDATA in 'changes'.
*/
- knot_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
- &changes->old_rdata_count, removed, type);
+ knot_changes_add_rdata(changes->old_rdata, &changes->old_rdata_count,
+ rr_remove);
/*
* 4) If the RRSet is empty, remove it and store in 'changes'.
- * Do this also if the RRSIGs are empty.
+ * Do this also if the RRSIGs are empty.
* And if both are empty, remove both.
+ * RRSIG handling first,
*/
- if (type == KNOT_RRTYPE_RRSIG
- && knot_rrset_rdata(to_modify) == NULL) {
+ if (type == KNOT_RRTYPE_RRSIG &&
+ knot_rrset_rdata_rr_count(to_modify) == 0) {
/* Empty RRSIGs, remove the RRSIG RRSet */
ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
&changes->old_rrsets_count,
@@ -1751,45 +1773,44 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
if (ret == KNOT_EOK) {
knot_rrset_t *rrsig = knot_rrset_get_rrsigs(rrset_copy);
dbg_xfrin_detail("Removed RRSIG RRSet (%p).\n", rrsig);
-
- assert(rrsig == to_modify);
+
+ assert(rrsig && rrsig == to_modify);
// add the removed RRSet to list of old RRSets
changes->old_rrsets[changes->old_rrsets_count++]
= rrsig;
-
+
// remove it from the RRSet
knot_rrset_set_rrsigs(rrset_copy, NULL);
} else {
dbg_ddns("Failed to reserve space for empty RRSet.\n");
}
}
-
- /*! \note Copied from xfr-in.c - maybe extract to some function. */
- /*! \note This is not needed as rrset is already on the old_rrsets */
-// if (knot_rrset_rdata(rrset_copy) == NULL
-// && knot_rrset_rrsigs(rrset_copy) == NULL) {
-// // The RRSet should not be empty if we were removing NSs from
-// // apex in case of DDNS
-// assert(!is_apex);
-
-// ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
-// &changes->old_rrsets_count,
-// &changes->old_rrsets_allocated,
-// 1);
-// if (ret == KNOT_EOK) {
-// knot_rrset_t *tmp = knot_node_remove_rrset(node, type);
-// dbg_xfrin_detail("Removed whole RRSet (%p).\n", tmp);
-
-// assert(tmp == rrset_copy);
-
-// // add the removed RRSet to list of old RRSets
-// changes->old_rrsets[changes->old_rrsets_count++]
-// = rrset_copy;
-// } else {
-// dbg_ddns("Failed to reserve space for empty RRSet.\n");
-// }
-// }
+
+ // Remove empty RRSet from node and store to changeset
+ if (type != KNOT_RRTYPE_RRSIG &&
+ knot_rrset_rdata_rr_count(to_modify) == 0) {
+ // The RRSet should not be empty if we were removing NSs from
+ // apex in case of DDNS
+ assert(!is_apex);
+
+ ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
+ &changes->old_rrsets_count,
+ &changes->old_rrsets_allocated,
+ 1);
+ if (ret == KNOT_EOK) {
+ knot_rrset_t *tmp = knot_node_remove_rrset(node, type);
+ dbg_xfrin_detail("Removed whole RRSet (%p).\n", tmp);
+
+ assert(tmp == rrset_copy);
+
+ // add the removed RRSet to list of old RRSets
+ changes->old_rrsets[changes->old_rrsets_count++]
+ = rrset_copy;
+ } else {
+ dbg_ddns("Failed to reserve space for empty RRSet.\n");
+ }
+ }
/*
* 5) Check if the RR is not in the ADD section. If yes, remove it
@@ -1798,8 +1819,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
knot_rrset_t **from_chgset = NULL;
size_t from_chgset_count = 0;
ret = knot_ddns_check_remove_rr2(changeset, knot_node_owner(node),
- type, knot_rrset_rdata(rr),
- &from_chgset, &from_chgset_count);
+ rr, &from_chgset, &from_chgset_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove possible redundant RRs from ADD "
"section: %s.\n", knot_strerror(ret));
@@ -1811,13 +1831,13 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
if (from_chgset_count == 1) {
/* Just delete the RRSet. */
- knot_rrset_deep_free(&(from_chgset[0]), 1, 1, 1);
+ knot_rrset_deep_free(&(from_chgset[0]), 1, 1);
/* Finish processing, no adding to changeset. */
free(from_chgset);
return KNOT_EOK;
}
-
+
free(from_chgset);
/*
@@ -1841,7 +1861,7 @@ static int knot_ddns_process_rem_rr(const knot_rrset_t *rr,
if (ret != KNOT_EOK) {
dbg_ddns("Failed to store the RRSet copy to changeset: %s.\n",
knot_strerror(ret));
- knot_rrset_deep_free(&to_chgset, 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset, 1, 1);
return ret;
}
@@ -1858,9 +1878,9 @@ static int knot_ddns_process_rem_rrsig(knot_node_t *node,
assert(node != NULL);
assert(rrset != NULL);
assert(changes != NULL);
-
+
knot_rrset_t *rrset_copy = NULL;
-
+
/* Copy RRSet. */
int ret = xfrin_copy_old_rrset(rrset, &rrset_copy, changes, 1);
if (ret != KNOT_EOK) {
@@ -1868,29 +1888,29 @@ static int knot_ddns_process_rem_rrsig(knot_node_t *node,
knot_strerror(ret));
return ret;
}
-
+
/* Remove RRSIGs from the copy. */
*rrsig = knot_rrset_get_rrsigs(rrset_copy);
if (*rrsig != NULL) {
knot_rrset_set_rrsigs(rrset_copy, NULL);
}
-
+
/* Put the copy to the node. */
- ret = knot_node_add_rrset(node, rrset_copy, 0);
+ ret = knot_node_add_rrset_no_merge(node, rrset_copy);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to add RRSet copy to the node: %s\n",
knot_strerror(ret));
- knot_rrset_deep_free(&rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
return ret;
}
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
- knot_changes_t *changes,
+static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
+ knot_changes_t *changes,
knot_rrset_t ***removed,
size_t *removed_count)
{
@@ -1898,33 +1918,37 @@ static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
assert(removed != NULL);
assert(removed_count != NULL);
assert(changes != NULL);
-
- /* If removing RRSIGs, we must remove them from all RRSets in
- * the node. This means to copy all RRSets and then remove the
+
+ /* If removing RRSIGs, we must remove them from all RRSets in
+ * the node. This means to copy all RRSets and then remove the
* RRSIGs from them.
*/
dbg_ddns_verb("Removing all RRSIGs from node.\n");
-
+
knot_rrset_t **rrsets = knot_node_get_rrsets(node);
if (rrsets == NULL) {
// No RRSets in the node, nothing to remove
return KNOT_EOK;
}
-
+
/* Allocate space for the removed RRSIGs. There may be as many as there
* are RRSets.
*/
short rrset_count = knot_node_rrset_count(node);
-
+
*removed = malloc(rrset_count * sizeof(knot_rrset_t *));
- CHECK_ALLOC_LOG(*removed, KNOT_ENOMEM);
+ if (*removed == NULL) {
+ ERR_ALLOC_FAILED;
+ free(rrsets);
+ return KNOT_ENOMEM;
+ }
*removed_count = 0;
-
+
/* Remove all the RRSets from the node, so that we may insert the copies
* right away.
*/
knot_node_remove_all_rrsets(node);
-
+
knot_rrset_t *rrsig = NULL;
int ret = 0;
for (int i = 0; i < rrset_count; ++i) {
@@ -1932,41 +1956,47 @@ static int knot_ddns_process_rem_rrsigs(knot_node_t *node,
&rrsig);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove RRSIG.\n");
+ free(rrsets);
+ free(*removed);
+ *removed = NULL;
return ret;
}
/* Store the RRSIGs to the array of removed RRSets. */
(*removed)[(*removed_count)++] = rrsig;
}
-
+
free(rrsets);
-
-
+
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int knot_ddns_process_rem_rrset(uint16_t type,
+static int knot_ddns_process_rem_rrset(const knot_rrset_t *rrset,
knot_node_t *node,
knot_changeset_t *changeset,
knot_changes_t *changes)
{
assert(node != NULL);
+ assert(rrset != NULL);
assert(changeset != NULL);
assert(changes != NULL);
+ uint16_t type = knot_rrset_type(rrset);
+
/*! \note
* We decided to automatically remove RRSIGs together with the removed
- * RRSet as they are no longer valid or required anyway.
+ * RRSet as they are no longer valid or required anyway.
*
* Also refer to RFC3007, section 4.3:
- * 'When the contents of an RRset are updated, the server MAY delete
+ * 'When the contents of an RRset are updated, the server MAY delete
* all associated SIG records, since they will no longer be valid.'
*
* (Although we are compliant with this RFC only selectively. The next
- * section says: 'If any changes are made, the server MUST, if
- * necessary, generate a new SOA record and new NXT records, and sign
- * these with the appropriate zone keys.' and we are definitely not
+ * section says: 'If any changes are made, the server MUST, if
+ * necessary, generate a new SOA record and new NXT records, and sign
+ * these with the appropriate zone keys.' and we are definitely not
* doing this...
*
* \todo Document!!
@@ -1980,15 +2010,20 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
// if removing NS from apex, ignore
return KNOT_EOK;
}
-
+
knot_rrset_t **removed = NULL;
size_t removed_count = 0;
int ret = 0;
-
+
if (type == KNOT_RRTYPE_RRSIG) {
/* Remove all RRSIGs from the node. */
ret = knot_ddns_process_rem_rrsigs(node, changes, &removed,
&removed_count);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("Failed to remove RRSIGs. (%s)\n",
+ knot_strerror(ret));
+ return ret;
+ }
} else {
/* Remove the RRSet from the node. */
removed = malloc(sizeof(knot_rrset_t *));
@@ -1998,23 +2033,28 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
}
dbg_ddns_detail("Removing RRSet of type: %d\n", type);
-
+
*removed = knot_node_remove_rrset(node, type);
- removed_count = 1;
+ if (*removed != NULL) {
+ removed_count = 1;
+ } else {
+ removed_count = 0;
+ }
}
- dbg_ddns_detail("Removed: %p (first item: %p), removed count: %d\n",
- removed, (removed == NULL) ? "none" : *removed,
+ dbg_ddns_detail("Removed: %p (first item: %p), removed count: %zu\n",
+ removed, (removed == NULL) ? (void *)"none" : *removed,
removed_count);
// no such RR
- if (removed_count == 0 || removed == NULL) {
+ if (removed_count == 0) {
// ignore
+ free(removed);
return KNOT_EOK;
}
/* 2) Store them to 'changes' for later deallocation, together with
- * their RRSIGs.
+ * their RRSIGs.
*/
ret = knot_changes_add_old_rrsets(removed, removed_count, changes, 1);
if (ret != KNOT_EOK) {
@@ -2025,7 +2065,7 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
}
/* 3) Copy the RRSets, so that they can be stored to the changeset. */
- knot_rrset_t **to_chgset = malloc(removed_count
+ knot_rrset_t **to_chgset = malloc(removed_count
* sizeof(knot_rrset_t *));
if (to_chgset == NULL) {
dbg_ddns("Failed to allocate space for RRSets going to "
@@ -2033,21 +2073,21 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
free(removed);
return KNOT_ENOMEM;
}
-
+
for (int i = 0; i < removed_count; ++i) {
ret = knot_rrset_deep_copy(removed[i], &to_chgset[i], 1);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to copy the removed RRSet: %s.\n",
knot_strerror(ret));
for (int j = 0; j < i; ++j) {
- knot_rrset_deep_free(&to_chgset[j], 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset[j], 1, 1);
}
free(to_chgset);
free(removed);
return ret;
}
}
-
+
free(removed);
/* 4) But we must check if some of the RRs were not previously added
@@ -2059,22 +2099,28 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
size_t from_chgset_count = 0;
/* 4 a) Remove redundant RRs from the ADD section of the changeset. */
- ret = knot_ddns_check_remove_rr2(changeset, knot_node_owner(node), type,
- NULL, &from_chgset,
+ knot_rrset_t *empty_rrset =
+ knot_rrset_new(rrset->owner, type, rrset->rclass, rrset->ttl);
+ if (empty_rrset == NULL) {
+ return KNOT_ENOMEM;
+ }
+ ret = knot_ddns_check_remove_rr2(changeset, knot_node_owner(node),
+ empty_rrset, &from_chgset,
&from_chgset_count);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove possible redundant RRs from ADD "
"section: %s.\n", knot_strerror(ret));
for (int i = 0; i < removed_count; ++i) {
- knot_rrset_deep_free(&to_chgset[i], 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset[i], 1, 1);
}
free(from_chgset);
free(to_chgset);
+ knot_rrset_free(&empty_rrset);
return ret;
}
+ knot_rrset_free(&empty_rrset);
/* 4 b) Remove these RRs from the copy of the RRSets removed from zone*/
- knot_rdata_t *rem = NULL;
for (int j = 0; j < removed_count; ++j) {
/* In each RRSet removed from the node (each can have more
* RDATAs) ...
@@ -2083,18 +2129,21 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
/* ...try to remove redundant RDATA. Each RRSet in
* 'from_chgset' contains only one RDATA.
*/
- rem = knot_rrset_remove_rdata(to_chgset[j],
- knot_rrset_rdata(
- from_chgset[i]));
- /* And delete it right away, no use for that. */
- knot_rdata_deep_free(&rem, knot_rrset_type(
- from_chgset[i]), 1);
+ ret = knot_rrset_remove_rr_using_rrset_del(to_chgset[j],
+ from_chgset[i]);
+ if (ret != KNOT_EOK) {
+ dbg_ddns("Failed to remove RR from RRSet"
+ "(%s).\n", knot_strerror(ret));
+ free(from_chgset);
+ free(to_chgset);
+ return ret;
+ }
}
}
-
+
/* The array is cleared, we may delete the redundant RRs. */
for (int i = 0; i < from_chgset_count; ++i) {
- knot_rrset_deep_free(&from_chgset[i], 1, 1, 1);
+ knot_rrset_deep_free(&from_chgset[i], 1, 1);
}
free(from_chgset);
@@ -2110,13 +2159,13 @@ static int knot_ddns_process_rem_rrset(uint16_t type,
dbg_ddns("Failed to store the RRSet copy to changeset: "
"%s.\n", knot_strerror(ret));
for (int j = i; j < removed_count; ++j) {
- knot_rrset_deep_free(&to_chgset[j], 1, 1, 1);
+ knot_rrset_deep_free(&to_chgset[j], 1, 1);
}
free(to_chgset);
return ret;
}
}
-
+
free(to_chgset);
return KNOT_EOK;
@@ -2139,13 +2188,13 @@ static int knot_ddns_process_rem_all(knot_node_t *node,
* In case of SOA and NS in apex, the RRSets should not be removed, but
* what about their RRSIGs??
*
- * If the zone has to remain properly signed, the UPDATE will have to
+ * If the zone has to remain properly signed, the UPDATE will have to
* contain at least new SOA and RRSIGs for it (as the auto-incremented
- * SOA would not be signed). So it should not matter if we leave the
+ * SOA would not be signed). So it should not matter if we leave the
* RRSIGs there or not. But in case of the NSs it's not that clear.
*
* For now, we will leave the RRSIGs there. It's easier to implement.
- *
+ *
* \todo Should document this!!
*/
int ret = 0;
@@ -2169,8 +2218,8 @@ static int knot_ddns_process_rem_all(knot_node_t *node,
continue;
}
- ret = knot_ddns_process_rem_rrset(knot_rrset_type(rrsets[i]),
- node, changeset, changes);
+ ret = knot_ddns_process_rem_rrset(rrsets[i], node, changeset,
+ changes);
if (ret != KNOT_EOK) {
dbg_ddns("Failed to remove RRSet: %s\n",
knot_strerror(ret));
@@ -2178,7 +2227,7 @@ static int knot_ddns_process_rem_all(knot_node_t *node,
return ret;
}
}
-
+
free(rrsets);
return KNOT_EOK;
@@ -2211,14 +2260,13 @@ static int knot_ddns_process_rr(const knot_rrset_t *rr,
return KNOT_EOK;
} else if (knot_rrset_class(rr) == KNOT_CLASS_NONE) {
return knot_ddns_process_rem_rr(rr, node, zone, changeset,
- changes, qclass);
+ changes, qclass);
} else if (knot_rrset_class(rr) == KNOT_CLASS_ANY) {
if (knot_rrset_type(rr) == KNOT_RRTYPE_ANY) {
return knot_ddns_process_rem_all(node, changeset,
changes);
} else {
- return knot_ddns_process_rem_rrset(knot_rrset_type(rr),
- node, changeset,
+ return knot_ddns_process_rem_rrset(rr, node, changeset,
changes);
}
} else {
@@ -2258,7 +2306,7 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
KNOT_RRTYPE_SOA);
knot_rrset_t *soa_begin = NULL;
knot_rrset_t *soa_end = NULL;
- ret = knot_rrset_deep_copy(soa, &soa_begin, 0);
+ ret = knot_rrset_deep_copy(soa, &soa_begin, 1);
if (ret == KNOT_EOK) {
knot_changeset_store_soa(&changeset->soa_from,
&changeset->serial_from, soa_begin);
@@ -2268,7 +2316,7 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
}
/* Current SERIAL */
- int64_t sn = knot_rdata_soa_serial(knot_rrset_rdata(soa_begin));
+ int64_t sn = knot_rrset_rdata_soa_serial(soa_begin);
int64_t sn_new;
/* Incremented SERIAL
@@ -2320,13 +2368,14 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
if (knot_rrset_type(rr) == KNOT_RRTYPE_SOA
&& (knot_rrset_class(rr) == KNOT_CLASS_NONE
|| knot_rrset_class(rr) == KNOT_CLASS_ANY
- || ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(rr)), sn_new) < 0)) {
+ || ns_serial_compare(knot_rrset_rdata_soa_serial(rr),
+ sn_new) < 0)) {
// This ignores also SOA removals
dbg_ddns_verb("Ignoring SOA...\n");
continue;
}
+ dbg_ddns_verb("Processing RR %p...\n", rr);
ret = knot_ddns_process_rr(rr, zone, changeset, changes,
knot_packet_qclass(query),
&rr_copy);
@@ -2341,10 +2390,9 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
// we need the RR copy, that's why this code is here
if (knot_rrset_type(rr) == KNOT_RRTYPE_SOA) {
- int64_t sn_rr = knot_rdata_soa_serial(
- knot_rrset_rdata(rr));
- dbg_ddns_verb("Replacing SOA. Old serial: %d, new "
- "serial: %d\n", sn_new, sn_rr);
+ int64_t sn_rr = knot_rrset_rdata_soa_serial(rr);
+ dbg_ddns_verb("Replacing SOA. Old serial: %"PRId64", "
+ "new serial: %"PRId64"\n", sn_new, sn_rr);
assert(ns_serial_compare(sn_rr, sn_new) >= 0);
assert(rr_copy != NULL);
sn_new = sn_rr;
@@ -2354,14 +2402,14 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
/* Ending SOA (not in the UPDATE) */
if (soa_end == NULL) {
- /* If the changeset is empty, do not process anything further
+ /* If the changeset is empty, do not process anything further
* and indicate this to the caller, so that the changeset is not
* saved and zone is not switched.
*/
if (knot_changeset_is_empty(changeset)) {
return 1;
}
-
+
/* If not set, create new SOA. */
assert(sn_new == (uint32_t)sn + 1);
ret = knot_rrset_deep_copy(soa, &soa_end, 1);
@@ -2371,9 +2419,8 @@ int knot_ddns_process_update2(knot_zone_contents_t *zone,
*rcode = KNOT_RCODE_SERVFAIL;
return ret;
}
- knot_rdata_t *rd = knot_rrset_get_rdata(soa_end);
- knot_rdata_soa_serial_set(rd, sn_new);
-
+ knot_rrset_rdata_soa_serial_set(soa_end, sn_new);
+
/* And replace it in the zone. */
ret = xfrin_replace_rrset_in_node(
knot_zone_contents_get_apex(zone),
diff --git a/src/libknot/updates/ddns.h b/src/libknot/updates/ddns.h
index d3cb359..d6164fe 100644
--- a/src/libknot/updates/ddns.h
+++ b/src/libknot/updates/ddns.h
@@ -57,7 +57,7 @@ typedef struct knot_ddns_prereq_t {
size_t not_in_use_allocd;
} knot_ddns_prereq_t;
-int knot_ddns_check_zone(const knot_zone_contents_t *zone,
+int knot_ddns_check_zone(const knot_zone_contents_t *zone,
const knot_packet_t *query, knot_rcode_t *rcode);
int knot_ddns_process_prereqs(const knot_packet_t *query,
diff --git a/src/libknot/updates/xfr-in.c b/src/libknot/updates/xfr-in.c
index 98d4df6..78d12a9 100644
--- a/src/libknot/updates/xfr-in.c
+++ b/src/libknot/updates/xfr-in.c
@@ -14,9 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
#include <urcu.h>
+#include "knot/server/journal.h"
+
#include "updates/xfr-in.h"
#include "nameserver/name-server.h"
@@ -26,9 +29,11 @@
#include "dname.h"
#include "zone/zone.h"
#include "packet/query.h"
+#include "common.h"
#include "updates/changesets.h"
#include "tsig.h"
#include "tsig-op.h"
+#include "common/descriptor.h"
/*----------------------------------------------------------------------------*/
/* Non-API functions */
@@ -40,7 +45,7 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype,
{
knot_packet_t *pkt = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
CHECK_ALLOC_LOG(pkt, KNOT_ENOMEM);
-
+
/*! \todo Get rid of the numeric constant. */
int rc = knot_packet_set_max_size(pkt, 512);
if (rc != KNOT_EOK) {
@@ -74,7 +79,7 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype,
knot_packet_free(&pkt);
return KNOT_ERROR;
}
-
+
/* Reserve space for TSIG. */
if (use_tsig && xfr->tsig_key) {
dbg_xfrin_detail("xfrin: setting packet TSIG size to %zu\n",
@@ -101,32 +106,30 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype,
if (wire_size > *size) {
dbg_xfrin("Not enough space provided for the wire "
- "format of the query.\n");
+ "format of the query.\n");
knot_packet_free(&pkt);
return KNOT_ESPACE;
}
-
+
// wire format created, sign it with TSIG if required
if (use_tsig && xfr->tsig_key) {
char *name = knot_dname_to_str(xfr->tsig_key->name);
dbg_xfrin_detail("Signing XFR query with key (name %s): \n",
- name);
+ name);
free(name);
- dbg_xfrin_hex_detail(xfr->tsig_key->secret,
- xfr->tsig_key->secret_size);
-
+
xfr->digest_size = xfr->digest_max_size;
- rc = knot_tsig_sign(wire, &wire_size, *size, NULL, 0,
- xfr->digest, &xfr->digest_size, xfr->tsig_key,
- 0, 0);
+ rc = knot_tsig_sign(wire, &wire_size, *size, NULL, 0,
+ xfr->digest, &xfr->digest_size, xfr->tsig_key,
+ 0, 0);
if (rc != KNOT_EOK) {
/*! \todo [TSIG] Handle TSIG errors. */
knot_packet_free(&pkt);
return rc;
}
-
+
dbg_xfrin_detail("Signed XFR query, new wire size: %zu, digest:"
- "\n", wire_size);
+ "\n", wire_size);
dbg_xfrin_hex_detail((const char*)xfr->digest, xfr->digest_size);
}
@@ -164,14 +167,14 @@ int xfrin_transfer_needed(const knot_zone_contents_t *zone,
// first, parse the rest of the packet
assert(!knot_packet_is_query(soa_response));
dbg_xfrin_verb("Response - parsed: %zu, total wire size: %zu\n",
- soa_response->parsed, soa_response->size);
+ soa_response->parsed, soa_response->size);
int ret;
if (soa_response->parsed < soa_response->size) {
- ret = knot_packet_parse_rest(soa_response);
+ ret = knot_packet_parse_rest(soa_response, 0);
if (ret != KNOT_EOK) {
dbg_xfrin_verb("knot_packet_parse_rest() returned %s\n",
- knot_strerror(ret));
+ knot_strerror(ret));
return KNOT_EMALF;
}
}
@@ -181,7 +184,7 @@ int xfrin_transfer_needed(const knot_zone_contents_t *zone,
*/
const knot_rrset_t *soa_rrset =
knot_node_rrset(knot_zone_contents_apex(zone),
- KNOT_RRTYPE_SOA);
+ KNOT_RRTYPE_SOA);
if (soa_rrset == NULL) {
char *name = knot_dname_to_str(knot_node_owner(
knot_zone_contents_apex(zone)));
@@ -190,8 +193,7 @@ int xfrin_transfer_needed(const knot_zone_contents_t *zone,
return KNOT_ERROR;
}
- int64_t local_serial = knot_rdata_soa_serial(
- knot_rrset_rdata(soa_rrset));
+ int64_t local_serial = knot_rrset_rdata_soa_serial(soa_rrset);
if (local_serial < 0) {
dbg_xfrin_exec(
char *name = knot_dname_to_str(knot_rrset_owner(soa_rrset));
@@ -211,8 +213,7 @@ dbg_xfrin_exec(
return KNOT_EMALF;
}
- int64_t remote_serial = knot_rdata_soa_serial(
- knot_rrset_rdata(soa_rrset));
+ int64_t remote_serial = knot_rrset_rdata_soa_serial(soa_rrset);
if (remote_serial < 0) {
return KNOT_EMALF; // maybe some other error
}
@@ -231,7 +232,7 @@ int xfrin_create_axfr_query(knot_dname_t *owner, knot_ns_xfr_t *xfr,
/*----------------------------------------------------------------------------*/
-int xfrin_create_ixfr_query(const knot_zone_contents_t *zone,
+int xfrin_create_ixfr_query(const knot_zone_contents_t *zone,
knot_ns_xfr_t *xfr, size_t *size, int use_tsig)
{
/*!
@@ -241,65 +242,29 @@ int xfrin_create_ixfr_query(const knot_zone_contents_t *zone,
const knot_rrset_t *soa = knot_node_rrset(apex, KNOT_RRTYPE_SOA);
return xfrin_create_query(knot_node_get_owner(apex), KNOT_RRTYPE_IXFR,
- KNOT_CLASS_IN, xfr, size, soa, use_tsig);
+ KNOT_CLASS_IN, xfr, size, soa, use_tsig);
}
/*----------------------------------------------------------------------------*/
-static int xfrin_add_orphan_rrsig(xfrin_orphan_rrsig_t **rrsigs,
+static int xfrin_add_orphan_rrsig(xfrin_orphan_rrsig_t **rrsigs,
knot_rrset_t *rr)
{
- // try to find similar RRSIGs (check owner and type covered) in the list
assert(knot_rrset_type(rr) == KNOT_RRTYPE_RRSIG);
-
- if (*rrsigs == NULL) {
- /* First item, nothing to iterate. */
- *rrsigs = malloc(sizeof(xfrin_orphan_rrsig_t));
- CHECK_ALLOC_LOG(*rrsigs, KNOT_ENOMEM);
- (*rrsigs)->rrsig = rr;
- (*rrsigs)->next = NULL;
- return KNOT_EOK;
- }
-
- int ret = 0;
- xfrin_orphan_rrsig_t *last = *rrsigs;
- assert(last);
- while (last != NULL) {
- // check if the RRSIG is not similar to the one we want to add
- assert(last->rrsig != NULL);
- if (knot_rrset_match(last->rrsig, rr,
- KNOT_RRSET_COMPARE_HEADER) == 1
- && knot_rdata_rrsig_type_covered(knot_rrset_rdata(
- last->rrsig))
- == knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr))) {
- ret = knot_rrset_merge_no_dupl((void **)&last->rrsig,
- (void **)&rr);
- if (ret < 0) {
- return ret;
- } else {
- return 1;
- }
- }
- last = last->next;
- }
-
- assert(last == NULL);
- assert(&last != rrsigs);
-
- // the RRSIG is not in the list, add to the front
+
xfrin_orphan_rrsig_t *new_item = malloc(sizeof(xfrin_orphan_rrsig_t));
- CHECK_ALLOC_LOG(new_item, KNOT_ENOMEM);
+ CHECK_ALLOC_LOG(new_item, KNOT_ENOMEM);
new_item->rrsig = rr;
new_item->next = *rrsigs;
-
+
*rrsigs = new_item;
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-static int xfrin_process_orphan_rrsigs(knot_zone_contents_t *zone,
+static int xfrin_process_orphan_rrsigs(knot_zone_contents_t *zone,
xfrin_orphan_rrsig_t *rrsigs)
{
xfrin_orphan_rrsig_t **last = &rrsigs;
@@ -307,26 +272,55 @@ static int xfrin_process_orphan_rrsigs(knot_zone_contents_t *zone,
while (*last != NULL) {
knot_rrset_t *rrset = NULL;
knot_node_t *node = NULL;
- ret = knot_zone_contents_add_rrsigs(zone, (*last)->rrsig,
- &rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1);
+ ret = knot_zone_contents_add_rrsigs(zone, (*last)->rrsig,
+ &rrset, &node,
+ KNOT_RRSET_DUPL_MERGE);
if (ret > 0) {
- knot_rrset_free(&(*last)->rrsig);
+ knot_rrset_deep_free(&(*last)->rrsig, 1, 0);
+ } else if (ret == KNOT_ENONODE) {
+ // Nothing to cover - print warning
+ char *name = knot_dname_to_str((*last)->rrsig->owner);
+ char type[16];
+ knot_rrtype_to_string(
+ knot_rrset_rdata_rrsig_type_covered((*last)->rrsig),
+ type, 16);
+
+ log_zone_warning("No RRSet for RRSIG: "
+ "%s, covering type %s",
+ name, type);
+ free(name);
+
+ // discard RRSIG
+ knot_rrset_deep_free(&(*last)->rrsig, 1, 1);
} else if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add orphan RRSIG to zone.\n");
return ret;
} else {
(*last)->rrsig = NULL;
}
-
last = &((*last)->next);
}
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
+static int xfrin_insert_rdata_dnames_to_table(knot_dname_t **dname, void *data)
+{
+ hattrie_t *lookup_tree = data;
+ knot_zone_contents_insert_dname_into_table(dname, lookup_tree);
+ return KNOT_EOK;
+}
+
+static int xfrin_insert_rrset_dnames_to_table(knot_rrset_t *rrset,
+ hattrie_t *lookup_tree)
+{
+ knot_zone_contents_insert_dname_into_table(&rrset->owner, lookup_tree);
+ rrset_dnames_apply(rrset, xfrin_insert_rdata_dnames_to_table, lookup_tree);
+ return KNOT_EOK;
+}
+
void xfrin_free_orphan_rrsigs(xfrin_orphan_rrsig_t **rrsigs)
{
xfrin_orphan_rrsig_t *r = *rrsigs;
@@ -335,7 +329,7 @@ void xfrin_free_orphan_rrsigs(xfrin_orphan_rrsig_t **rrsigs)
r = r->next;
free(prev);
}
-
+
*rrsigs = NULL;
}
@@ -346,16 +340,16 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
{
assert(packet != NULL);
assert(xfr != NULL);
-
- dbg_xfrin_verb("xfrin_check_tsig(): packet nr: %d, required: %d\n",
- xfr->packet_nr, tsig_req);
-
+
+ dbg_xfrin_verb("xfrin_check_tsig(): packet nr: %d, required: %d\n",
+ xfr->packet_nr, tsig_req);
+
/*
* If we are expecting it (i.e. xfr->prev_digest_size > 0)
* a) it should be there (first, last or each 100th packet) and it
* is not
* Then we should discard the changes and close the connection.
- * b) it should be there and it is or it may not be there (other
+ * b) it should be there and it is or it may not be there (other
* packets) and it is
* We validate the TSIG and reset packet number counting and
* data aggregation.
@@ -368,7 +362,7 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
if (ret != KNOT_EOK) {
return ret;
}
-
+
if (xfr->tsig_key) {
// just append the wireformat to the TSIG data
assert(KNOT_NS_TSIG_DATA_MAX_SIZE - xfr->tsig_data_size
@@ -377,7 +371,7 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
xfr->wire, xfr->wire_size);
xfr->tsig_data_size += xfr->wire_size;
}
-
+
if (xfr->tsig_key) {
if (tsig_req && tsig == NULL) {
// TSIG missing!!
@@ -385,54 +379,54 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
} else if (tsig != NULL) {
// TSIG there, either required or not, process
if (xfr->packet_nr == 0) {
- ret = knot_tsig_client_check(tsig,
- xfr->wire, xfr->wire_size,
+ ret = knot_tsig_client_check(tsig,
+ xfr->wire, xfr->wire_size,
xfr->digest, xfr->digest_size,
xfr->tsig_key,
xfr->tsig_prev_time_signed);
} else {
- ret = knot_tsig_client_check_next(tsig,
- xfr->tsig_data, xfr->tsig_data_size,
+ ret = knot_tsig_client_check_next(tsig,
+ xfr->tsig_data, xfr->tsig_data_size,
xfr->digest, xfr->digest_size,
xfr->tsig_key,
xfr->tsig_prev_time_signed);
}
-
+
if (ret != KNOT_EOK) {
/* No need to check TSIG error
* here, propagate and check elsewhere.*/
- knot_rrset_deep_free(&tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tsig, 1, 1);
return ret;
}
-
+
// and reset the data storage
//xfr->packet_nr = 1;
xfr->tsig_data_size = 0;
// Extract the digest from the TSIG RDATA and store it.
if (xfr->digest_max_size < tsig_rdata_mac_length(tsig)) {
- knot_rrset_deep_free(&tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tsig, 1, 1);
return KNOT_ESPACE;
}
- memcpy(xfr->digest, tsig_rdata_mac(tsig),
+ memcpy(xfr->digest, tsig_rdata_mac(tsig),
tsig_rdata_mac_length(tsig));
xfr->digest_size = tsig_rdata_mac_length(tsig);
// Extract the time signed from the TSIG and store it
// We may rewrite the tsig_req_time_signed field
xfr->tsig_prev_time_signed =
- tsig_rdata_time_signed(tsig);
+ tsig_rdata_time_signed(tsig);
+
-
}
} else if (tsig != NULL) {
// TSIG where it should not be
- knot_rrset_deep_free(&tsig, 1, 1, 1);
+ knot_rrset_deep_free(&tsig, 1, 1);
return KNOT_EMALF;
}
-
- knot_rrset_deep_free(&tsig, 1, 1, 1);
-
+
+ knot_rrset_deep_free(&tsig, 1, 1);
+
return KNOT_EOK;
}
@@ -442,20 +436,20 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
{
const uint8_t *pkt = xfr->wire;
size_t size = xfr->wire_size;
- xfrin_constructed_zone_t **constr =
+ xfrin_constructed_zone_t **constr =
(xfrin_constructed_zone_t **)(&xfr->data);
-
+
if (pkt == NULL || constr == NULL) {
return KNOT_EINVAL;
}
-
+
dbg_xfrin_verb("Processing AXFR packet of size %zu.\n", size);
-
+
// check if the response is OK
if (knot_wire_get_rcode(pkt) != KNOT_RCODE_NOERROR) {
return KNOT_EXFRREFUSED;
}
-
+
/*! \todo Should TC bit be checked? */
knot_packet_t *packet =
@@ -465,14 +459,14 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
return KNOT_ENOMEM;
}
- int ret = knot_packet_parse_from_wire(packet, pkt, size, 1);
+ int ret = knot_packet_parse_from_wire(packet, pkt, size, 1, 0);
if (ret != KNOT_EOK) {
dbg_xfrin("Could not parse packet: %s.\n", knot_strerror(ret));
knot_packet_free(&packet);
/*! \todo Cleanup. */
return KNOT_EMALF;
}
-
+
/*! \todo [TSIG] If packet RCODE is NOTAUTH(9), process as TSIG error. */
knot_rrset_t *rr = NULL;
@@ -480,7 +474,7 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
if (ret != KNOT_EOK) {
dbg_xfrin("Could not parse first Answer RR: %s.\n",
- knot_strerror(ret));
+ knot_strerror(ret));
knot_packet_free(&packet);
/*! \todo Cleanup. */
return KNOT_EMALF;
@@ -497,6 +491,9 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
* message corresponds to the SOA RR.
*/
+ /* RR parsed - sort out DNAME duplications. */
+ xfrin_insert_rrset_dnames_to_table(rr, xfr->lookup_tree);
+
knot_node_t *node = NULL;
int in_zone = 0;
knot_zone_contents_t *zone = NULL;
@@ -505,21 +502,31 @@ int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
// this should be the first packet
/*! Packet number for checking TSIG validation. */
xfr->packet_nr = 0;
-
+
// create new zone
/*! \todo Ensure that the packet is the first one. */
if (knot_rrset_type(rr) != KNOT_RRTYPE_SOA) {
dbg_xfrin("No zone created, but the first RR in "
- "Answer is not a SOA RR.\n");
+ "Answer is not a SOA RR.\n");
knot_packet_free(&packet);
knot_node_free(&node);
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
/*! \todo Cleanup. */
return KNOT_EMALF;
}
+
+ /* Check for SOA name and type. */
+ if (knot_packet_qname(packet) == NULL) {
+ dbg_xfrin("Invalid packet in sequence, ignoring.\n");
+ knot_packet_free(&packet);
+ knot_node_free(&node);
+ knot_rrset_deep_free(&rr, 1, 1);
+ return KNOT_EOK;
+ }
+
if (knot_dname_compare(knot_rrset_owner(rr),
- knot_packet_qname(packet)) != 0) {
+ knot_packet_qname(packet)) != 0) {
dbg_xfrin_exec(
char *rr_owner =
knot_dname_to_str(knot_rrset_owner(rr));
@@ -527,7 +534,7 @@ dbg_xfrin_exec(
knot_packet_qname(packet));
dbg_xfrin("Owner of the first SOA RR (%s) does not"
- " match QNAME (%s).\n", rr_owner, qname);
+ " match QNAME (%s).\n", rr_owner, qname);
free(rr_owner);
free(qname);
@@ -535,7 +542,7 @@ dbg_xfrin_exec(
/*! \todo Cleanup. */
knot_packet_free(&packet);
knot_node_free(&node);
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_EMALF;
}
@@ -543,33 +550,32 @@ dbg_xfrin_exec(
if (node == NULL) {
dbg_xfrin("Failed to create new node.\n");
knot_packet_free(&packet);
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_ENOMEM;
}
// the first RR is SOA and its owner and QNAME are the same
// create the zone
-
+
*constr = (xfrin_constructed_zone_t *)malloc(
sizeof(xfrin_constructed_zone_t));
if (*constr == NULL) {
dbg_xfrin("Failed to create new constr. zone.\n");
knot_packet_free(&packet);
knot_node_free(&node);
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_ENOMEM;
}
-
+
memset(*constr, 0, sizeof(xfrin_constructed_zone_t));
-
+
dbg_xfrin_verb("Creating new zone contents.\n");
- (*constr)->contents = knot_zone_contents_new(node, 0, 1,
- xfr->zone);
+ (*constr)->contents = knot_zone_contents_new(node, xfr->zone);
if ((*constr)->contents== NULL) {
dbg_xfrin("Failed to create new zone.\n");
knot_packet_free(&packet);
knot_node_free(&node);
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
/*! \todo Cleanup. */
return KNOT_ENOMEM;
}
@@ -581,19 +587,19 @@ dbg_xfrin_exec(
assert(zone->apex->owner == rr->owner);
// add the RRSet to the node
ret = knot_zone_contents_add_rrset(zone, rr, &node,
- KNOT_RRSET_DUPL_MERGE, 1);
+ KNOT_RRSET_DUPL_MERGE);
if (ret < 0) {
dbg_xfrin("Failed to add RRSet to zone node: %s.\n",
- knot_strerror(ret));
+ knot_strerror(ret));
knot_packet_free(&packet);
knot_node_free(&node);
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
/*! \todo Cleanup. */
return KNOT_ERROR;
} else if (ret > 0) {
dbg_xfrin("Merged SOA RRSet.\n");
// merged, free the RRSet
- knot_rrset_free(&rr);
+ knot_rrset_deep_free(&rr, 1, 0);
}
// take next RR
@@ -602,17 +608,19 @@ dbg_xfrin_exec(
zone = (*constr)->contents;
++xfr->packet_nr;
}
-
+
assert(zone != NULL);
while (ret == KNOT_EOK && rr != NULL) {
// process the parsed RR
dbg_rrset_detail("\nNext RR:\n\n");
- knot_rrset_dump(rr, 0);
+ knot_rrset_dump(rr);
+ /* RR parsed - sort out DNAME duplications. */
+ xfrin_insert_rrset_dnames_to_table(rr, xfr->lookup_tree);
if (node != NULL
- && knot_dname_compare(rr->owner, node->owner) != 0) {
+ && knot_dname_compare_non_canon(rr->owner, node->owner) != 0) {
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(node->owner);
dbg_xfrin_detail("Node owner: %s\n", name);
@@ -634,36 +642,36 @@ dbg_xfrin_exec_detail(
// discard the RR
assert(knot_zone_contents_apex((zone)) != NULL);
assert(knot_node_rrset(knot_zone_contents_apex((zone)),
- KNOT_RRTYPE_SOA) != NULL);
+ KNOT_RRTYPE_SOA) != NULL);
dbg_xfrin_verb("Found last SOA, transfer finished.\n");
-
+
dbg_xfrin_verb("Verifying TSIG...\n");
/*! \note [TSIG] Now check if there is not a TSIG record
- * at the end of the packet.
+ * at the end of the packet.
*/
ret = xfrin_check_tsig(packet, xfr, 1);
-
+
dbg_xfrin_verb("xfrin_check_tsig() returned %d\n", ret);
-
+
knot_packet_free(&packet);
- knot_rrset_deep_free(&rr, 1, 1, 1);
-
+ knot_rrset_deep_free(&rr, 1, 1);
+
if (ret != KNOT_EOK) {
/*! \todo [TSIG] Handle TSIG errors. */
return ret;
}
-
+
// we must now find place for all orphan RRSIGs
- ret = xfrin_process_orphan_rrsigs(zone,
- (*constr)->rrsigs);
+ ret = xfrin_process_orphan_rrsigs(zone,
+ (*constr)->rrsigs);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to process orphan RRSIGs\n");
/*! \todo Cleanup?? */
return ret;
}
-
+
xfrin_free_orphan_rrsigs(&(*constr)->rrsigs);
-
+
return 1;
}
@@ -672,7 +680,7 @@ dbg_xfrin_exec_detail(
// nodes for them
knot_rrset_t *tmp_rrset = NULL;
ret = knot_zone_contents_add_rrsigs(zone, rr,
- &tmp_rrset, &node, KNOT_RRSET_DUPL_MERGE, 1);
+ &tmp_rrset, &node, KNOT_RRSET_DUPL_MERGE);
if (ret == KNOT_ENONODE || ret == KNOT_ENORRSET) {
dbg_xfrin_verb("No node or RRSet for RRSIGs\n");
dbg_xfrin_verb("Saving for later insertion.\n");
@@ -681,37 +689,35 @@ dbg_xfrin_exec_detail(
in_zone = 1;
}
- ret = xfrin_add_orphan_rrsig(&(*constr)->rrsigs,
- rr);
+ ret = xfrin_add_orphan_rrsig(&(*constr)->rrsigs,
+ rr);
if (ret > 0) {
dbg_xfrin_detail("Merged RRSIGs.\n");
- knot_rrset_free(&rr);
+ knot_rrset_deep_free(&rr, 1, 0);
} else if (ret != KNOT_EOK) {
dbg_xfrin("Failed to save orphan"
- " RRSIGs.\n");
+ " RRSIGs.\n");
knot_packet_free(&packet);
- knot_node_free(&node); // ???
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return ret;
}
} else if (ret < 0) {
dbg_xfrin("Failed to add RRSIGs (%s).\n",
- knot_strerror(ret));
+ knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node); // ???
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_ERROR; /*! \todo Other error code. */
} else if (ret == 1) {
assert(node != NULL);
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(node->owner);
dbg_xfrin_detail("Found node for the record in "
- "zone: %s. Merged.\n", name);
+ "zone: %s. Merged.\n", name);
free(name);
);
in_zone = 1;
- knot_rrset_deep_free(&rr, 1, 0, 0);
+ knot_rrset_deep_free(&rr, 1, 0);
} else if (ret == 2) {
// should not happen
assert(0);
@@ -720,7 +726,7 @@ dbg_xfrin_exec_verb(
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(node->owner);
dbg_xfrin_detail("Found node for the record in "
- "zone: %s.\n", name);
+ "zone: %s.\n", name);
free(name);
);
in_zone = 1;
@@ -732,21 +738,21 @@ dbg_xfrin_exec_verb(
continue;
}
-
+
/* TSIG where it should not be - in Answer section.*/
if (knot_rrset_type(rr) == KNOT_RRTYPE_TSIG) {
// not allowed here
dbg_xfrin("TSIG in Answer section.\n");
knot_packet_free(&packet);
knot_node_free(&node); // ???
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_EMALF;
}
knot_node_t *(*get_node)(const knot_zone_contents_t *,
- const knot_dname_t *) = NULL;
+ const knot_dname_t *) = NULL;
int (*add_node)(knot_zone_contents_t *, knot_node_t *, int,
- uint8_t, int) = NULL;
+ uint8_t) = NULL;
if (knot_rrset_type(rr) == KNOT_RRTYPE_NSEC3) {
get_node = knot_zone_contents_get_nsec3_node;
@@ -757,7 +763,7 @@ dbg_xfrin_exec_verb(
}
if (node == NULL && (node = get_node(zone,
- knot_rrset_owner(rr))) != NULL) {
+ knot_rrset_owner(rr))) != NULL) {
// the node for this RR was found in the zone
dbg_xfrin_detail("Found node for the record in zone\n");
in_zone = 1;
@@ -770,19 +776,19 @@ dbg_xfrin_exec_verb(
if (node == NULL) {
dbg_xfrin("Failed to create new node.\n");
knot_packet_free(&packet);
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_ENOMEM;
}
dbg_xfrin_detail("Created new node for the record.\n");
// insert the RRSet to the node
- ret = knot_node_add_rrset_no_dupl(node, rr);
+ ret = knot_node_add_rrset(node, rr);
if (ret < 0) {
dbg_xfrin("Failed to add RRSet to node (%s)\n",
- knot_strerror(ret));
+ knot_strerror(ret));
knot_packet_free(&packet);
knot_node_free(&node); // ???
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_ERROR;
} else if (ret > 0) {
// should not happen, this is new node
@@ -790,14 +796,14 @@ dbg_xfrin_exec_verb(
}
// insert the node into the zone
- ret = add_node(zone, node, 1, 0, 1);
+ ret = add_node(zone, node, 1, 0);
assert(node != NULL);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add node to zone (%s).\n",
- knot_strerror(ret));
+ knot_strerror(ret));
knot_packet_free(&packet);
knot_node_free(&node); // ???
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_ERROR;
}
@@ -806,15 +812,15 @@ dbg_xfrin_exec_verb(
assert(in_zone);
ret = knot_zone_contents_add_rrset(zone, rr, &node,
- KNOT_RRSET_DUPL_MERGE, 1);
+ KNOT_RRSET_DUPL_MERGE);
if (ret < 0) {
knot_packet_free(&packet);
dbg_xfrin("Failed to add RRSet to zone :%s.\n",
- knot_strerror(ret));
+ knot_strerror(ret));
return KNOT_ERROR;
} else if (ret > 0) {
// merged, free the RRSet
- knot_rrset_free(&rr);
+ knot_rrset_deep_free(&rr, 1, 0);
}
}
@@ -836,7 +842,7 @@ dbg_xfrin_exec_verb(
knot_node_free(&node);
}
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
return KNOT_EMALF;
}
@@ -846,27 +852,27 @@ dbg_xfrin_exec_verb(
// if the last node is not yet in the zone, insert
if (!in_zone) {
assert(node != NULL);
- ret = knot_zone_contents_add_node(zone, node, 1, 0, 1);
+ ret = knot_zone_contents_add_node(zone, node, 1, 0);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add last node into zone (%s).\n",
- knot_strerror(ret));
+ knot_strerror(ret));
knot_packet_free(&packet);
knot_node_free(&node);
return KNOT_ERROR; /*! \todo Other error */
}
}
-
+
/* Now check if there is not a TSIG record at the end of the packet. */
- ret = xfrin_check_tsig(packet, xfr,
- knot_ns_tsig_required(xfr->packet_nr));
+ ret = xfrin_check_tsig(packet, xfr,
+ knot_ns_tsig_required(xfr->packet_nr));
++xfr->packet_nr;
-
+
knot_packet_free(&packet);
dbg_xfrin_verb("Processed one AXFR packet successfully.\n");
-
+
/* TSIG errors are propagated and reported in a standard
- * manner, as we're in response processing, no further error response
- * should be sent.
+ * manner, as we're in response processing, no further error response
+ * should be sent.
*/
return ret;
@@ -886,13 +892,13 @@ static int xfrin_parse_first_rr(knot_packet_t **packet, const uint8_t *pkt,
return KNOT_ENOMEM;
}
- int ret = knot_packet_parse_from_wire(*packet, pkt, size, 1);
+ int ret = knot_packet_parse_from_wire(*packet, pkt, size, 1, 0);
if (ret != KNOT_EOK) {
dbg_xfrin("Could not parse packet: %s.\n", knot_strerror(ret));
knot_packet_free(packet);
return KNOT_EMALF;
}
-
+
// check if the TC bit is set (it must not be)
if (knot_wire_get_tc(pkt)) {
dbg_xfrin("IXFR response has TC bit set.\n");
@@ -904,7 +910,7 @@ static int xfrin_parse_first_rr(knot_packet_t **packet, const uint8_t *pkt,
if (ret != KNOT_EOK) {
dbg_xfrin("Could not parse first Answer RR: %s.\n",
- knot_strerror(ret));
+ knot_strerror(ret));
knot_packet_free(packet);
return KNOT_EMALF;
}
@@ -919,12 +925,12 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
size_t size = xfr->wire_size;
const uint8_t *pkt = xfr->wire;
knot_changesets_t **chs = (knot_changesets_t **)(&xfr->data);
-
+
if (pkt == NULL || chs == NULL) {
dbg_xfrin("Wrong parameters supported.\n");
return KNOT_EINVAL;
}
-
+
// check if the response is OK
if (knot_wire_get_rcode(pkt) != KNOT_RCODE_NOERROR) {
return KNOT_EXFRREFUSED;
@@ -934,13 +940,13 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
knot_rrset_t *rr = NULL;
int ret;
-
+
if ((ret = xfrin_parse_first_rr(&packet, pkt, size, &rr)) != KNOT_EOK) {
return ret;
}
assert(packet != NULL);
-
+
// state of the transfer
// -1 .. a SOA is expected to create a new changeset
int state = 0;
@@ -951,13 +957,15 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
/*! \todo Some other action??? */
return KNOT_EMALF;
}
-
+
+ xfrin_insert_rrset_dnames_to_table(rr, xfr->lookup_tree);
+
if (*chs == NULL) {
dbg_xfrin_verb("Changesets empty, creating new.\n");
-
+
ret = knot_changeset_allocate(chs, KNOT_CHANGESET_TYPE_IXFR);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
knot_packet_free(&packet);
return ret;
}
@@ -965,24 +973,24 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
// the first RR must be a SOA
if (knot_rrset_type(rr) != KNOT_RRTYPE_SOA) {
dbg_xfrin("First RR is not a SOA RR!\n");
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
ret = KNOT_EMALF;
goto cleanup;
}
-
+
// just store the first SOA for later use
(*chs)->first_soa = rr;
state = -1;
-
+
dbg_xfrin_verb("First SOA of IXFR saved, state set to -1.\n");
-
+
// parse the next one
ret = knot_packet_parse_next_rr_answer(packet, &rr);
if (ret != KNOT_EOK) {
knot_packet_free(&packet);
return ret;
}
-
+
/*
* If there is no other records in the response than the SOA, it
* means one of these three cases:
@@ -990,7 +998,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
* 1) The server does not have newer zone than ours.
* This is indicated by serial equal to the one of our zone.
* 2) The server wants to send the transfer but is unable to fit
- * it in the packet. This is indicated by serial different
+ * it in the packet. This is indicated by serial different
* (newer) from the one of our zone, but applies only for
* IXFR/UDP.
* 3) The master is weird and sends only SOA in the first packet
@@ -1004,7 +1012,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
knot_packet_free(&packet);
return XFRIN_RES_SOA_ONLY;
} else if (knot_rrset_type(rr) != KNOT_RRTYPE_SOA) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
knot_packet_free(&packet);
dbg_xfrin("Fallback to AXFR.\n");
ret = XFRIN_RES_FALLBACK;
@@ -1013,7 +1021,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
} else {
if ((*chs)->first_soa == NULL) {
dbg_xfrin("Changesets don't contain SOA first!\n");
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
ret = KNOT_EINVAL;
goto cleanup;
}
@@ -1021,7 +1029,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
}
/*
- * Process the next RR. Different requirements are in place in
+ * Process the next RR. Different requirements are in place in
* different cases:
*
* 1) Last changeset has both soa_from and soa_to.
@@ -1031,60 +1039,61 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
* the end should be signalised by returning positive value.
*
* ii) The next RR is some other SOA.
- * This means a start of new changeset - create it and add it
+ * This means a start of new changeset - create it and add it
* to the list.
*
* b) The next RR is not a SOA.
* Put the RR into the ADD part of the last changeset as this is
* not finished yet. Continue while SOA is not encountered. Then
* jump to 1-a.
- *
+ *
* 2) Last changeset has only the soa_from and does not have soa_to.
* a) The next RR is a SOA.
- * This means start of the ADD section. Put the SOA to the
+ * This means start of the ADD section. Put the SOA to the
* changeset. Continue adding RRs to the ADD section while SOA
* is not encountered. This is identical to 1-b.
*
* b) The next RR is not a SOA.
* This means the REMOVE part is not finished yet. Add the RR to
- * the REMOVE part. Continue adding next RRs until a SOA is
+ * the REMOVE part. Continue adding next RRs until a SOA is
* encountered. Then jump to 2-a.
*/
-
+
// first, find out in what state we are
- /*! \todo It would be more elegant to store the state in the
+ /*! \todo It would be more elegant to store the state in the
* changesets structure, or in some place persistent between
* calls to this function.
*/
+ knot_changeset_t *cur = (*chs)->sets + ((*chs)->count - 1);
if (state != -1) {
dbg_xfrin_detail("State is not -1, deciding...\n");
// there should be at least one started changeset right now
if ((*chs)->count <= 0) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
ret = KNOT_EMALF;
goto cleanup;
}
-
+
// a changeset should be created only when there is a SOA
- assert((*chs)->sets[(*chs)->count - 1].soa_from != NULL);
-
- if ((*chs)->sets[(*chs)->count - 1].soa_to == NULL) {
+ assert(cur->soa_from != NULL);
+
+ if (cur->soa_to == NULL) {
state = KNOT_CHANGESET_REMOVE;
} else {
state = KNOT_CHANGESET_ADD;
}
}
-
+
dbg_xfrin_detail("State before the loop: %d\n", state);
-
+
/*! \todo This may be implemented with much less IFs! */
-
+
while (ret == KNOT_EOK && rr != NULL) {
dbg_xfrin_exec_verb(
dbg_xfrin_detail("Next loop, state: %d\n", state);
char *name = knot_dname_to_str(knot_rrset_owner(rr));
- dbg_xfrin_detail("Actual RR: %s, type %s.\n", name,
- knot_rrtype_to_string(knot_rrset_type(rr)));
+ dbg_xfrin_detail("Actual RR: %s, type %u.\n", name,
+ knot_rrset_type(rr));
free(name);
);
switch (state) {
@@ -1095,51 +1104,55 @@ dbg_xfrin_exec_verb(
// is quite weird in fact
if (knot_rrset_type(rr) != KNOT_RRTYPE_SOA) {
dbg_xfrin("First RR is not a SOA RR!\n");
- dbg_xfrin_verb("RR type: %s\n",
- knot_rrtype_to_string(knot_rrset_type(rr)));
+ dbg_xfrin_verb("RR type: %u\n",
+ knot_rrset_type(rr));
ret = KNOT_EMALF;
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
goto cleanup;
}
-
- if (knot_rdata_soa_serial(knot_rrset_rdata(rr))
- == knot_rdata_soa_serial(
- knot_rrset_rdata((*chs)->first_soa))) {
-
+
+ if (knot_rrset_rdata_soa_serial(rr)
+ == knot_rrset_rdata_soa_serial((*chs)->first_soa)) {
+
/*! \note [TSIG] Check TSIG, we're at the end of
- * transfer.
+ * transfer.
*/
ret = xfrin_check_tsig(packet, xfr, 1);
-
+
// last SOA, discard and end
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
knot_packet_free(&packet);
-
- /*! \note [TSIG] If TSIG validates, consider
+
+ /*! \note [TSIG] If TSIG validates, consider
* transfer complete. */
if (ret == KNOT_EOK) {
ret = XFRIN_RES_COMPLETE;
}
-
+
return ret;
} else {
// normal SOA, start new changeset
(*chs)->count++;
- if ((ret = knot_changesets_check_size(*chs))
- != KNOT_EOK) {
+ ret = knot_changesets_check_size(*chs);
+
+ /* Check changesets for maximum count (so they fit into journal). */
+ if ((*chs)->count > JOURNAL_NCOUNT)
+ ret = KNOT_ESPACE;
+
+ if (ret != KNOT_EOK) {
(*chs)->count--;
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
goto cleanup;
}
-
- ret = knot_changeset_add_soa(
- &(*chs)->sets[(*chs)->count - 1], rr,
- KNOT_CHANGESET_REMOVE);
+
+ cur = (*chs)->sets + ((*chs)->count - 1);
+ ret = knot_changeset_add_soa(cur, rr,
+ KNOT_CHANGESET_REMOVE);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
goto cleanup;
}
-
+
// change state to REMOVE
state = KNOT_CHANGESET_REMOVE;
}
@@ -1149,25 +1162,23 @@ dbg_xfrin_exec_verb(
// ADD
if (knot_rrset_type(rr) == KNOT_RRTYPE_SOA) {
// we should not be here if soa_from is not set
- assert((*chs)->sets[(*chs)->count - 1].soa_from
- != NULL);
-
- ret = knot_changeset_add_soa(
- &(*chs)->sets[(*chs)->count - 1], rr,
- KNOT_CHANGESET_ADD);
+ assert(cur->soa_from != NULL);
+
+ ret = knot_changeset_add_soa(cur, rr,
+ KNOT_CHANGESET_ADD);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ knot_rrset_deep_free(&rr, 1, 1);
goto cleanup;
}
-
+
state = KNOT_CHANGESET_ADD;
} else {
// just add the RR to the REMOVE part and
// continue
- if ((ret = knot_changeset_add_new_rr(
- &(*chs)->sets[(*chs)->count - 1], rr,
- KNOT_CHANGESET_REMOVE)) != KNOT_EOK) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ ret = knot_changeset_add_new_rr(cur, rr,
+ KNOT_CHANGESET_REMOVE);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&rr, 1, 1);
goto cleanup;
}
}
@@ -1176,40 +1187,44 @@ dbg_xfrin_exec_verb(
// if the next RR is SOA change to state -1 and do not
// parse next RR
if (knot_rrset_type(rr) == KNOT_RRTYPE_SOA) {
+ log_zone_info("%s Serial %u -> %u.\n",
+ xfr->msg,
+ knot_rrset_rdata_soa_serial(cur->soa_from),
+ knot_rrset_rdata_soa_serial(cur->soa_to));
state = -1;
continue;
} else {
-
+
// just add the RR to the ADD part and continue
- if ((ret = knot_changeset_add_new_rr(
- &(*chs)->sets[(*chs)->count - 1], rr,
- KNOT_CHANGESET_ADD)) != KNOT_EOK) {
- knot_rrset_deep_free(&rr, 1, 1, 1);
+ ret = knot_changeset_add_new_rr(cur, rr,
+ KNOT_CHANGESET_ADD);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&rr, 1, 1);
goto cleanup;
}
}
break;
}
-
+
// parse the next RR
dbg_xfrin_detail("Parsing next RR..\n");
ret = knot_packet_parse_next_rr_answer(packet, &rr);
dbg_xfrin_detail("Returned %d, %p.\n", ret, rr);
}
-
- /*! \note Check TSIG, we're at the end of packet. It may not be
- * required.
+
+ /*! \note Check TSIG, we're at the end of packet. It may not be
+ * required.
*/
- ret = xfrin_check_tsig(packet, xfr,
- knot_ns_tsig_required(xfr->packet_nr));
+ ret = xfrin_check_tsig(packet, xfr,
+ knot_ns_tsig_required(xfr->packet_nr));
dbg_xfrin_verb("xfrin_check_tsig() returned %d\n", ret);
++xfr->packet_nr;
-
+
/*! \note [TSIG] Cleanup and propagate error if TSIG validation fails.*/
if (ret != KNOT_EOK) {
goto cleanup;
}
-
+
// here no RRs remain in the packet but the transfer is not finished
// yet, return EOK
knot_packet_free(&packet);
@@ -1218,7 +1233,7 @@ dbg_xfrin_exec_verb(
cleanup:
/* We should go here only if some error occured. */
assert(ret < 0);
-
+
dbg_xfrin_detail("Cleanup after processing IXFR/IN packet.\n");
knot_free_changesets(chs);
knot_packet_free(&packet);
@@ -1233,10 +1248,6 @@ cleanup:
static void xfrin_zone_contents_free(knot_zone_contents_t **contents)
{
/*! \todo This should be all in some API!! */
-
- if ((*contents)->table != NULL) {
- ck_destroy_table(&(*contents)->table, NULL, 0);
- }
// free the zone tree with nodes
dbg_zone("Destroying zone tree.\n");
@@ -1246,138 +1257,89 @@ static void xfrin_zone_contents_free(knot_zone_contents_t **contents)
knot_nsec3_params_free(&(*contents)->nsec3_params);
- knot_dname_table_deep_free(&(*contents)->dname_table);
-
free(*contents);
*contents = NULL;
}
/*----------------------------------------------------------------------------*/
-static knot_rdata_t *xfrin_remove_rdata(knot_rrset_t *from,
- const knot_rrset_t *what,
- int ddns_check)
-{
- knot_rdata_t *old = NULL;
- knot_rdata_t *old_actual = NULL;
-
- const knot_rdata_t *rdata = knot_rrset_rdata(what);
-
- while (rdata != NULL) {
- // rdata - the RDATA to be removed
- // old_actual - removed RDATA
-
- /*
- * DDNS special handling - last apex NS should remain in the
- * zone.
- *
- * TODO: this is not correct, the last NS from the 'what' RRSet
- * may not even be in the zone.
- */
- if (ddns_check
- && knot_rrset_rdata_next(what, rdata) == NULL) {
- assert(knot_rrset_type(from) == KNOT_RRTYPE_NS);
- return old;
- }
-
- old_actual = knot_rrset_remove_rdata(from, rdata);
- if (old_actual != NULL) {
- old_actual->next = old;
- old = old_actual;
- }
- rdata = knot_rrset_rdata_next(what, rdata);
- }
-
- // returning chain of removed RDATA (terminated with NULL)
- return old;
-}
-
-/*----------------------------------------------------------------------------*/
-
int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
knot_changes_t *changes, int save_new)
{
dbg_xfrin_detail("Copying old RRSet: %p\n", old);
// create new RRSet by copying the old one
- int ret = knot_rrset_deep_copy(old, copy, 0);
+ int ret = knot_rrset_deep_copy(old, copy, 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to create RRSet copy.\n");
return KNOT_ENOMEM;
}
-
+
int count = 0;
// add the RRSet to the list of new RRSets
// create place also for RRSIGs
if (save_new) {
+ count = 1;
+ count += (*copy)->rrsigs ? 1 : 0;
ret = knot_changes_rrsets_reserve(&changes->new_rrsets,
&changes->new_rrsets_count,
&changes->new_rrsets_allocated,
- 2);
+ count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RRSet to list.\n");
- knot_rrset_deep_free(copy, 1, 1, 1);
+ knot_rrset_deep_free(copy, 1, 1);
return ret;
}
- count = knot_rrset_rdata_rr_count(*copy);
- count += knot_rrset_rdata_rr_count((*copy)->rrsigs);
-
+
// add the copied RDATA to the list of new RDATA
ret = knot_changes_rdata_reserve(&changes->new_rdata,
- &changes->new_rdata_types,
changes->new_rdata_count,
- &changes->new_rdata_allocated,
- count);
+ &changes->new_rdata_allocated,
+ count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RRSet to list.\n");
- knot_rrset_deep_free(copy, 1, 1, 1);
+ knot_rrset_deep_free(copy, 1, 1);
return ret;
}
-
+
changes->new_rrsets[changes->new_rrsets_count++] = *copy;
-
+
dbg_xfrin_detail("Adding RDATA from the RRSet copy to new RDATA list."
"\n");
- knot_changes_add_rdata(changes->new_rdata,
- changes->new_rdata_types,
+ knot_changes_add_rdata(changes->new_rdata,
&changes->new_rdata_count,
- knot_rrset_get_rdata(*copy),
- knot_rrset_type(*copy));
+ *copy);
if ((*copy)->rrsigs != NULL) {
assert(old->rrsigs != NULL);
changes->new_rrsets[changes->new_rrsets_count++] =
(*copy)->rrsigs;
-
+
dbg_xfrin_detail("Adding RDATA from RRSIG of the RRSet copy to "
"new RDATA list.\n");
knot_changes_add_rdata(changes->new_rdata,
- changes->new_rdata_types,
&changes->new_rdata_count,
- knot_rrset_get_rdata(
- (*copy)->rrsigs),
- KNOT_RRTYPE_RRSIG);
+ (*copy)->rrsigs);
}
}
+ count = 1;
+ count += old->rrsigs ? 1 : 0;
+
// add the old RRSet to the list of old RRSets
ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
- &changes->old_rrsets_count,
- &changes->old_rrsets_allocated, 2);
+ &changes->old_rrsets_count,
+ &changes->old_rrsets_allocated, count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add old RRSet to list.\n");
return ret;
}
- count = knot_rrset_rdata_rr_count(old);
- count += knot_rrset_rdata_rr_count(old->rrsigs);
-
// and old RDATA to the list of old RDATA
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
- changes->old_rdata_count,
- &changes->old_rdata_allocated, count);
+ changes->old_rdata_count,
+ &changes->old_rdata_allocated, count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add old RRSet to list.\n");
return ret;
@@ -1386,21 +1348,18 @@ int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
changes->old_rrsets[changes->old_rrsets_count++] = old;
dbg_xfrin_detail("Adding RDATA from old RRSet to old RDATA list.\n");
- knot_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
- &changes->old_rdata_count, old->rdata,
- knot_rrset_type(old));
+ knot_changes_add_rdata(changes->old_rdata, &changes->old_rdata_count,
+ old);
if ((*copy)->rrsigs != NULL) {
assert(old->rrsigs != NULL);
changes->old_rrsets[changes->old_rrsets_count++] = old->rrsigs;
dbg_xfrin_detail("Adding RDATA from RRSIG of the old RRSet to "
- "old RDATA list.\n");
+ "old RDATA list.\n");
knot_changes_add_rdata(changes->old_rdata,
- changes->old_rdata_types,
- &changes->old_rdata_count,
- old->rrsigs->rdata,
- KNOT_RRTYPE_RRSIG);
+ &changes->old_rdata_count,
+ old->rrsigs);
}
return KNOT_EOK;
@@ -1408,21 +1367,21 @@ int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
/*----------------------------------------------------------------------------*/
-int xfrin_copy_rrset(knot_node_t *node, knot_rr_type_t type,
+int xfrin_copy_rrset(knot_node_t *node, uint16_t type,
knot_rrset_t **rrset, knot_changes_t *changes,
int save_new)
{
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_node_owner(node));
- dbg_xfrin_detail("Removing RRSet of type %s from node %s (%p)\n",
- knot_rrtype_to_string(type), name, node);
+ dbg_xfrin_detail("Removing RRSet of type %u from node %s (%p)\n",
+ type, name, node);
free(name);
);
knot_rrset_t *old = knot_node_remove_rrset(node, type);
dbg_xfrin_detail("Removed RRSet: %p\n", old);
dbg_xfrin_detail("Other RRSet of the same type in the node: %p\n",
- knot_node_rrset(node, type));
+ knot_node_rrset(node, type));
if (old == NULL) {
dbg_xfrin_verb("RRSet not found for RR to be removed.\n");
@@ -1433,16 +1392,16 @@ dbg_xfrin_exec_detail(
if (ret != KNOT_EOK) {
return ret;
}
-
+
dbg_xfrin_detail("Copied old rrset %p to new %p.\n", old, *rrset);
-
+
// replace the RRSet in the node copy by the new one
- ret = knot_node_add_rrset(node, *rrset, 0);
+ ret = knot_node_add_rrset_replace(node, *rrset);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add RRSet copy to node\n");
return KNOT_ERROR;
}
-
+
return KNOT_EOK;
}
@@ -1459,29 +1418,29 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
assert(node != NULL);
assert(rrset != NULL);
assert(knot_rrset_type(remove) == KNOT_RRTYPE_RRSIG);
-
+
/*! \todo These optimalizations may be useless as there may be only
* one RRSet of each type and owner in the changeset.
*/
-
- int ret;
+
+ int ret = KNOT_EOK;
int copied = 0;
if (*rrset
- && knot_dname_compare(knot_rrset_owner(*rrset),
- knot_node_owner(node)) == 0
- && knot_rrset_type(*rrset) == knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(remove))) {
+ && knot_dname_compare_non_canon(knot_rrset_owner(*rrset),
+ knot_node_owner(node)) == 0
+ && knot_rrset_type(*rrset) == knot_rrset_rdata_rrsig_type_covered(
+ remove)) {
// this RRSet should be the already copied RRSet so we may
// update it right away
/*! \todo Does this case even occur? */
dbg_xfrin_verb("Using RRSet from previous iteration.\n");
} else {
// find RRSet based on the Type Covered
- knot_rr_type_t type = knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(remove));
-
+ uint16_t type =
+ knot_rrset_rdata_rrsig_type_covered(remove);
+
// copy the rrset
dbg_xfrin_detail("Copying RRSet that carries the RRSIGs.\n");
ret = xfrin_copy_rrset(node, type, rrset, changes, 1);
@@ -1490,7 +1449,7 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
return ret;
}
dbg_xfrin_detail("Copied RRSet:\n");
- knot_rrset_dump(*rrset, 0);
+ knot_rrset_dump(*rrset);
copied = 1;
}
@@ -1500,7 +1459,7 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
if (old == NULL) {
return 1;
}
-
+
// copy the RRSIGs
knot_rrset_t *rrsigs = NULL;
if (!copied) {
@@ -1515,13 +1474,13 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
}
dbg_xfrin_detail("Copied RRSIGs: %p\n", rrsigs);
dbg_xfrin_detail("Copied RRSet:\n");
- knot_rrset_dump(rrsigs, 0);
+ knot_rrset_dump(rrsigs);
}
} else {
rrsigs = old;
dbg_xfrin_detail("Using old RRSIGs: %p\n", rrsigs);
}
-
+
// set the RRSIGs to the new RRSet copy
if (knot_rrset_set_rrsigs(*rrset, rrsigs) != KNOT_EOK) {
dbg_xfrin("Failed to set rrsigs.\n");
@@ -1530,81 +1489,82 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
*rrsigs_old = rrsigs;
- // now in '*rrset' we have a copy of the RRSet which holds the RRSIGs
+ // now in '*rrset' we have a copy of the RRSet which holds the RRSIGs
// and in 'rrsigs' we have the copy of the RRSIGs
-
- knot_rdata_t *rdata = xfrin_remove_rdata(rrsigs, remove, 0);
- if (rdata == NULL) {
+
+ knot_rrset_t *rr_removed = NULL;
+ ret = knot_rrset_remove_rr_using_rrset(rrsigs, remove, &rr_removed, 0);
+ if (ret != KNOT_EOK) {
dbg_xfrin("Failed to remove RDATA from RRSet: %s.\n",
- knot_strerror(ret));
+ knot_strerror(ret));
return 1;
}
+ /*!< \todo This RRSet will be created even when nothing was removed. */
+ assert(rr_removed);
-
- int count = knot_rdata_count(rdata);
+ int count = 1;
// connect the RDATA to the list of old RDATA
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
- changes->old_rdata_count,
- &changes->old_rdata_allocated, count);
+ changes->old_rdata_count,
+ &changes->old_rdata_allocated, count);
if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&rr_removed, 1, 1);
return ret;
}
- knot_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
- &changes->old_rdata_count, rdata,
- knot_rrset_type(remove));
-
+ knot_changes_add_rdata(changes->old_rdata, &changes->old_rdata_count,
+ rr_removed);
+
// if the RRSet is empty, remove from node and add to old RRSets
// check if there is no RRSIGs; if there are, leave the RRSet
// there; it may be eventually removed when the RRSIGs are removed
- if (knot_rrset_rdata(rrsigs) == NULL) {
+ if (knot_rrset_rdata_rr_count(rrsigs) == 0) {
// remove the RRSIGs from the RRSet
knot_rrset_set_rrsigs(*rrset, NULL);
-
+
// add RRSet to the list of old RRSets
ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
- &changes->old_rrsets_count,
- &changes->old_rrsets_allocated,
- 1);
+ &changes->old_rrsets_count,
+ &changes->old_rrsets_allocated,
+ 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add empty RRSet to the "
- "list of old RRSets.");
+ "list of old RRSets.");
// delete the RRSet right away
knot_rrset_free(&rrsigs);
return ret;
}
-
+
changes->old_rrsets[changes->old_rrsets_count++] = rrsigs;
// saving old RDATA is not necessary as there is none
-
+
// now check if the RRSet is not totally empty
- if (knot_rrset_rdata(*rrset) == NULL) {
+ if (knot_rrset_rdata_rr_count(*rrset) == 0) {
assert(knot_rrset_rrsigs(*rrset) == NULL);
-
+
// remove the whole RRSet from the node
knot_rrset_t *tmp = knot_node_remove_rrset(node,
- knot_rrset_type(*rrset));
+ knot_rrset_type(*rrset));
assert(tmp == *rrset);
-
+
ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
- &changes->old_rrsets_count,
- &changes->old_rrsets_allocated,
- 1);
+ &changes->old_rrsets_count,
+ &changes->old_rrsets_allocated,
+ 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add empty RRSet to "
- "the list of old RRSets.");
+ "the list of old RRSets.");
// delete the RRSet right away
knot_rrset_free(rrset);
return ret;
}
-
- changes->old_rrsets[changes->old_rrsets_count++] =
+
+ changes->old_rrsets[changes->old_rrsets_count++] =
*rrset;
}
}
-
+
return KNOT_EOK;
}
@@ -1620,11 +1580,11 @@ static int xfrin_apply_remove_normal(knot_changes_t *changes,
assert(remove != NULL);
assert(node != NULL);
assert(rrset != NULL);
-
+
int ret;
-
+
dbg_xfrin_detail("Removing RRSet: \n");
- knot_rrset_dump(remove, 0);
+ knot_rrset_dump(remove);
int is_apex = knot_node_rrset(node, KNOT_RRTYPE_SOA) != NULL;
@@ -1641,15 +1601,15 @@ static int xfrin_apply_remove_normal(knot_changes_t *changes,
// check if we do not already have it
if (*rrset
&& knot_dname_compare(knot_rrset_owner(*rrset),
- knot_node_owner(node)) == 0
+ knot_node_owner(node)) == 0
&& knot_rrset_type(*rrset) == knot_rrset_type(remove)) {
/*! \todo Does some other case even occur? */
dbg_xfrin_verb("Using RRSet from previous loop.\n");
} else {
/*!
- * \todo This may happen also with already
+ * \todo This may happen also with already
* copied RRSet. In that case it would be
- * an unnecesary overhead but will
+ * an unnecesary overhead but will
* probably not cause problems. TEST!!
*/
ret = xfrin_copy_rrset(node,
@@ -1658,94 +1618,94 @@ static int xfrin_apply_remove_normal(knot_changes_t *changes,
return ret;
}
dbg_xfrin_detail("Copied RRSet:\n");
- knot_rrset_dump(*rrset, 0);
+ knot_rrset_dump(*rrset);
}
-
+
if (*rrset == NULL) {
dbg_xfrin_verb("RRSet not found for RR to be removed.\n");
return 1;
}
-
+
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
- dbg_xfrin_detail("Updating RRSet with owner %s, type %s\n", name,
- knot_rrtype_to_string(knot_rrset_type(*rrset)));
+ dbg_xfrin_detail("Updating RRSet with owner %s, type %u\n", name,
+ knot_rrset_type(*rrset));
free(name);
);
// remove the specified RRs from the RRSet (de facto difference of sets)
int ddns_remove_ns_from_apex =
- ((chflags & KNOT_CHANGESET_TYPE_DDNS) && is_apex
- && knot_rrset_type(*rrset) == KNOT_RRTYPE_NS);
- knot_rdata_t *rdata = xfrin_remove_rdata(*rrset, remove,
- ddns_remove_ns_from_apex);
- if (rdata == NULL && !ddns_remove_ns_from_apex) {
+ ((chflags & KNOT_CHANGESET_TYPE_DDNS) && is_apex
+ && knot_rrset_type(*rrset) == KNOT_RRTYPE_NS);
+ knot_rrset_t *rr_remove = NULL;
+ ret = knot_rrset_remove_rr_using_rrset(*rrset, remove, &rr_remove,
+ ddns_remove_ns_from_apex);
+ if (ret != KNOT_EOK) {
+ dbg_xfrin("xfr: remove_normal: Could not remove RR (%s).\n",
+ knot_strerror(ret));
+ return ret;
+ }
+ /*!< \todo either one of these checks should be enough. */
+ if (knot_rrset_rdata_rr_count(rr_remove) == 0
+ && !ddns_remove_ns_from_apex) {
+ /* No RDATA, no need to deep free. */
+ knot_rrset_free(&rr_remove);
dbg_xfrin_verb("Failed to remove RDATA from RRSet\n");
// In this case, the RDATA was not found in the RRSet
return 1;
}
-
-dbg_xfrin_exec_detail(
- dbg_xfrin_detail("Removed rdata: \n");
- knot_rdata_t *r = rdata;
- if (r != NULL) {
- do {
- dbg_xfrin_detail("pointer: %p\n", r);
- knot_rdata_dump(r, knot_rrset_type(remove), 0);
- r = r->next;
- } while (r != NULL && r != rdata);
- }
-);
- if (rdata != NULL) {
- int count = knot_rdata_count(rdata);
+ if (rr_remove->rdata_count != 0) {
+ int count = 1;
// connect the RDATA to the list of old RDATA
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
- changes->old_rdata_count,
- &changes->old_rdata_allocated,
- count);
+ changes->old_rdata_count,
+ &changes->old_rdata_allocated,
+ count);
if (ret != KNOT_EOK) {
+ knot_rrset_free(&rr_remove);
return ret;
}
knot_changes_add_rdata(changes->old_rdata,
- changes->old_rdata_types,
- &changes->old_rdata_count, rdata,
- knot_rrset_type(remove));
+ &changes->old_rdata_count, rr_remove);
+ } else {
+ /* Discard empty RRSet. */
+ knot_rrset_free(&rr_remove);
}
-
+
// if the RRSet is empty, remove from node and add to old RRSets
// check if there is no RRSIGs; if there are, leave the RRSet
// there; it may be eventually removed when the RRSIGs are removed
- if (knot_rrset_rdata(*rrset) == NULL
+ if (knot_rrset_rdata_rr_count(*rrset) == 0
&& knot_rrset_rrsigs(*rrset) == NULL) {
// The RRSet should not be empty if we were removing NSs from
// apex in case of DDNS
assert(!ddns_remove_ns_from_apex);
-
+
knot_rrset_t *tmp = knot_node_remove_rrset(node,
- knot_rrset_type(*rrset));
- dbg_xfrin_detail("Removed whole RRSet (%p).\n", tmp);
-
+ knot_rrset_type(*rrset));
+ dbg_xfrin_detail("Removed whole RRSet (%p). Node rr count=%d\n",
+ tmp, knot_node_rrset_count(node));
+
// add the removed RRSet to list of old RRSets
-
+
assert(tmp == *rrset);
ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
- &changes->old_rrsets_count,
- &changes->old_rrsets_allocated,
- 1);
+ &changes->old_rrsets_count,
+ &changes->old_rrsets_allocated,
+ 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add empty RRSet to the "
- "list of old RRSets.");
+ "list of old RRSets.");
// delete the RRSet right away
knot_rrset_free(rrset);
return ret;
}
-
+
changes->old_rrsets[changes->old_rrsets_count++] = *rrset;
}
-
+
return KNOT_EOK;
}
@@ -1762,15 +1722,15 @@ static int xfrin_apply_remove_all_rrsets(knot_changes_t *changes,
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(knot_node_owner(node));
- dbg_xfrin_verb("Removing all RRSets from node %s of type %s. "
+ dbg_xfrin_verb("Removing all RRSets from node %s of type %u. "
"Is apex: %d, changeset flags: %u\n",
- name, knot_rrtype_to_string(type), is_apex, chflags);
+ name, type, is_apex, chflags);
free(name);
);
/*! \todo ref #937 is it OK to modify nodes at this point?
* shouldn't it be after the zones are switched? */
-
+
/* Assemble RRSets to remove. */
if (type == KNOT_RRTYPE_ANY) {
/* Remove all RRSets from the node. */
@@ -1798,14 +1758,14 @@ dbg_xfrin_exec_verb(
*/
if (is_apex && (chflags & KNOT_CHANGESET_TYPE_DDNS)) {
dbg_xfrin_detail("DDNS: returning SOA and NS to the "
- "node.\n");
+ "node.\n");
for (unsigned i = 0; i < rrsets_count; ++i) {
if (knot_rrset_type(rrsets[i])
== KNOT_RRTYPE_SOA
|| knot_rrset_type(rrsets[i])
== KNOT_RRTYPE_NS) {
dbg_xfrin_detail("Returning...\n");
- knot_node_add_rrset(node, rrsets[i], 0);
+ knot_node_add_rrset_no_merge(node, rrsets[i]);
rrsets[i] = NULL;
}
}
@@ -1830,7 +1790,7 @@ dbg_xfrin_exec_verb(
rrsets_count = 1;
}
}
-
+
ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
&changes->old_rrsets_count,
&changes->old_rrsets_allocated,
@@ -1840,7 +1800,7 @@ dbg_xfrin_exec_verb(
free(rrsets);
return ret;
}
-
+
/* Mark RRsets and RDATA for removal. */
for (unsigned i = 0; i < rrsets_count; ++i) {
if (rrsets[i] == NULL) {
@@ -1848,11 +1808,10 @@ dbg_xfrin_exec_verb(
}
changes->old_rrsets[changes->old_rrsets_count++] = rrsets[i];
-
+
/* Remove old RDATA. */
- int rdata_count = knot_rrset_rdata_rr_count(rrsets[i]);
+ int rdata_count = 1;//knot_rrset_rdata_rr_count(rrsets[i]);
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
changes->old_rdata_count,
&changes->old_rdata_allocated,
rdata_count);
@@ -1861,14 +1820,12 @@ dbg_xfrin_exec_verb(
free(rrsets);
return ret;
}
-
+
knot_changes_add_rdata(changes->old_rdata,
- changes->old_rdata_types,
&changes->old_rdata_count,
- knot_rrset_get_rdata(rrsets[i]),
- knot_rrset_type(rrsets[i]));
+ rrsets[i]);
}
-
+
free(rrsets);
return KNOT_EOK;
@@ -1880,7 +1837,7 @@ static knot_node_t *xfrin_add_new_node(knot_zone_contents_t *contents,
knot_rrset_t *rrset, int is_nsec3)
{
knot_node_t *node = knot_node_new(knot_rrset_get_owner(rrset),
- NULL, 0);
+ NULL, 0);
if (node == NULL) {
dbg_xfrin("Failed to create a new node.\n");
return NULL;
@@ -1891,10 +1848,9 @@ static knot_node_t *xfrin_add_new_node(knot_zone_contents_t *contents,
// insert the node into zone structures and create parents if
// necessary
if (is_nsec3) {
- ret = knot_zone_contents_add_nsec3_node(contents, node, 1, 0,
- 1);
+ ret = knot_zone_contents_add_nsec3_node(contents, node, 1, 0);
} else {
- ret = knot_zone_contents_add_node(contents, node, 1, 0, 1);
+ ret = knot_zone_contents_add_node(contents, node, 1, 0);
}
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new node to zone contents.\n");
@@ -1919,17 +1875,16 @@ int xfrin_replace_rrset_in_node(knot_node_t *node,
knot_changes_t *changes,
knot_zone_contents_t *contents)
{
- knot_rr_type_t type = knot_rrset_type(rrset_new);
+ uint16_t type = knot_rrset_type(rrset_new);
// remove RRSet of the proper type from the node
- dbg_xfrin_verb("Removing RRSet of type: %s.\n",
- knot_rrtype_to_string(type));
+ dbg_xfrin_verb("Removing RRSet of type: %u.\n", type);
knot_rrset_t *rrset_old = knot_node_remove_rrset(node, type);
assert(rrset_old != NULL);
// add the old RRSet to the list of old RRSets
int ret = knot_changes_rrsets_reserve(&changes->old_rrsets,
- &changes->old_rrsets_count,
- &changes->old_rrsets_allocated, 1);
+ &changes->old_rrsets_count,
+ &changes->old_rrsets_allocated, 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add old RRSet to list.\n");
return ret;
@@ -1937,11 +1892,10 @@ int xfrin_replace_rrset_in_node(knot_node_t *node,
// save also the RDATA, because RDATA are not deleted with the RRSet
// The count should be 1, but just to be sure....
- int count = knot_rrset_rdata_rr_count(rrset_old);
+ int count = 1;//knot_rrset_rdata_rr_count(rrset_old);
ret = knot_changes_rdata_reserve(&changes->old_rdata,
- &changes->old_rdata_types,
- changes->old_rdata_count,
- &changes->old_rdata_allocated, count);
+ changes->old_rdata_count,
+ &changes->old_rdata_allocated, count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add old RDATA to list.\n");
return ret;
@@ -1950,20 +1904,19 @@ int xfrin_replace_rrset_in_node(knot_node_t *node,
// save the new RRSet to the new RRSet, so that it is deleted if the
// apply fails
ret = knot_changes_rrsets_reserve(&changes->new_rrsets,
- &changes->new_rrsets_count,
- &changes->new_rrsets_allocated, 1);
+ &changes->new_rrsets_count,
+ &changes->new_rrsets_allocated, 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RRSet to list.\n");
return ret;
}
// The count should be 1, but just to be sure....
- count = knot_rrset_rdata_rr_count(rrset_new);
+ count = 1;//knot_rrset_rdata_rr_count(rrset_new);
// save the new RDATA
ret = knot_changes_rdata_reserve(&changes->new_rdata,
- &changes->new_rdata_types,
- changes->new_rdata_count,
- &changes->new_rdata_allocated, count);
+ changes->new_rdata_count,
+ &changes->new_rdata_allocated, count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RDATA to list.\n");
return ret;
@@ -1972,10 +1925,9 @@ int xfrin_replace_rrset_in_node(knot_node_t *node,
changes->old_rrsets[changes->old_rrsets_count++] = rrset_old;
dbg_xfrin_verb("Adding RDATA from old RRSet to the list of old RDATA."
- "\n");
- knot_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
- &changes->old_rdata_count,
- knot_rrset_get_rdata(rrset_old), type);
+ "\n");
+ knot_changes_add_rdata(changes->old_rdata, &changes->old_rdata_count,
+ rrset_old);
// store RRSIGs from the old RRSet to the new
knot_rrset_set_rrsigs(rrset_new, knot_rrset_get_rrsigs(rrset_old));
@@ -1983,7 +1935,7 @@ int xfrin_replace_rrset_in_node(knot_node_t *node,
// insert the new RRSet to the node
dbg_xfrin_verb("Adding new RRSet.\n");
ret = knot_zone_contents_add_rrset(contents, rrset_new, &node,
- KNOT_RRSET_DUPL_SKIP, 1);
+ KNOT_RRSET_DUPL_SKIP);
if (ret < 0) {
dbg_xfrin("Failed to add RRSet to node.\n");
@@ -1994,10 +1946,9 @@ int xfrin_replace_rrset_in_node(knot_node_t *node,
changes->new_rrsets[changes->new_rrsets_count++] = rrset_new;
dbg_xfrin_verb("Adding RDATA from new RRSet to the list of new RDATA."
- "\n");
- knot_changes_add_rdata(changes->new_rdata, changes->new_rdata_types,
- &changes->new_rdata_count,
- knot_rrset_get_rdata(rrset_new), type);
+ "\n");
+ knot_changes_add_rdata(changes->new_rdata, &changes->new_rdata_count,
+ rrset_new);
return KNOT_EOK;
}
@@ -2016,26 +1967,22 @@ static int xfrin_apply_add_normal_ddns(knot_changes_t *changes,
* serial is less than the current serial, ignore.
*/
if (knot_node_rrset(node, KNOT_RRTYPE_SOA) == NULL
- || ns_serial_compare(knot_rdata_soa_serial(
- knot_rrset_rdata(
- knot_node_rrset(node, KNOT_RRTYPE_SOA))),
- knot_rdata_soa_serial(knot_rrset_rdata(add)
- )) > 0
- ) {
+ || ns_serial_compare(knot_rrset_rdata_soa_serial(
+ knot_node_rrset(node, KNOT_RRTYPE_SOA)),
+ knot_rrset_rdata_soa_serial(add) > 0
+ )) {
dbg_ddns_verb("DDNS: Ignoring SOA.\n");
return KNOT_EOK;
} else {
dbg_ddns_verb("DDNS: replacing SOA (old serial: %u,"
- " new serial: %u.\n",
- knot_rdata_soa_serial(knot_rrset_rdata(
- knot_node_rrset(node,
- KNOT_RRTYPE_SOA))),
- knot_rdata_soa_serial(knot_rrset_rdata(
- add)));
+ " new serial: %u.\n",
+ knot_rrset_rdata_soa_serial(knot_node_rrset(node,
+ KNOT_RRTYPE_SOA)),
+ knot_rrset_rdata_soa_serial(add));
/* b) Otherwise, replace the current SOA. */
ret = xfrin_replace_rrset_in_node(node, add,
- changes,
- contents);
+ changes,
+ contents);
/* In this case we must however remove the ADD RRSet
* from the changeset, so that it is not deleted
* afterwards.
@@ -2052,7 +1999,7 @@ static int xfrin_apply_add_normal_ddns(knot_changes_t *changes,
dbg_ddns_verb("DDNS: replacing CNAME.\n");
/* a) ... to a CNAME node => replace. */
ret = xfrin_replace_rrset_in_node(node, add, changes,
- contents);
+ contents);
/* In this case we must however remove the ADD RRSet
* from the changeset, so that it is not deleted
* afterwards.
@@ -2098,7 +2045,7 @@ static int xfrin_apply_add_normal(knot_changes_t *changes,
dbg_xfrin_exec_detail(
dbg_xfrin_detail("applying rrset:\n");
- knot_rrset_dump(add, 0);
+ knot_rrset_dump(add);
);
/* DDNS special cases. */
@@ -2109,7 +2056,7 @@ dbg_xfrin_exec_detail(
return ret;
}
}
-
+
int copied = 0;
/*! \note Reusing RRSet from previous function caused it not to be
* removed from the node.
@@ -2119,7 +2066,7 @@ dbg_xfrin_exec_detail(
*/
if (*rrset
&& knot_dname_compare(knot_rrset_owner(*rrset),
- knot_node_owner(node)) == 0
+ knot_node_owner(node)) == 0
&& knot_rrset_type(*rrset) == knot_rrset_type(add)) {
dbg_xfrin_verb("Using RRSet from previous iteration.\n");
} else {
@@ -2136,22 +2083,21 @@ dbg_xfrin_exec_detail(
dbg_xfrin_detail("Copied RRSet: %p\n", *rrset);
dbg_xfrin_detail("Copied RRSet:\n");
- knot_rrset_dump(*rrset, 0);
+ knot_rrset_dump(*rrset);
copied = 1;
}
}
-
+
dbg_xfrin_exec_detail(
dbg_xfrin_detail("Removed RRSet: \n");
- knot_rrset_dump(*rrset, 1);
+ knot_rrset_dump(*rrset);
);
if (*rrset == NULL) {
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(add->owner);
dbg_xfrin_detail("RRSet to be added not found in zone.\n");
- dbg_xfrin_detail("owner: %s type: %s\n", name,
- knot_rrtype_to_string(add->type));
+ dbg_xfrin_detail("owner: %s type: %u\n", name, add->type);
free(name);
);
// add the RRSet from the changeset to the node
@@ -2165,7 +2111,7 @@ dbg_xfrin_exec_detail(
*/
// ret = knot_node_add_rrset(node, add, 0);
ret = knot_zone_contents_add_rrset(contents, add, &node,
- KNOT_RRSET_DUPL_SKIP, 1);
+ KNOT_RRSET_DUPL_SKIP);
if (ret < 0) {
dbg_xfrin("Failed to add RRSet to node.\n");
@@ -2179,8 +2125,8 @@ dbg_xfrin_exec_detail(
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
- dbg_xfrin_detail("Found RRSet with owner %s, type %s\n", name,
- knot_rrtype_to_string(knot_rrset_type(*rrset)));
+ dbg_xfrin_detail("Found RRSet with owner %s, type %u\n", name,
+ knot_rrset_type(*rrset));
free(name);
);
@@ -2196,33 +2142,34 @@ dbg_xfrin_exec_detail(
* TODO: add the 'add' rrset to list of old RRSets?
*/
- dbg_xfrin_detail("Merging RRSets with owners: %s, %s types: %s, %s\n",
- (*rrset)->owner->name, add->owner->name,
- knot_rrtype_to_string((*rrset)->type),
- knot_rrtype_to_string(add->type));
+ dbg_xfrin_detail("Merging RRSets with owners: %s, %s types: %u, %u\n",
+ (*rrset)->owner->name, add->owner->name,
+ (*rrset)->type,
+ add->type);
dbg_xfrin_detail("RDATA in RRSet1: %p, RDATA in RRSet2: %p\n",
- (*rrset)->rdata, add->rdata);
+ (*rrset)->rdata, add->rdata);
/* In case the RRSet is empty (and only remained there because of the
* RRSIGs) it may happen that the TTL may be different than that of
* the new RRs. Update the TTL according to the first RR.
*/
- if (knot_rrset_rdata(*rrset) == NULL
+ if (knot_rrset_rdata_rr_count(*rrset) == 0
&& knot_rrset_ttl(*rrset) != knot_rrset_ttl(add)) {
knot_rrset_set_ttl(*rrset, knot_rrset_ttl(add));
}
- ret = knot_rrset_merge_no_dupl((void **)rrset, (void **)&add);
+ int merged, deleted_rrs;
+ ret = knot_rrset_merge_no_dupl(*rrset, add, &merged, &deleted_rrs);
if (ret < 0) {
dbg_xfrin("Failed to merge changeset RRSet.\n");
return ret;
}
dbg_xfrin_detail("Merge returned: %d\n", ret);
- knot_rrset_dump(*rrset, 1);
+ knot_rrset_dump(*rrset);
if (copied) {
- ret = knot_node_add_rrset(node, *rrset, 0);
+ ret = knot_node_add_rrset_no_merge(node, *rrset);
if (ret < 0) {
dbg_xfrin("Failed to add merged RRSet to the node.\n");
@@ -2252,17 +2199,15 @@ static int xfrin_apply_add_rrsig(knot_changes_t *changes,
assert(rrset != NULL);
assert(knot_rrset_type(add) == KNOT_RRTYPE_RRSIG);
assert(contents != NULL);
-
+
int ret;
-
- knot_rr_type_t type = knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(add));
-
+
+ uint16_t type = knot_rrset_rdata_rrsig_type_covered(add);
+
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(add));
- const char *typestr = knot_rrtype_to_string(type);
- dbg_xfrin_verb("Adding RRSIG: Owner %s, type covered %s.\n",
- name, typestr);
+ dbg_xfrin_verb("Adding RRSIG: Owner %s, type covered %u.\n",
+ name, type);
free(name);
);
@@ -2273,7 +2218,7 @@ dbg_xfrin_exec_verb(
*/
if (*rrset
&& knot_dname_compare(knot_rrset_owner(*rrset),
- knot_node_owner(node)) == 0
+ knot_node_owner(node)) == 0
&& knot_rrset_type(*rrset) == type) {
dbg_xfrin_verb("Using RRSet from previous iteration.\n");
} else {
@@ -2286,16 +2231,16 @@ dbg_xfrin_exec_verb(
}
copied = 1;
dbg_xfrin_detail("Copied RRSet:\n");
- knot_rrset_dump(*rrset, 0);
+ knot_rrset_dump(*rrset);
}
if (*rrset == NULL) {
dbg_xfrin_detail("RRSet to be added not found in zone.\n");
-
+
// create a new RRSet to add the RRSIGs into
*rrset = knot_rrset_new(knot_node_get_owner(node), type,
- knot_rrset_class(add),
- knot_rrset_ttl(add));
+ knot_rrset_class(add),
+ knot_rrset_ttl(add));
if (*rrset == NULL) {
dbg_xfrin("Failed to create new RRSet for RRSIGs.\n");
return KNOT_ENOMEM;
@@ -2316,7 +2261,7 @@ dbg_xfrin_exec_verb(
// add the new RRSet to the node
// not needed to insert it through the zone_contents() function,
// as the owner is already in the dname table
- ret = knot_node_add_rrset(node, *rrset, 0);
+ ret = knot_node_add_rrset_no_merge(node, *rrset);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add RRSet to node.\n");
knot_rrset_free(rrset);
@@ -2328,8 +2273,8 @@ dbg_xfrin_exec_verb(
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
- dbg_xfrin_detail("Found RRSet with owner %s, type %s\n", name,
- knot_rrtype_to_string(knot_rrset_type(*rrset)));
+ dbg_xfrin_detail("Found RRSet with owner %s, type %u\n", name,
+ knot_rrset_type(*rrset));
free(name);
);
@@ -2337,21 +2282,24 @@ dbg_xfrin_exec_detail(
dbg_xfrin_detail("Adding new RRSIGs to RRSet.\n");
ret = knot_zone_contents_add_rrsigs(contents, add, rrset, &node,
- KNOT_RRSET_DUPL_SKIP, 1);
+ KNOT_RRSET_DUPL_SKIP);
if (ret < 0) {
dbg_xfrin("Failed to add RRSIGs to the RRSet.\n");
return KNOT_ERROR;
}
+ dbg_xfrin_detail("RRSet after added RRSIG:\n");
+ knot_rrset_dump(*rrset);
+
assert(ret == 0);
-
+
return 1;
} else {
knot_rrset_t *old = knot_rrset_get_rrsigs(*rrset);
assert(old != NULL);
knot_rrset_t *rrsig;
-
+
if (!copied) {
// check if the stored RRSIGs are not the right ones
if (*rrsigs_old && *rrsigs_old == old) {
@@ -2359,34 +2307,35 @@ dbg_xfrin_exec_detail(
rrsig = *rrsigs_old;
} else {
ret = xfrin_copy_old_rrset(old, &rrsig, changes,
- 1);
+ 1);
if (ret != KNOT_EOK) {
return ret;
}
dbg_xfrin_detail("Copied RRSIGs: %p\n", rrsig);
dbg_xfrin_detail("Copied RRSet:\n");
- knot_rrset_dump(rrsig, 0);
+ knot_rrset_dump(rrsig);
}
} else {
rrsig = old;
dbg_xfrin_verb("Using old RRSIGs: %p\n", rrsig);
}
-
+
// replace the old RRSIGs with the new ones
knot_rrset_set_rrsigs(*rrset, rrsig);
-
+
// merge the changeset RRSet to the copy
dbg_xfrin_detail("Merging RRSIG to the one in the RRSet.\n");
- ret = knot_rrset_merge_no_dupl((void **)&rrsig, (void **)&add);
- if (ret < 0) {
+ int merged, deleted_rrs;
+ ret = knot_rrset_merge_no_dupl(rrsig, add, &merged, &deleted_rrs);
+ if (ret != KNOT_EOK) {
dbg_xfrin("Failed to merge changeset RRSIG to copy: %s"
- ".\n", knot_strerror(ret));
+ ".\n", knot_strerror(ret));
return KNOT_ERROR;
}
-
+
return 2;
}
-
+
return KNOT_EOK;
}
@@ -2394,44 +2343,36 @@ dbg_xfrin_exec_detail(
void xfrin_cleanup_successful_update(knot_changes_t **changes)
{
-
for (int i = 0; i < (*changes)->old_rrsets_count; ++i) {
- dbg_xfrin_detail("Deleting old RRSet: %p\n",
- (*changes)->old_rrsets[i]);
- knot_rrset_dump((*changes)->old_rrsets[i], 0);
- knot_rrset_free(&(*changes)->old_rrsets[i]);
+ //TODO temporary fix!
+ if ((*changes)->old_rrsets[i] == NULL) {
+ log_server_warning("NULL RRSet to be freed in DDNS!\n");
+ continue;
+ }
+ if ((*changes)->old_rrsets[i]->rdata_count == 0) {
+dbg_xfrin_exec_detail(
+ char *name = knot_dname_to_str((*changes)->old_rrsets[i]->owner);
+ dbg_xfrin_detail("Deleting old RRSet: %s type %u\n",
+ name, (*changes)->old_rrsets[i]->type);
+ free(name);
+);
+ knot_rrset_free(&(*changes)->old_rrsets[i]);
+ }
}
// delete old RDATA
for (int i = 0; i < (*changes)->old_rdata_count; ++i) {
- dbg_xfrin_detail("Deleting old RDATA: %p, type: %s\n",
- (*changes)->old_rdata[i],
- knot_rrtype_to_string((*changes)->old_rdata_types[i]));
- knot_rdata_dump((*changes)->old_rdata[i],
- (*changes)->old_rdata_types[i], 0);
// RDATA are stored separately so do not delete the whole chain
- knot_rdata_deep_free(&(*changes)->old_rdata[i],
- (*changes)->old_rdata_types[i], 1);
-// knot_rdata_t *rdata = (*changes)->old_rdata[i];
-// if (rdata != NULL) {
-// do {
-// knot_rdata_t *tmp = rdata->next;
-// knot_rdata_deep_free(&rdata,
-// (*changes)->old_rdata_types[i], 1);
-// rdata = tmp;
-// } while (rdata != NULL
-// && rdata != (*changes)->old_rdata[i]);
-// }
-
+ knot_rrset_deep_free_no_sig(&(*changes)->old_rdata[i], 1, 1);
}
// free the empty nodes
for (int i = 0; i < (*changes)->old_nodes_count; ++i) {
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(
- knot_node_owner((*changes)->old_nodes[i]));
+ knot_node_owner((*changes)->old_nodes[i]));
dbg_xfrin_detail("Deleting old empty node: %p, owner: %s\n",
- (*changes)->old_nodes[i], name);
+ (*changes)->old_nodes[i], name);
free(name);
);
knot_node_free(&(*changes)->old_nodes[i]);
@@ -2441,9 +2382,9 @@ dbg_xfrin_exec_detail(
for (int i = 0; i < (*changes)->old_nsec3_count; ++i) {
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(
- knot_node_owner((*changes)->old_nsec3[i]));
+ knot_node_owner((*changes)->old_nsec3[i]));
dbg_xfrin_detail("Deleting old empty node: %p, owner: %s\n",
- (*changes)->old_nsec3[i], name);
+ (*changes)->old_nsec3[i], name);
free(name);
);
knot_node_free(&(*changes)->old_nsec3[i]);
@@ -2452,12 +2393,10 @@ dbg_xfrin_exec_detail(
// free allocated arrays of nodes and rrsets
free((*changes)->new_rrsets);
free((*changes)->new_rdata);
- free((*changes)->new_rdata_types);
free((*changes)->old_nodes);
free((*changes)->old_nsec3);
free((*changes)->old_rrsets);
free((*changes)->old_rdata);
- free((*changes)->old_rdata_types);
free((*changes));
*changes = NULL;
@@ -2479,50 +2418,6 @@ static void xfrin_switch_nodes_in_node(knot_node_t *node, void *data)
/*----------------------------------------------------------------------------*/
-static void xfrin_switch_node_in_hash_table(ck_hash_table_item_t *item,
- void *data)
-{
- UNUSED(data);
-
- if (item == NULL) {
- return;
- }
-
- knot_node_t *node = (knot_node_t *)item->value;
- knot_node_t *new_node = knot_node_get_new_node(node);
-
- assert(new_node != NULL);
-
- if (new_node != NULL) {
- item->value = new_node;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void xfrin_switch_node_in_dname_table(knot_dname_t *dname, void *data)
-{
- UNUSED(data);
-
-dbg_xfrin_exec_detail(
- char *name = knot_dname_to_str(dname);
- dbg_xfrin_detail("Switching node in dname %s (%p)\n", name, dname->node);
- free(name);
-);
- /* dname is not checked here (for NULL value), which resulted in crash
- * on howl recently. However, dname should not be NULL here at all,
- * it is a sign of some other error.
- */
-
- if (dname->node == NULL) {
- return;
- }
-
- knot_dname_update_node(dname);
-}
-
-/*----------------------------------------------------------------------------*/
-
static int xfrin_switch_nodes(knot_zone_contents_t *contents_copy)
{
assert(contents_copy != NULL);
@@ -2530,22 +2425,10 @@ static int xfrin_switch_nodes(knot_zone_contents_t *contents_copy)
// Traverse the trees and for each node check every reference
// stored in that node. The node itself should be new.
knot_zone_contents_tree_apply_inorder(contents_copy,
- xfrin_switch_nodes_in_node, NULL);
+ xfrin_switch_nodes_in_node, NULL);
knot_zone_contents_nsec3_apply_inorder(contents_copy,
- xfrin_switch_nodes_in_node, NULL);
-
- // Then traverse the hash table and change each pointer in hash table
- // item from old node to new node.
- int ret = ck_apply(knot_zone_contents_get_hash_table(contents_copy),
- xfrin_switch_node_in_hash_table, NULL);
- assert(ret == 0);
-
-// // Traverse also the dname table and change the node pointers in dnames
-// knot_zone_contents_dname_table_apply(contents_copy,
-// xfrin_switch_node_in_dname_table,
-// NULL);
-
+ xfrin_switch_nodes_in_node, NULL);
return KNOT_EOK;
}
@@ -2555,10 +2438,6 @@ static void xfrin_zone_contents_free2(knot_zone_contents_t **contents)
{
/*! \todo This should be all in some API!! */
- if ((*contents)->table != NULL) {
- ck_destroy_table(&(*contents)->table, NULL, 0);
- }
-
// free the zone tree, but only the structure
// (nodes are already destroyed)
dbg_zone("Destroying zone tree.\n");
@@ -2568,8 +2447,6 @@ static void xfrin_zone_contents_free2(knot_zone_contents_t **contents)
knot_nsec3_params_free(&(*contents)->nsec3_params);
- knot_dname_table_deep_free(&(*contents)->dname_table);
-
free(*contents);
*contents = NULL;
}
@@ -2604,11 +2481,11 @@ static void xfrin_cleanup_failed_update(knot_zone_contents_t *old_contents,
// also set pointers from dnames to old nodes
knot_zone_contents_tree_apply_inorder(old_contents,
xfrin_cleanup_old_nodes,
- NULL);
+ NULL);
knot_zone_contents_nsec3_apply_inorder(old_contents,
xfrin_cleanup_old_nodes,
- NULL);
+ NULL);
}
}
@@ -2626,12 +2503,14 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
// discard new RRSets
for (int i = 0; i < (*changes)->new_rrsets_count; ++i) {
//knot_rrset_deep_free(&changes->new_rrsets[i], 0, 1, 1);
- knot_rrset_free(&(*changes)->new_rrsets[i]);
+ if ((*changes)->new_rrsets[i]->rdata_count == 0) {
+ knot_rrset_free(&(*changes)->new_rrsets[i]);
+ }
}
for (int i = 0; i < (*changes)->new_rdata_count; ++i) {
dbg_xfrin_detail("Freeing %d. RDATA: %p\n", i,
- (*changes)->new_rdata[i]);
+ (*changes)->new_rdata[i]);
/*
* In some case, the same RDATA may be stored in
@@ -2651,19 +2530,16 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
* the first RDATA in each.
*/
- knot_rdata_deep_free(&(*changes)->new_rdata[i],
- (*changes)->new_rdata_types[i], 1);
+ knot_rrset_deep_free_no_sig(&(*changes)->new_rdata[i], 1, 1);
}
// free allocated arrays of nodes and rrsets
free((*changes)->new_rrsets);
free((*changes)->new_rdata);
- free((*changes)->new_rdata_types);
free((*changes)->old_nodes);
free((*changes)->old_nsec3);
free((*changes)->old_rrsets);
free((*changes)->old_rdata);
- free((*changes)->old_rdata_types);
free(*changes);
*changes = NULL;
@@ -2693,13 +2569,12 @@ static int xfrin_apply_remove(knot_zone_contents_t *contents,
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(
knot_rrset_owner(chset->remove[i]));
- dbg_xfrin_verb("Removing RRSet: %s, type %s\n", name,
- knot_rrtype_to_string(
- knot_rrset_type(chset->remove[i])));
+ dbg_xfrin_verb("Removing RRSet: %s, type %u\n", name,
+ knot_rrset_type(chset->remove[i]));
free(name);
);
dbg_xfrin_exec_detail(
- knot_rrset_dump(chset->remove[i], 0);
+ knot_rrset_dump(chset->remove[i]);
);
is_nsec3 = 0;
@@ -2707,9 +2582,8 @@ dbg_xfrin_exec_detail(
// check if the RRSet belongs to the NSEC3 tree
if ((knot_rrset_type(chset->remove[i]) == KNOT_RRTYPE_NSEC3)
|| (knot_rrset_type(chset->remove[i]) == KNOT_RRTYPE_RRSIG
- && knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(chset->remove[i]))
- == KNOT_RRTYPE_NSEC3))
+ && knot_rrset_rdata_rrsig_type_covered(chset->remove[i])
+ == KNOT_RRTYPE_NSEC3))
{
dbg_xfrin_verb("Removed RRSet belongs to NSEC3 tree.\n");
is_nsec3 = 1;
@@ -2720,18 +2594,18 @@ dbg_xfrin_exec_detail(
node, knot_rrset_owner(chset->remove[i]),
knot_node_owner(node));
if (!node || knot_rrset_owner(chset->remove[i])
- != knot_node_owner(node)) {
+ != knot_node_owner(node)) {
if (is_nsec3) {
node = knot_zone_contents_get_nsec3_node(
- contents,
- knot_rrset_owner(chset->remove[i]));
+ contents,
+ knot_rrset_owner(chset->remove[i]));
} else {
node = knot_zone_contents_get_node(contents,
- knot_rrset_owner(chset->remove[i]));
+ knot_rrset_owner(chset->remove[i]));
}
if (node == NULL) {
dbg_xfrin_verb("Node not found for RR to be "
- "removed!\n");
+ "removed!\n");
continue;
}
}
@@ -2746,17 +2620,17 @@ dbg_xfrin_exec_detail(
changes, node,
knot_rrset_type(chset->remove[i]), chset->flags);
} else if (knot_rrset_type(chset->remove[i])
- == KNOT_RRTYPE_RRSIG) {
+ == KNOT_RRTYPE_RRSIG) {
// this should work also for UPDATE
ret = xfrin_apply_remove_rrsigs(changes,
- chset->remove[i],
- node, &rrset, &rrsigs);
+ chset->remove[i],
+ node, &rrset, &rrsigs);
} else {
// this should work also for UPDATE
ret = xfrin_apply_remove_normal(changes,
- chset->remove[i],
- node, &rrset,
- chset->flags);
+ chset->remove[i],
+ node, &rrset,
+ chset->flags);
}
dbg_xfrin_detail("xfrin_apply_remove() ret = %d\n", ret);
@@ -2788,13 +2662,12 @@ static int xfrin_apply_add(knot_zone_contents_t *contents,
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(
knot_rrset_owner(chset->add[i]));
- dbg_xfrin_verb("Adding RRSet: %s, type: %s\n", name,
- knot_rrtype_to_string(
- knot_rrset_type(chset->add[i])));
+ dbg_xfrin_verb("Adding RRSet: %s, type: %u\n", name,
+ knot_rrset_type(chset->add[i]));
free(name);
);
dbg_xfrin_exec_detail(
- knot_rrset_dump(chset->add[i], 0);
+ knot_rrset_dump(chset->add[i]);
);
is_nsec3 = 0;
@@ -2802,9 +2675,8 @@ dbg_xfrin_exec_detail(
// check if the RRSet belongs to the NSEC3 tree
if ((knot_rrset_type(chset->add[i]) == KNOT_RRTYPE_NSEC3)
|| (knot_rrset_type(chset->add[i]) == KNOT_RRTYPE_RRSIG
- && knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(chset->add[i]))
- == KNOT_RRTYPE_NSEC3))
+ && knot_rrset_rdata_rrsig_type_covered(chset->add[i])
+ == KNOT_RRTYPE_NSEC3))
{
dbg_xfrin_detail("This is NSEC3-related RRSet.\n");
is_nsec3 = 1;
@@ -2816,23 +2688,23 @@ dbg_xfrin_exec_detail(
dbg_xfrin_detail("Searching for node...\n");
if (is_nsec3) {
node = knot_zone_contents_get_nsec3_node(
- contents,
- knot_rrset_owner(chset->add[i]));
+ contents,
+ knot_rrset_owner(chset->add[i]));
} else {
node = knot_zone_contents_get_node(contents,
- knot_rrset_owner(chset->add[i]));
+ knot_rrset_owner(chset->add[i]));
}
if (node == NULL) {
// create new node, connect it properly to the
// zone nodes
dbg_xfrin_detail("Node not found. Creating new."
- "\n");
+ "\n");
node = xfrin_add_new_node(contents,
- chset->add[i],
- is_nsec3);
+ chset->add[i],
+ is_nsec3);
if (node == NULL) {
dbg_xfrin("Failed to create new node "
- "in zone.\n");
+ "in zone.\n");
return KNOT_ERROR;
}
}
@@ -2842,13 +2714,13 @@ dbg_xfrin_exec_detail(
if (knot_rrset_type(chset->add[i]) == KNOT_RRTYPE_RRSIG) {
ret = xfrin_apply_add_rrsig(changes, chset->add[i],
- node, &rrset, &rrsigs,
- contents);
+ node, &rrset, &rrsigs,
+ contents);
assert(ret != KNOT_EOK);
} else {
ret = xfrin_apply_add_normal(changes, chset->add[i],
- node, &rrset, contents,
- chset->flags);
+ node, &rrset, contents,
+ chset->flags);
assert(ret <= 3);
}
@@ -2857,7 +2729,7 @@ dbg_xfrin_exec_detail(
//assert(ret != KNOT_EOK);
dbg_xfrin_detail("xfrin_apply_..() returned %d, rrset: %p\n",
- ret, rrset);
+ ret, rrset);
if (ret > 0) {
if (ret == 1) {
@@ -2870,7 +2742,7 @@ dbg_xfrin_exec_detail(
&changes->new_rrsets_allocated, 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add old RRSet to "
- "list.\n");
+ "list.\n");
return ret;
}
@@ -2878,13 +2750,11 @@ dbg_xfrin_exec_detail(
= chset->add[i];
// the same goes for the RDATA
- int count = knot_rrset_rdata_rr_count(
- chset->add[i]);
+ int count = 1;//knot_rrset_rdata_rr_count(chset->add[i]);
// connect the RDATA to the list of new RDATA
int res = knot_changes_rdata_reserve(
&changes->new_rdata,
- &changes->new_rdata_types,
changes->new_rdata_count,
&changes->new_rdata_allocated, count);
if (res != KNOT_EOK) {
@@ -2892,18 +2762,16 @@ dbg_xfrin_exec_detail(
}
knot_changes_add_rdata(changes->new_rdata,
- changes->new_rdata_types,
- &changes->new_rdata_count,
- knot_rrset_get_rdata(chset->add[i]),
- knot_rrset_type(chset->add[i]));
+ &changes->new_rdata_count,
+ chset->add[i]);
chset->add[i] = NULL;
} else if (ret == 2) {
// the copy of the RRSet was used, but it was
// already stored in the new RRSets list
// just delete the add RRSet, but without RDATA
- // as these were merged to the copied RRSet
- knot_rrset_free(&chset->add[i]);
+ // DNAMES as these were merged to the copied RRSet
+ knot_rrset_deep_free(&chset->add[i], 1, 0);
// In this case, the RDATA does not have to be
// stored in the list of new RDATA, because
@@ -2940,7 +2808,7 @@ static int xfrin_apply_replace_soa(knot_zone_contents_t *contents,
int ret = xfrin_replace_rrset_in_node(node, chset->soa_to, changes,
- contents);
+ contents);
if (ret == KNOT_EOK) {
// remove the SOA from the changeset, so it will not be deleted
// after successful apply
@@ -2963,14 +2831,14 @@ static int xfrin_apply_changeset(knot_zone_contents_t *contents,
*/
dbg_xfrin("APPLYING CHANGESET: from serial %u to serial %u\n",
- chset->serial_from, chset->serial_to);
+ chset->serial_from, chset->serial_to);
// check if serial matches
/*! \todo Only if SOA is present? */
const knot_rrset_t *soa = knot_node_rrset(contents->apex,
- KNOT_RRTYPE_SOA);
- if (soa == NULL || knot_rdata_soa_serial(knot_rrset_rdata(soa))
- != chset->serial_from) {
+ KNOT_RRTYPE_SOA);
+ if (soa == NULL || knot_rrset_rdata_soa_serial(soa)
+ != chset->serial_from) {
dbg_xfrin("SOA serials do not match!!\n");
return KNOT_ERROR;
}
@@ -3000,8 +2868,8 @@ static void xfrin_mark_empty(knot_node_t *node, void *data)
if (knot_node_rrset_count(node) == 0
&& knot_node_children(node) == 0) {
int ret = knot_changes_nodes_reserve(&changes->old_nodes,
- &changes->old_nodes_count,
- &changes->old_nodes_allocated);
+ &changes->old_nodes_count,
+ &changes->old_nodes_allocated);
if (ret != KNOT_EOK) {
/*! \todo Stop on error? */
return;
@@ -3020,6 +2888,8 @@ static void xfrin_mark_empty(knot_node_t *node, void *data)
node->parent = NULL;
}
}
+ dbg_xfrin_detail("Space for nodes reserved, old node count = %d\n",
+ changes->old_nodes_count);
}
/*----------------------------------------------------------------------------*/
@@ -3034,8 +2904,8 @@ static void xfrin_mark_empty_nsec3(knot_node_t *node, void *data)
if (knot_node_rrset_count(node) == 0
&& knot_node_children(node) == 0) {
int ret = knot_changes_nodes_reserve(&changes->old_nsec3,
- &changes->old_nsec3_count,
- &changes->old_nsec3_allocated);
+ &changes->old_nsec3_count,
+ &changes->old_nsec3_allocated);
if (ret != KNOT_EOK) {
/*! \todo Stop on error? */
return;
@@ -3069,47 +2939,53 @@ static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
dbg_xfrin_verb("OLD NSEC3 NODES COUNT: %d\n", changes->old_nsec3_count);
// walk through the zone and select nodes to be removed
+ /* \note This function doesn't require order, but requires to be applied
+ * on the leaves first and then on the their parent.
+ */
ret = knot_zone_contents_tree_apply_inorder_reverse(contents,
- xfrin_mark_empty,
- (void *)changes);
+ xfrin_mark_empty,
+ (void *)changes);
assert(ret == KNOT_EOK);
// Do the same with NSEC3 nodes.
ret = knot_zone_contents_nsec3_apply_inorder_reverse(contents,
- xfrin_mark_empty_nsec3,
- (void *)changes);
+ xfrin_mark_empty_nsec3,
+ (void *)changes);
assert(ret == KNOT_EOK);
dbg_xfrin_verb("OLD NODES COUNT: %d\n", changes->old_nodes_count);
dbg_xfrin_verb("OLD NSEC3 NODES COUNT: %d\n", changes->old_nsec3_count);
// remove these nodes from both hash table and the tree
- ck_hash_table_item_t *hash_item = NULL;
- knot_zone_tree_node_t *zone_node = NULL;
+ knot_node_t *zone_node = NULL;
for (int i = 0; i < changes->old_nodes_count; ++i) {
zone_node = NULL;
- hash_item = NULL;
dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_node_owner(
- changes->old_nodes[i]));
+ changes->old_nodes[i]));
dbg_xfrin_detail("Old node #%d: %p, %s\n", i,
- changes->old_nodes[i], name);
+ changes->old_nodes[i], name);
free(name);
);
ret = knot_zone_contents_remove_node(
- contents, changes->old_nodes[i], &zone_node,
- &hash_item);
-
- if (ret != KNOT_EOK) {
+ contents, changes->old_nodes[i], &zone_node);
+
+ if (ret == KNOT_ENONODE) {
+ assert(knot_node_rrset_count(changes->old_nodes[i]) == 1);
+ assert(knot_node_rrset(changes->old_nodes[i],
+ KNOT_RRTYPE_RRSIG));
+ char *name = knot_dname_to_str(changes->old_nodes[i]->owner);
+ log_zone_warning("Ignoring extra RRSIG for %s!\n",
+ name);
+ free(name);
+ } else if (ret != KNOT_EOK) {
dbg_xfrin("Failed to remove node from zone!\n");
- return KNOT_ENONODE;
+ return ret;
}
-
- free(hash_item);
- free(zone_node);
+ assert(changes->old_nodes[i] == zone_node);
}
// remove NSEC3 nodes
@@ -3117,9 +2993,9 @@ dbg_xfrin_exec_detail(
zone_node = NULL;
char *name = knot_dname_to_str(knot_node_owner(
- changes->old_nsec3[i]));
+ changes->old_nsec3[i]));
dbg_xfrin_detail("Old NSEC3 node #%d: %p, %s\n", i,
- changes->old_nsec3[i], name);
+ changes->old_nsec3[i], name);
free(name);
ret = knot_zone_contents_remove_nsec3_node(
@@ -3129,8 +3005,7 @@ dbg_xfrin_exec_detail(
dbg_xfrin("Failed to remove NSEC3 node from zone!\n");
return KNOT_ENONODE;
}
-
- free(zone_node);
+ assert(changes->old_nsec3[i] == zone_node);
}
return KNOT_EOK;
@@ -3161,15 +3036,15 @@ static int xfrin_check_contents_copy(knot_zone_contents_t *old_contents)
int err = KNOT_EOK;
int ret = knot_zone_contents_tree_apply_inorder(old_contents,
- xfrin_check_contents_copy_node,
- &err);
+ xfrin_check_contents_copy_node,
+ &err);
assert(ret == KNOT_EOK);
if (err == KNOT_EOK) {
ret = knot_zone_contents_nsec3_apply_inorder(old_contents,
- xfrin_check_contents_copy_node,
- &err);
+ xfrin_check_contents_copy_node,
+ &err);
}
assert(ret == KNOT_EOK);
@@ -3200,7 +3075,7 @@ int xfrin_prepare_zone_copy(knot_zone_contents_t *old_contents,
// this would mean that a previous update was not completed
// abort
dbg_zone("Trying to apply changesets to zone that is "
- "being updated. Aborting.\n");
+ "being updated. Aborting.\n");
return KNOT_EAGAIN;
}
@@ -3216,15 +3091,15 @@ int xfrin_prepare_zone_copy(knot_zone_contents_t *old_contents,
dbg_xfrin("Copying zone contents.\n");
int ret = knot_zone_contents_shallow_copy2(old_contents,
- &contents_copy);
+ &contents_copy);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to create shallow copy of zone: %s\n",
- knot_strerror(ret));
+ knot_strerror(ret));
return ret;
}
knot_changes_t *chgs = (knot_changes_t *)malloc(
- sizeof(knot_changes_t));
+ sizeof(knot_changes_t));
if (chgs == NULL) {
dbg_xfrin("Failed to allocate structure for changes!\n");
xfrin_rollback_update(old_contents, &contents_copy, &chgs);
@@ -3243,7 +3118,7 @@ int xfrin_prepare_zone_copy(knot_zone_contents_t *old_contents,
return ret;
}
- assert(knot_zone_contents_apex(contents_copy) != NULL);
+ assert(knot_zone_contents_apex(contents_copy) != NULL);
/*
* Fix references to new nodes. Some references in new nodes may point
@@ -3252,29 +3127,29 @@ int xfrin_prepare_zone_copy(knot_zone_contents_t *old_contents,
dbg_xfrin("Switching ptrs pointing to old nodes to the new nodes.\n");
ret = xfrin_switch_nodes(contents_copy);
assert(knot_zone_contents_apex(contents_copy) != NULL);
-
+
*new_contents = contents_copy;
*changes = chgs;
-
+
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
int xfrin_finalize_updated_zone(knot_zone_contents_t *contents_copy,
- knot_changes_t *changes,
- knot_zone_contents_t *old_contents)
+ knot_changes_t *changes)
{
- if (contents_copy == NULL || changes == NULL || old_contents == NULL) {
+ if (contents_copy == NULL || changes == NULL) {
return KNOT_EINVAL;
}
-
+
/*
* Finalize the new zone contents:
* - delete empty nodes
* - parse NSEC3PARAM
* - do adjusting of nodes and RDATA
* - ???
+ * - PROFIT
*/
/*
@@ -3284,31 +3159,19 @@ int xfrin_finalize_updated_zone(knot_zone_contents_t *contents_copy,
int ret = xfrin_remove_empty_nodes(contents_copy, changes);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to remove empty nodes: %s\n",
- knot_strerror(ret));
-// xfrin_rollback_update(old_contents, &contents_copy, &changes);
+ knot_strerror(ret));
return ret;
}
dbg_xfrin("Adjusting zone contents.\n");
- dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
- old_contents->apex, contents_copy->apex);
- ret = knot_zone_contents_adjust(contents_copy);
+ ret = knot_zone_contents_adjust(contents_copy, NULL, NULL, 1);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to finalize zone contents: %s\n",
- knot_strerror(ret));
-// xfrin_rollback_update(old_contents, &contents_copy, &changes);
+ knot_strerror(ret));
return ret;
}
assert(knot_zone_contents_apex(contents_copy) != NULL);
- dbg_xfrin("Checking zone for CNAME loops.\n");
- ret = knot_zone_contents_check_loops(contents_copy);
- if (ret != KNOT_EOK) {
- dbg_xfrin("CNAME loop check failed: %s\n", knot_strerror(ret));
-// xfrin_rollback_update(old_contents, &contents_copy, &changes);
- return ret;
- }
-
return KNOT_EOK;
}
@@ -3335,10 +3198,10 @@ int xfrin_apply_changesets(knot_zone_t *zone,
knot_zone_contents_t *contents_copy = NULL;
knot_changes_t *changes = NULL;
int ret = xfrin_prepare_zone_copy(old_contents, &contents_copy,
- &changes);
+ &changes);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to prepare zone copy: %s\n",
- knot_strerror(ret));
+ knot_strerror(ret));
return ret;
}
@@ -3347,15 +3210,15 @@ int xfrin_apply_changesets(knot_zone_t *zone,
*/
dbg_xfrin("Applying changesets.\n");
dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
- old_contents->apex, contents_copy->apex);
+ old_contents->apex, contents_copy->apex);
for (int i = 0; i < chsets->count; ++i) {
if ((ret = xfrin_apply_changeset(contents_copy, changes,
- &chsets->sets[i]))
- != KNOT_EOK) {
+ &chsets->sets[i]))
+ != KNOT_EOK) {
xfrin_rollback_update(old_contents,
- &contents_copy, &changes);
+ &contents_copy, &changes);
dbg_xfrin("Failed to apply changesets to zone: "
- "%s\n", knot_strerror(ret));
+ "%s\n", knot_strerror(ret));
return ret;
}
}
@@ -3366,10 +3229,10 @@ int xfrin_apply_changesets(knot_zone_t *zone,
*/
dbg_xfrin_verb("Finalizing updated zone...\n");
- ret = xfrin_finalize_updated_zone(contents_copy, changes, old_contents);
+ ret = xfrin_finalize_updated_zone(contents_copy, changes);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to finalize updated zone: %s\n",
- knot_strerror(ret));
+ knot_strerror(ret));
xfrin_rollback_update(old_contents, &contents_copy, &changes);
return ret;
}
@@ -3382,6 +3245,56 @@ int xfrin_apply_changesets(knot_zone_t *zone,
/*----------------------------------------------------------------------------*/
+static int xfrin_switch_node_in_rdata(knot_dname_t **dname, void *data)
+{
+ UNUSED(data);
+ if (dname == NULL || *dname == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ if ((*dname)->node != NULL) {
+ knot_dname_update_node(*dname);
+ }
+
+ return KNOT_EOK;
+}
+
+static void xfrin_switch_node_in_rrset(knot_rrset_t *rrset)
+{
+ if (rrset == NULL) {
+ return;
+ }
+
+ if (rrset->rrsigs) {
+ xfrin_switch_node_in_rrset(rrset->rrsigs);
+ }
+
+ if (rrset->owner->node != NULL) {
+ knot_dname_update_node(rrset->owner);
+ }
+
+ rrset_dnames_apply(rrset, xfrin_switch_node_in_rdata, NULL);
+}
+
+static void xfrin_switch_node_in_node(knot_node_t **node, void *data)
+{
+ UNUSED(data);
+ if (node == NULL || *node == NULL) {
+ return;
+ }
+
+ if ((*node)->owner->node != NULL) {
+ knot_dname_update_node((*node)->owner);
+ }
+
+ knot_rrset_t **rr_array = knot_node_get_rrsets_no_copy(*node);
+ for (uint16_t i = 0; i < (*node)->rrset_count; ++i) {
+ xfrin_switch_node_in_rrset(rr_array[i]);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+
int xfrin_switch_zone(knot_zone_t *zone,
knot_zone_contents_t *new_contents,
int transfer_type)
@@ -3392,22 +3305,23 @@ int xfrin_switch_zone(knot_zone_t *zone,
dbg_xfrin("Switching zone contents.\n");
dbg_xfrin_verb("Old contents: %p, apex: %p, new apex: %p\n",
- zone->contents, (zone->contents)
- ? zone->contents->apex : NULL, new_contents->apex);
+ zone->contents, (zone->contents)
+ ? zone->contents->apex : NULL, new_contents->apex);
knot_zone_contents_t *old =
knot_zone_switch_contents(zone, new_contents);
dbg_xfrin_verb("Old contents: %p, apex: %p, new apex: %p\n",
- old, (old) ? old->apex : NULL, new_contents->apex);
+ old, (old) ? old->apex : NULL, new_contents->apex);
// switch pointers in domain names, now only the new zone is used
if (transfer_type == XFR_TYPE_IIN || transfer_type == XFR_TYPE_UPDATE) {
- // Traverse also the dname table and change the node pointers
- // in dnames
- int ret = knot_zone_contents_dname_table_apply(
- new_contents,
- xfrin_switch_node_in_dname_table, NULL);
+ /* Switch node references in owner DNAMEs and RDATA dnames. */
+ int ret = knot_zone_tree_apply(new_contents->nodes,
+ xfrin_switch_node_in_node, NULL);
+ assert(ret == KNOT_EOK);
+ ret = knot_zone_tree_apply(new_contents->nsec3_nodes,
+ xfrin_switch_node_in_node, NULL);
assert(ret == KNOT_EOK);
}
@@ -3422,7 +3336,7 @@ int xfrin_switch_zone(knot_zone_t *zone,
dbg_xfrin_verb("Freeing old zone: %p\n", old);
if (transfer_type == XFR_TYPE_AIN) {
- knot_zone_contents_deep_free(&old, 0);
+ knot_zone_contents_deep_free(&old);
} else {
assert(old != NULL);
xfrin_zone_contents_free(&old);
diff --git a/src/libknot/updates/xfr-in.h b/src/libknot/updates/xfr-in.h
index c65e708..54a22c5 100644
--- a/src/libknot/updates/xfr-in.h
+++ b/src/libknot/updates/xfr-in.h
@@ -93,7 +93,7 @@ int xfrin_transfer_needed(const knot_zone_contents_t *zone,
* pointer to the buffer for wireformat and TSIG data.
* \param size In: available space in the buffer. Out: actual size of the
* message in bytes.
- * \param use_tsig If TSIG should be used.
+ * \param use_tsig If TSIG should be used.
*
* \todo Parameter use_tsig probably not needed.
*
@@ -111,7 +111,7 @@ int xfrin_create_axfr_query(knot_dname_t *owner, knot_ns_xfr_t *xfr,
* \param buffer Buffer to fill the message in.
* \param size In: available space in the buffer. Out: actual size of the
* message in bytes.
- * \param use_tsig If TSIG should be used.
+ * \param use_tsig If TSIG should be used.
*
* \todo Parameter use_tsig probably not needed.
*
@@ -119,7 +119,7 @@ int xfrin_create_axfr_query(knot_dname_t *owner, knot_ns_xfr_t *xfr,
* \retval KNOT_ESPACE
* \retval KNOT_ERROR
*/
-int xfrin_create_ixfr_query(const knot_zone_contents_t *zone,
+int xfrin_create_ixfr_query(const knot_zone_contents_t *zone,
knot_ns_xfr_t *xfr, size_t *size, int use_tsig);
/*!
@@ -178,7 +178,7 @@ void xfrin_free_changesets(knot_changesets_t **changesets);
int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr/*const uint8_t *pkt, size_t size,
knot_changesets_t **changesets*/);
-int xfrin_apply_changesets_to_zone(knot_zone_t *zone,
+int xfrin_apply_changesets_to_zone(knot_zone_t *zone,
knot_changesets_t *chsets);
int xfrin_apply_changesets(knot_zone_t *zone,
@@ -190,8 +190,7 @@ int xfrin_prepare_zone_copy(knot_zone_contents_t *old_contents,
knot_changes_t **changes);
int xfrin_finalize_updated_zone(knot_zone_contents_t *contents_copy,
- knot_changes_t *changes,
- knot_zone_contents_t *old_contents);
+ knot_changes_t *changes);
int xfrin_switch_zone(knot_zone_t *zone,
knot_zone_contents_t *new_contents,
@@ -203,8 +202,8 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
knot_zone_contents_t **new_contents,
knot_changes_t **changes);
-int xfrin_copy_rrset(knot_node_t *node, knot_rr_type_t type,
- knot_rrset_t **rrset, knot_changes_t *changes,
+int xfrin_copy_rrset(knot_node_t *node, uint16_t type,
+ knot_rrset_t **rrset, knot_changes_t *changes,
int save_new);
int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
diff --git a/src/libknot/util/debug.c b/src/libknot/util/debug.c
index a6555ad..9f8d852 100644
--- a/src/libknot/util/debug.c
+++ b/src/libknot/util/debug.c
@@ -22,123 +22,39 @@
#include "util/utils.h"
#include "util/debug.h"
+#include "libknot/rrset.h"
+#include "common/descriptor.h"
#include "common/print.h"
-void knot_rdata_dump(knot_rdata_t *rdata, uint32_t type, char loaded_zone)
+#if defined(KNOT_ZONE_DEBUG)
+static void knot_node_dump_from_tree(knot_node_t *node, void *data)
{
-#if defined(KNOT_ZONE_DEBUG) || defined(KNOT_RDATA_DEBUG)
- fprintf(stderr, " ------- RDATA -------\n");
- if (rdata == NULL) {
- fprintf(stderr, " There are no rdata in this RRset!\n");
- fprintf(stderr, " ------- RDATA -------\n");
- return;
- }
- knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(type);
- assert(desc != NULL);
- char *name;
-
- for (int i = 0; i < rdata->count; i++) {
- if (rdata->items[i].raw_data == NULL) {
- continue;
- }
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ) {
- assert(rdata->items[i].dname != NULL);
- name = knot_dname_to_str(rdata->items[i].dname);
- fprintf(stderr, " DNAME: %d: %s (%p)\n",
- i, name, rdata->items[i].dname);
- free(name);
- if (loaded_zone) {
- if (rdata->items[i].dname->node) {
- name =
- knot_dname_to_str(rdata->items[i].dname->node->owner);
- fprintf(stderr, " Has node owner: %s\n", name);
- free(name);
- } else {
- fprintf(stderr, " No node set\n");
- }
- }
- fprintf(stderr, " labels: ");
- hex_print((char *)rdata->items[i].dname->labels,
- rdata->items[i].dname->label_count);
-
- } else {
- assert(rdata->items[i].raw_data != NULL);
- fprintf(stderr, " %d: raw_data: length: %d\n", i,
- *(rdata->items[i].raw_data));
- fprintf(stderr, " ");
- hex_print(((char *)(
- rdata->items[i].raw_data + 1)),
- rdata->items[i].raw_data[0]);
- }
- }
- fprintf(stderr, " ------- RDATA -------\n");
-#endif
+ UNUSED(data);
+ knot_node_dump(node);
}
-
-void knot_rrset_dump(const knot_rrset_t *rrset, char loaded_zone)
-{
-#if defined(KNOT_ZONE_DEBUG) || defined(KNOT_RRSET_DEBUG)
- fprintf(stderr, " ------- RRSET -------\n");
- fprintf(stderr, " %p\n", rrset);
- if (!rrset) {
- return;
- }
- char *name = knot_dname_to_str(rrset->owner);
- fprintf(stderr, " owner: %s\n", name);
- free(name);
- fprintf(stderr, " type: %s\n", knot_rrtype_to_string(rrset->type));
- fprintf(stderr, " class: %d\n", rrset->rclass);
- fprintf(stderr, " ttl: %d\n", rrset->ttl);
-
- fprintf(stderr, " RRSIGs:\n");
- if (rrset->rrsigs != NULL) {
- knot_rrset_dump(rrset->rrsigs, loaded_zone);
- } else {
- fprintf(stderr, " none\n");
- }
-
- if (rrset->rdata == NULL) {
- fprintf(stderr, " NO RDATA!\n");
- fprintf(stderr, " ------- RRSET -------\n");
- return;
- }
-
- knot_rdata_t *tmp = rrset->rdata;
-
- while (tmp->next != rrset->rdata && tmp->next != NULL) {
- knot_rdata_dump(tmp, rrset->type, loaded_zone);
- tmp = tmp->next;
- }
-
- knot_rdata_dump(tmp, rrset->type, loaded_zone);
-
- fprintf(stderr, " ------- RRSET -------\n");
#endif
-}
-void knot_node_dump(knot_node_t *node, void *loaded_zone)
+void knot_node_dump(knot_node_t *node)
{
#if defined(KNOT_ZONE_DEBUG) || defined(KNOT_NODE_DEBUG)
//char loaded_zone = *((char*) data);
char *name;
- fprintf(stderr, "------- NODE --------\n");
+ dbg_node_detail("------- NODE --------\n");
name = knot_dname_to_str(node->owner);
- fprintf(stderr, "owner: %s\n", name);
+ dbg_node_detail("owner: %s\n", name);
free(name);
- fprintf(stderr, "labels: ");
- hex_print((char *)node->owner->labels, node->owner->label_count);
- fprintf(stderr, "node: %p\n", node);
- fprintf(stderr, "node (in node's owner): %p\n", node->owner->node);
+ dbg_node_detail("labels: ");
+ hex_print(node->owner->labels, node->owner->label_count);
+ dbg_node_detail("node: %p\n", node);
+ dbg_node_detail("node (in node's owner): %p\n", node->owner->node);
if (knot_node_is_deleg_point(node)) {
- fprintf(stderr, "delegation point\n");
+ dbg_node_detail("delegation point\n");
}
if (knot_node_is_non_auth(node)) {
- fprintf(stderr, "non-authoritative node\n");
+ dbg_node_detail("non-authoritative node\n");
}
if (node->parent != NULL) {
@@ -146,83 +62,89 @@ void knot_node_dump(knot_node_t *node, void *loaded_zone)
* e.g. when applying changesets.
*/
name = knot_dname_to_str(node->parent->owner);
- fprintf(stderr, "parent: %s\n", name);
+ dbg_node_detail("parent: %s\n", name);
free(name);
} else {
- fprintf(stderr, "no parent\n");
+ dbg_node_detail("no parent\n");
}
if (node->prev != NULL) {
- fprintf(stderr, "previous node: %p\n", node->prev);
+ dbg_node_detail("previous node: %p\n", node->prev);
/*! \todo This causes segfault when prev was free'd,
* e.g. when applying changesets.
*/
name = knot_dname_to_str(node->prev->owner);
- fprintf(stderr, "previous node: %s\n", name);
+ dbg_node_detail("previous node: %s\n", name);
free(name);
} else {
- fprintf(stderr, "previous node: none\n");
+ dbg_node_detail("previous node: none\n");
}
knot_rrset_t **rrsets = knot_node_get_rrsets(node);
- fprintf(stderr, "Wildcard child: ");
+ dbg_node_detail("Wildcard child: ");
if (node->wildcard_child != NULL) {
/*! \todo This causes segfault when wildcard child was free'd,
* e.g. when applying changesets.
*/
name = knot_dname_to_str(node->wildcard_child->owner);
- fprintf(stderr, "%s\n", name);
+ dbg_node_detail("%s\n", name);
free(name);
} else {
- fprintf(stderr, "none\n");
+ dbg_node_detail("none\n");
}
- fprintf(stderr, "NSEC3 node: ");
+ dbg_node_detail("NSEC3 node: ");
if (node->nsec3_node != NULL) {
- /*! \todo This causes segfault when nsec3_node was free'd,
+ /*! \todo This causes segfault when n sec3_node was free'd,
* e.g. when applying changesets.
*/
name = knot_dname_to_str(node->nsec3_node->owner);
- fprintf(stderr, "%s\n", name);
+ dbg_node_detail("%s\n", name);
free(name);
} else {
- fprintf(stderr, "none\n");
+ dbg_node_detail("none\n");
}
-
- fprintf(stderr, "Zone: %p\n", node->zone);
- fprintf(stderr, "RRSet count: %d\n", node->rrset_count);
+ dbg_node_detail("Zone: %p\n", node->zone);
+
+ dbg_node_detail("RRSet count: %d\n", node->rrset_count);
for (int i = 0; i < node->rrset_count; i++) {
- knot_rrset_dump(rrsets[i], (int) loaded_zone);
+ knot_rrset_dump(rrsets[i]);
}
free(rrsets);
//assert(node->owner->node == node);
- fprintf(stderr, "------- NODE --------\n");
+ dbg_node_detail("------- NODE --------\n");
+#else
+ UNUSED(node);
#endif
}
-void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone)
+void knot_zone_contents_dump(knot_zone_contents_t *zone)
{
#if defined(KNOT_ZONE_DEBUG)
if (!zone) {
- fprintf(stderr, "------- STUB ZONE --------\n");
+ dbg_zone_detail("------- STUB ZONE --------\n");
return;
}
- fprintf(stderr, "------- ZONE --------\n");
+ dbg_zone_detail("------- ZONE --------\n");
+
+ knot_zone_contents_tree_apply_inorder(zone, knot_node_dump_from_tree,
+ NULL);
- knot_zone_contents_tree_apply_inorder(zone, knot_node_dump, (void *)&loaded_zone);
+ dbg_zone_detail("------- ZONE --------\n");
- fprintf(stderr, "------- ZONE --------\n");
-
- fprintf(stderr, "------- NSEC 3 tree -\n");
+ dbg_zone_detail("------- NSEC 3 tree -\n");
- knot_zone_contents_nsec3_apply_inorder(zone, knot_node_dump, (void *)&loaded_zone);
+ knot_zone_contents_nsec3_apply_inorder(zone, knot_node_dump_from_tree,
+ NULL);
- fprintf(stderr, "------- NSEC 3 tree -\n");
+ dbg_zone_detail("------- NSEC 3 tree -\n");
+#else
+ UNUSED(zone);
#endif
}
diff --git a/src/libknot/util/debug.h b/src/libknot/util/debug.h
index abe335b..826260a 100644
--- a/src/libknot/util/debug.h
+++ b/src/libknot/util/debug.h
@@ -1,5 +1,5 @@
/*!
- * \file debug.h
+ * \file libknot/util/debug.h
*
* \author Jan Kadlec <jan.kadlec.@nic.cz>
* \author Lubos Slovak <lubos.slovak@nic.cz>
@@ -32,7 +32,6 @@
#include <stdint.h>
#include <stdio.h>
-#include "config.h" /* autoconf generated */
#include "common/log.h"
/*
@@ -74,7 +73,6 @@
/* KNOT_DNAME_DEBUG -- in configure.ac */
/* #define KNOT_DDNS_DEBUG -- \todo Use this or delete. */
-#include "rdata.h"
#include "rrset.h"
#include "zone/node.h"
#include "zone/zone.h"
@@ -82,19 +80,6 @@
#include "common/print.h"
/*!
- * \brief Dumps RDATA of the given type.
- *
- * This function is empty if neither KNOT_ZONE_DEBUG nor KNOT_RDATA_DEBUG
- * is defined.
- *
- * \param rdata RDATA to dump.
- * \param type Type of the RDATA (needed to properly parse the RDATA).
- * \param loaded_zone Set to <> 0 if the RDATA is part of a zone loaded into
- * the server. Set to 0 otherwise.
- */
-void knot_rdata_dump(knot_rdata_t *rdata, uint32_t type, char loaded_zone);
-
-/*!
* \brief Dumps RRSet.
*
* This function is empty if neither KNOT_ZONE_DEBUG nor KNOT_RRSET_DEBUG
@@ -104,7 +89,7 @@ void knot_rdata_dump(knot_rdata_t *rdata, uint32_t type, char loaded_zone);
* \param loaded_zone Set to <> 0 if the RRSet is part of a zone loaded into
* the server. Set to 0 otherwise.
*/
-void knot_rrset_dump(const knot_rrset_t *rrset, char loaded_zone);
+void knot_rrset_dump(const knot_rrset_t *rrset);
/*!
* \brief Dumps zone node.
@@ -116,7 +101,7 @@ void knot_rrset_dump(const knot_rrset_t *rrset, char loaded_zone);
* \param loaded_zone Set to <> 0 if the node is part of a zone loaded into
* the server. Set to 0 otherwise.
*/
-void knot_node_dump(knot_node_t *node, void *loaded_zone);
+void knot_node_dump(knot_node_t *node);
/*!
* \brief Dumps the whole zone.
@@ -127,7 +112,7 @@ void knot_node_dump(knot_node_t *node, void *loaded_zone);
* \param loaded_zone Set to <> 0 if the node is part of a zone loaded into
* the server. Set to 0 otherwise.
*/
-void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
+void knot_zone_contents_dump(knot_zone_contents_t *zone);
/******************************************************************************/
diff --git a/src/libknot/util/descriptor.c b/src/libknot/util/descriptor.c
deleted file mode 100644
index 8cab6b4..0000000
--- a/src/libknot/util/descriptor.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/*!
- * \file descriptor.c
- *
- * \author Modifications by Jan Kadlec <jan.kadlec@nic.cz>,
- * most of the work by NLnet labs.
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \note Most of the constants and functions were taken from NSD's dns.c.
- *
- * \addtogroup libknot
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "libknot.h"
-
-enum desclen { KNOT_RRTYPE_DESCRIPTORS_LENGTH = 32770 }; // used to be 101
-
-/*!
- * \brief Table for linking RR class constants to their textual representation.
- */
-static knot_lookup_table_t dns_rrclasses[] = {
- { KNOT_CLASS_IN, "IN" }, /* the Internet */
- { KNOT_CLASS_CS, "CS" }, /* the CSNET class (Obsolete) */
- { KNOT_CLASS_CH, "CH" }, /* the CHAOS class */
- { KNOT_CLASS_HS, "HS" }, /* Hesiod */
- { 0, NULL }
-};
-
-/*! \brief DS digest lengths. */
-enum knot_ds_algorithm_len
-{
- KNOT_DS_DIGEST_LEN_SHA1 = 20, /* 20B - RFC 3658 */
- KNOT_DS_DIGEST_LEN_SHA256 = 32, /* 32B - RFC 4509 */
- KNOT_DS_DIGEST_LEN_GOST = 32, /* 32B - RFC 5933 */
- KNOT_DS_DIGEST_LEN_SHA384 = 48 /* 48B - RFC 6605 */
-};
-
-/*! \brief RR type descriptors. */
-static knot_rrtype_descriptor_t
- knot_rrtype_descriptors[KNOT_RRTYPE_DESCRIPTORS_LENGTH] = {
- /* 0 */
- { 0, NULL, 1, { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 1 */
- { KNOT_RRTYPE_A, "A", 1, { KNOT_RDATA_WF_A }, { KNOT_RDATA_ZF_A }, true },
- /* 2 */
- { KNOT_RRTYPE_NS, "NS", 1,
- { KNOT_RDATA_WF_COMPRESSED_DNAME }, { KNOT_RDATA_ZF_DNAME }, true },
- /* 3 */
- { KNOT_RRTYPE_MD, "MD", 1,
- { KNOT_RDATA_WF_UNCOMPRESSED_DNAME }, { KNOT_RDATA_ZF_DNAME }, true },
- /* 4 */
- { KNOT_RRTYPE_MF, "MF", 1,
- { KNOT_RDATA_WF_UNCOMPRESSED_DNAME }, { KNOT_RDATA_ZF_DNAME }, true },
- /* 5 */
- { KNOT_RRTYPE_CNAME, "CNAME", 1,
- { KNOT_RDATA_WF_COMPRESSED_DNAME }, { KNOT_RDATA_ZF_DNAME }, true },
- /* 6 */
- { KNOT_RRTYPE_SOA, "SOA", 7,
- { KNOT_RDATA_WF_COMPRESSED_DNAME, KNOT_RDATA_WF_COMPRESSED_DNAME,
- KNOT_RDATA_WF_LONG, KNOT_RDATA_WF_LONG, KNOT_RDATA_WF_LONG,
- KNOT_RDATA_WF_LONG, KNOT_RDATA_WF_LONG },
- { KNOT_RDATA_ZF_DNAME, KNOT_RDATA_ZF_DNAME, KNOT_RDATA_ZF_PERIOD, KNOT_RDATA_ZF_PERIOD,
- KNOT_RDATA_ZF_PERIOD, KNOT_RDATA_ZF_PERIOD, KNOT_RDATA_ZF_PERIOD },
- true },
- /* 7 */
- { KNOT_RRTYPE_MB, "MB", 1,
- { KNOT_RDATA_WF_COMPRESSED_DNAME }, { KNOT_RDATA_ZF_DNAME }, true },
- /* 8 */
- { KNOT_RRTYPE_MG, "MG", 1,
- { KNOT_RDATA_WF_COMPRESSED_DNAME }, { KNOT_RDATA_ZF_DNAME }, true },
- /* 9 */
- { KNOT_RRTYPE_MR, "MR", 1,
- { KNOT_RDATA_WF_COMPRESSED_DNAME }, { KNOT_RDATA_ZF_DNAME }, true },
- /* 10 */
- { KNOT_RRTYPE_NULL, NULL, 1,
- { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 11 */
- { KNOT_RRTYPE_WKS, "WKS", 2,
- { KNOT_RDATA_WF_A, KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_A, KNOT_RDATA_ZF_SERVICES }, true },
- /* 12 */
- { KNOT_RRTYPE_PTR, "PTR", 1,
- { KNOT_RDATA_WF_COMPRESSED_DNAME },
- { KNOT_RDATA_ZF_DNAME }, true },
- /* 13 */
- { KNOT_RRTYPE_HINFO, "HINFO", 2,
- { KNOT_RDATA_WF_TEXT_SINGLE, KNOT_RDATA_WF_TEXT_SINGLE },
- { KNOT_RDATA_ZF_TEXT_SINGLE, KNOT_RDATA_ZF_TEXT_SINGLE }, true },
- /* 14 */
- { KNOT_RRTYPE_MINFO, "MINFO", 2,
- { KNOT_RDATA_WF_COMPRESSED_DNAME,
- KNOT_RDATA_WF_COMPRESSED_DNAME },
- { KNOT_RDATA_ZF_DNAME, KNOT_RDATA_ZF_DNAME }, true },
- /* 15 */
- { KNOT_RRTYPE_MX, "MX", 2,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_COMPRESSED_DNAME },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_DNAME }, true },
- /* 16 */ /* This is obscure, but I guess there's no other way */
- { KNOT_RRTYPE_TXT, "TXT", 1,
- { KNOT_RDATA_WF_TEXT },
- { KNOT_RDATA_ZF_TEXT },
- false },
- /* 17 */
- { KNOT_RRTYPE_RP, "RP", 2,
- { KNOT_RDATA_WF_COMPRESSED_DNAME,
- KNOT_RDATA_WF_COMPRESSED_DNAME },
- { KNOT_RDATA_ZF_DNAME, KNOT_RDATA_ZF_DNAME }, true },
- /* 18 */
- { KNOT_RRTYPE_AFSDB, "AFSDB", 2,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_COMPRESSED_DNAME },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_DNAME }, true },
- /* 19 */
- { KNOT_RRTYPE_X25, "X25", 1,
- { KNOT_RDATA_WF_TEXT_SINGLE },
- { KNOT_RDATA_ZF_TEXT_SINGLE }, true },
- /* 20 */
- { KNOT_RRTYPE_ISDN, "ISDN", 2,
- { KNOT_RDATA_WF_TEXT_SINGLE, KNOT_RDATA_WF_TEXT_SINGLE },
- { KNOT_RDATA_ZF_TEXT_SINGLE, KNOT_RDATA_ZF_TEXT_SINGLE }, false },
- /* 21 */
- { KNOT_RRTYPE_RT, "RT", 2,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_COMPRESSED_DNAME },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_DNAME }, true },
- /* 22 */
- { KNOT_RRTYPE_NSAP, "NSAP", 1,
- { KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_NSAP }, true },
- /* 23 */
- { 23, NULL, 1, { KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 24 */
- { KNOT_RRTYPE_SIG, "SIG", 9,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_LONG, KNOT_RDATA_WF_LONG, KNOT_RDATA_WF_LONG,
- KNOT_RDATA_WF_SHORT,KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
- KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_RRTYPE, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_PERIOD,
- KNOT_RDATA_ZF_TIME, KNOT_RDATA_ZF_TIME, KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_DNAME,
- KNOT_RDATA_ZF_BASE64 },
- true },
- /* 25 */
- { KNOT_RRTYPE_KEY, "KEY", 4,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_ALGORITHM,
- KNOT_RDATA_ZF_BASE64 }, true },
- /* 26 */
- { KNOT_RRTYPE_PX, "PX", 3,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_DNAME, KNOT_RDATA_ZF_DNAME }, true },
- /* 27 */
- { 27, NULL, 1, { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 28 */
- { KNOT_RRTYPE_AAAA, "AAAA", 1,
- { KNOT_RDATA_WF_AAAA },
- { KNOT_RDATA_ZF_AAAA }, true },
- /* 29 */
- { KNOT_RRTYPE_LOC, "LOC", 1,
- { KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_LOC }, true },
- /* 30 */
- { KNOT_RRTYPE_NXT, "NXT", 2,
- { KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
- KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_DNAME, KNOT_RDATA_ZF_NXT }, true },
- /* 31 */
- { 31, NULL, 1, { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 32 */
- { 32, NULL, 1, { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 33 */
- { KNOT_RRTYPE_SRV, "SRV", 4,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_SHORT,
- KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_UNCOMPRESSED_DNAME },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_DNAME },
- true },
- /* 34 */
- { 34, NULL, 1, { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 35 */
- { KNOT_RRTYPE_NAPTR, "NAPTR", 6,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_TEXT_SINGLE,
- KNOT_RDATA_WF_TEXT_SINGLE, KNOT_RDATA_WF_TEXT_SINGLE,
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_TEXT_SINGLE,
- KNOT_RDATA_ZF_TEXT_SINGLE, KNOT_RDATA_ZF_TEXT_SINGLE,
- KNOT_RDATA_ZF_DNAME }, true },
- /* 36 */
- { KNOT_RRTYPE_KX, "KX", 2,
- { KNOT_RDATA_WF_SHORT,
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_DNAME }, true },
- /* 37 */
- { KNOT_RRTYPE_CERT, "CERT", 4,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_SHORT,
- KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_CERTIFICATE_TYPE, KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_ALGORITHM,
- KNOT_RDATA_ZF_BASE64 }, true },
- /* 38 */
- { KNOT_RRTYPE_A6, NULL, 1, { KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 39 */
- { KNOT_RRTYPE_DNAME, "DNAME", 1,
- { KNOT_RDATA_WF_UNCOMPRESSED_DNAME },
- { KNOT_RDATA_ZF_DNAME }, true },
- /* 40 */
- { 40, NULL, 1, { KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 41 */
- /* OPT has its parser token, but should never be in zone file... */
- { KNOT_RRTYPE_OPT, "OPT", 1,
- { KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 42 */
- { KNOT_RRTYPE_APL, "APL", 64,
- { KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL,
- KNOT_RDATA_WF_APL, KNOT_RDATA_WF_APL },
- { KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL,
- KNOT_RDATA_ZF_APL, KNOT_RDATA_ZF_APL },
- false },
- /* 43 */
- { KNOT_RRTYPE_DS, "DS", 4,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_ALGORITHM, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_HEX }, true },
- /* 44 */
- { KNOT_RRTYPE_SSHFP, "SSHFP", 3,
- { KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_HEX },
- true },
- /* 45 */
- { KNOT_RRTYPE_IPSECKEY, "IPSECKEY", 5,
- { KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_IPSECGATEWAY,
- KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_IPSECGATEWAY,
- KNOT_RDATA_ZF_BASE64 }, false },
- /* 46 */
- { KNOT_RRTYPE_RRSIG, "RRSIG", 9,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_LONG,
- KNOT_RDATA_WF_LONG, KNOT_RDATA_WF_LONG,
- KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_LITERAL_DNAME,
- KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_RRTYPE, KNOT_RDATA_ZF_ALGORITHM,
- KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_PERIOD,
- KNOT_RDATA_ZF_TIME, KNOT_RDATA_ZF_TIME,
- KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_LITERAL_DNAME,
- KNOT_RDATA_ZF_BASE64 }, true },
- /* 47 */
- { KNOT_RRTYPE_NSEC, "NSEC", 2,
- { KNOT_RDATA_WF_LITERAL_DNAME, KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_LITERAL_DNAME, KNOT_RDATA_ZF_NSEC },
- true },
- /* 48 */
- { KNOT_RRTYPE_DNSKEY, "DNSKEY", 4,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_BYTE,
- KNOT_RDATA_ZF_ALGORITHM, KNOT_RDATA_ZF_BASE64 }, true },
- /* 49 */
- { KNOT_RRTYPE_DHCID, "DHCID", 1, { KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_BASE64 }, true },
- /* 50 */
- { KNOT_RRTYPE_NSEC3, "NSEC3", 6,
- { KNOT_RDATA_WF_BYTE, /* hash type */
- KNOT_RDATA_WF_BYTE, /* flags */
- KNOT_RDATA_WF_SHORT, /* iterations */
- KNOT_RDATA_WF_BINARYWITHLENGTH, /* salt */
- KNOT_RDATA_WF_BINARYWITHLENGTH, /* next hashed name */
- KNOT_RDATA_WF_BINARY /* type bitmap */ },
- { KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_HEX_LEN,
- KNOT_RDATA_ZF_BASE32, KNOT_RDATA_ZF_NSEC },
- true },
- /* 51 */
- { KNOT_RRTYPE_NSEC3PARAM, "NSEC3PARAM", 4,
- { KNOT_RDATA_WF_BYTE, /* hash type */
- KNOT_RDATA_WF_BYTE, /* flags */
- KNOT_RDATA_WF_SHORT, /* iterations */
- KNOT_RDATA_WF_BINARYWITHLENGTH /* salt */ },
- { KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE,
- KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_HEX_LEN }, true },
- /* 52 */
- { KNOT_RRTYPE_TLSA, "TLSA", 4,
- { KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_BYTE,
- KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_HEX }, true },
-
-
- /* In NSD they have indices between 52 and 99 filled with
- unknown types. TODO add here if it's really needed? */
- /* it is indeed needed, in rrtype_from_string */
-
- /* There's a GNU extension that works like this: [first ... last] = value */
-
- [53 ... 98] = { 0, NULL, 1, { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- /* 99 */
- [99] = { KNOT_RRTYPE_SPF, "SPF", 1,
- { KNOT_RDATA_WF_TEXT },
- { KNOT_RDATA_ZF_TEXT }, false },
- /* TSIG pseudo RR. */
- [100 ... 249] = { 0, NULL, 1, { KNOT_RDATA_WF_BINARY }, { KNOT_RDATA_ZF_UNKNOWN }, true },
- [250] = { KNOT_RRTYPE_TSIG, "TSIG", 7,
- { KNOT_RDATA_WF_UNCOMPRESSED_DNAME, KNOT_RDATA_WF_UINT48,
- KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_BINARYWITHSHORT,
- KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_SHORT,
- KNOT_RDATA_WF_BINARYWITHSHORT },
- /* Zoneformat not needed. */
- {0, 0, 0, 0, 0}, true },
- /* 32769 */
- [32769] = { KNOT_RRTYPE_DLV, "DLV", 4,
- { KNOT_RDATA_WF_SHORT, KNOT_RDATA_WF_BYTE,
- KNOT_RDATA_WF_BYTE, KNOT_RDATA_WF_BINARY },
- { KNOT_RDATA_ZF_SHORT, KNOT_RDATA_ZF_ALGORITHM, KNOT_RDATA_ZF_BYTE, KNOT_RDATA_ZF_HEX },
- true },
-};
-
-knot_rrtype_descriptor_t *knot_rrtype_descriptor_by_type(uint16_t type)
-{
- if (type < KNOT_RRTYPE_LAST + 1) {
- return &knot_rrtype_descriptors[type];
- } else if (type == KNOT_RRTYPE_DLV) {
- return &knot_rrtype_descriptors[KNOT_RRTYPE_DLV];
- }
- return &knot_rrtype_descriptors[0];
-}
-
-/* I see a lot of potential here to speed up zone parsing - this is O(n) *
- * could be better */
-knot_rrtype_descriptor_t *knot_rrtype_descriptor_by_name(const char *name)
-{
- int i;
-
- for (i = 0; i < KNOT_RRTYPE_DLV + 1; ++i) {
- if (knot_rrtype_descriptors[i].name &&
- strcasecmp(knot_rrtype_descriptors[i].name, name) == 0) {
- return &knot_rrtype_descriptors[i];
- }
- }
-
- if (knot_rrtype_descriptors[KNOT_RRTYPE_DLV].name &&
- strcasecmp(knot_rrtype_descriptors[KNOT_RRTYPE_DLV].name,
- name) == 0) {
- return &knot_rrtype_descriptors[KNOT_RRTYPE_DLV];
- }
-
- return NULL;
-}
-
-const char *knot_rrtype_to_string(uint16_t rrtype)
-{
- static char buf[20];
- knot_rrtype_descriptor_t *descriptor =
- knot_rrtype_descriptor_by_type(rrtype);
- if (descriptor->name) {
- return descriptor->name;
- } else {
- snprintf(buf, sizeof(buf), "TYPE%d", (int) rrtype);
- return buf;
- }
-}
-
-uint16_t knot_rrtype_from_string(const char *name)
-{
- char *end;
- long rrtype;
- knot_rrtype_descriptor_t *entry;
-
- entry = knot_rrtype_descriptor_by_name(name);
- if (entry) {
- return entry->type;
- }
-
- if (strlen(name) < 5) {
- return 0;
- }
-
- if (strncasecmp(name, "TYPE", 4) != 0) {
- return 0;
- }
-
- if (!isdigit((int)name[4])) {
- return 0;
- }
-
- /* The rest from the string must be a number. */
- rrtype = strtol(name + 4, &end, 10);
- if (*end != '\0') {
- return 0;
- }
- if (rrtype < 0 || rrtype > 65535L) {
- return 0;
- }
-
- return (uint16_t) rrtype;
-}
-
-const char *knot_rrclass_to_string(uint16_t rrclass)
-{
- static char buf[20];
- knot_lookup_table_t *entry = knot_lookup_by_id(dns_rrclasses,
- rrclass);
- if (entry) {
- assert(strlen(entry->name) < sizeof(buf));
- knot_strlcpy(buf, entry->name, sizeof(buf));
- } else {
- snprintf(buf, sizeof(buf), "CLASS%d", (int) rrclass);
- }
- return buf;
-}
-
-uint16_t knot_rrclass_from_string(const char *name)
-{
- char *end;
- long rrclass;
- knot_lookup_table_t *entry;
-
- entry = knot_lookup_by_name(dns_rrclasses, name);
- if (entry) {
- return (uint16_t) entry->id;
- }
-
- if (strlen(name) < 6) {
- return 0;
- }
-
- if (strncasecmp(name, "CLASS", 5) != 0) {
- return 0;
- }
-
- if (!isdigit((int)name[5])) {
- return 0;
- }
-
- // The rest from the string must be a number.
- rrclass = strtol(name + 5, &end, 10);
- if (*end != '\0') {
- return 0;
- }
- if (rrclass < 0 || rrclass > 65535L) {
- return 0;
- }
-
- return (uint16_t) rrclass;
-}
-
-size_t knot_wireformat_size(unsigned int wire_type)
-{
- switch(wire_type) {
- case KNOT_RDATA_WF_BYTE:
- return 1;
- break;
- case KNOT_RDATA_WF_SHORT:
- return 2;
- break;
- case KNOT_RDATA_WF_LONG:
- return 4;
- break;
- case KNOT_RDATA_WF_A:
- return 4;
- break;
- default: /* unknown size */
- return 0;
- break;
- } /* switch */
-}
-
-int knot_rrtype_is_metatype(uint16_t type)
-{
- /*! \todo Check if there are some other metatypes. */
- return (type == KNOT_RRTYPE_ANY
- || type == KNOT_RRTYPE_AXFR
- || type == KNOT_RRTYPE_IXFR
- || type == KNOT_RRTYPE_MAILA
- || type == KNOT_RRTYPE_MAILB
- || type == KNOT_RRTYPE_OPT);
-}
-
-size_t knot_ds_digest_length(uint8_t algorithm)
-{
- switch (algorithm) {
- case KNOT_DS_ALG_SHA1:
- return KNOT_DS_DIGEST_LEN_SHA1;
- case KNOT_DS_ALG_SHA256:
- return KNOT_DS_DIGEST_LEN_SHA256;
- case KNOT_DS_ALG_GOST:
- return KNOT_DS_DIGEST_LEN_GOST;
- case KNOT_DS_ALG_SHA384:
- return KNOT_DS_DIGEST_LEN_SHA384;
- default:
- return 0;
- }
-}
-
-/*! @} */
-
diff --git a/src/libknot/util/descriptor.h b/src/libknot/util/descriptor.h
deleted file mode 100644
index 23b5d13..0000000
--- a/src/libknot/util/descriptor.h
+++ /dev/null
@@ -1,371 +0,0 @@
-/*!
- * \file descriptor.h
- *
- * \author Modifications by Jan Kadlec <jan.kadlec@nic.cz>,
- * most of the work by NLnet Labs.
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \note Most of the constants and functions were taken from NSD's dns.h.
- *
- * \addtogroup libknot
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _KNOT_DESCRIPTOR_H_
-#define _KNOT_DESCRIPTOR_H_
-
-#include <stdint.h>
-#include <stdbool.h>
-#include <string.h>
-
-enum knot_mxrdtln {
- /*! \brief Maximum items in RDATA wireformat. */
- KNOT_MAX_RDATA_ITEMS = 64,
- /*! \brief Maximum size of one item in RDATA wireformat. */
- KNOT_MAX_RDATA_ITEM_SIZE = 65534,
- /*! \brief Maximum wire size of one RDATA. */
- KNOT_MAX_RDATA_WIRE_SIZE =
- KNOT_MAX_RDATA_ITEMS * KNOT_MAX_RDATA_ITEM_SIZE
-};
-
-typedef enum knot_mxrdtln knot_mxrdtln_t;
-//#define MAXRDATALEN 64
-
-/* 64 is in NSD. Seems a little too much, but I'd say it's not a real issue. */
-
-/*!
- * \brief Resource record class codes.
- */
-enum knot_rr_class {
- KNOT_CLASS_IN = 1,
- KNOT_CLASS_CS,
- KNOT_CLASS_CH,
- KNOT_CLASS_HS,
- KNOT_CLASS_NONE = 254,
- KNOT_CLASS_ANY = 255
-};
-
-typedef enum knot_rr_class knot_rr_class_t;
-
-/*!
- * \brief Resource record type constants.
- * \todo Not all indices can be used for indexing.
- */
-enum knot_rr_type {
- KNOT_RRTYPE_UNKNOWN, /*!< 0 - an unknown type */
- KNOT_RRTYPE_A, /*!< 1 - a host address */
- KNOT_RRTYPE_NS, /*!< 2 - an authoritative name server */
- KNOT_RRTYPE_MD, /*!< 3 - a mail destination (Obsolete - use MX) */
- KNOT_RRTYPE_MF, /*!< 4 - a mail forwarder (Obsolete - use MX) */
- KNOT_RRTYPE_CNAME, /*!< 5 - the canonical name for an alias */
- KNOT_RRTYPE_SOA, /*!< 6 - marks the start of a zone of authority */
- KNOT_RRTYPE_MB, /*!< 7 - a mailbox domain name (EXPERIMENTAL) */
- KNOT_RRTYPE_MG, /*!< 8 - a mail group member (EXPERIMENTAL) */
- KNOT_RRTYPE_MR, /*!< 9 - a mail rename domain name (EXPERIMENTAL) */
- KNOT_RRTYPE_NULL, /*!< 10 - a null RR (EXPERIMENTAL) */
- KNOT_RRTYPE_WKS, /*!< 11 - a well known service description */
- KNOT_RRTYPE_PTR, /*!< 12 - a domain name pointer */
- KNOT_RRTYPE_HINFO, /*!< 13 - host information */
- KNOT_RRTYPE_MINFO, /*!< 14 - mailbox or mail list information */
- KNOT_RRTYPE_MX, /*!< 15 - mail exchange */
- KNOT_RRTYPE_TXT, /*!< 16 - text strings */
- KNOT_RRTYPE_RP, /*!< 17 - RFC1183 */
- KNOT_RRTYPE_AFSDB, /*!< 18 - RFC1183 */
- KNOT_RRTYPE_X25, /*!< 19 - RFC1183 */
- KNOT_RRTYPE_ISDN, /*!< 20 - RFC1183 */
- KNOT_RRTYPE_RT, /*!< 21 - RFC1183 */
- KNOT_RRTYPE_NSAP, /*!< 22 - RFC1706 */
-
- KNOT_RRTYPE_SIG = 24, /*!< 24 - 2535typecode */
- KNOT_RRTYPE_KEY, /*!< 25 - 2535typecode */
- KNOT_RRTYPE_PX, /*!< 26 - RFC2163 */
-
- KNOT_RRTYPE_AAAA = 28, /*!< 28 - ipv6 address */
- KNOT_RRTYPE_LOC, /*!< 29 - LOC record RFC1876 */
- KNOT_RRTYPE_NXT, /*!< 30 - 2535typecode */
-
- KNOT_RRTYPE_SRV = 33, /*!< 33 - SRV record RFC2782 */
-
- KNOT_RRTYPE_NAPTR = 35, /*!< 35 - RFC2915 */
- KNOT_RRTYPE_KX, /*!< 36 - RFC2230 Key Exchange Delegation Record */
- KNOT_RRTYPE_CERT, /*!< 37 - RFC2538 */
- KNOT_RRTYPE_A6, /*!< 38 - RFC2874 */
- KNOT_RRTYPE_DNAME, /*!< 39 - RFC2672 */
-
- KNOT_RRTYPE_OPT = 41, /*!< 41 - Pseudo OPT record... */
- KNOT_RRTYPE_APL, /*!< 42 - RFC3123 */
- KNOT_RRTYPE_DS, /*!< 43 - RFC 4033, 4034, and 4035 */
- KNOT_RRTYPE_SSHFP, /*!< 44 - SSH Key Fingerprint */
- KNOT_RRTYPE_IPSECKEY, /*!< 45 - public key for ipsec use. RFC 4025 */
- KNOT_RRTYPE_RRSIG, /*!< 46 - RFC 4033, 4034, and 4035 */
- KNOT_RRTYPE_NSEC, /*!< 47 - RFC 4033, 4034, and 4035 */
- KNOT_RRTYPE_DNSKEY, /*!< 48 - RFC 4033, 4034, and 4035 */
- KNOT_RRTYPE_DHCID, /*!< 49 - RFC4701 DHCP information */
- /*!
- * \brief 50 - NSEC3, secure denial, prevents zonewalking
- */
- KNOT_RRTYPE_NSEC3,
- /*!
- * \brief 51 - NSEC3PARAM at zone apex nsec3 parameters
- */
- KNOT_RRTYPE_NSEC3PARAM,
- KNOT_RRTYPE_TLSA = 52,
-
- /* TODO consider some better way of doing this, indices too high */
-
- KNOT_RRTYPE_SPF = 99, /*!< RFC 4408 */
-
- // not designating any RRs
- KNOT_RRTYPE_TSIG = 250, /*!< TSIG - RFC2845. */
- KNOT_RRTYPE_IXFR = 251, /*!< IXFR (not an actual RR). */
- KNOT_RRTYPE_AXFR = 252, /*!< AXFR (not an actual RR). */
- /*!
- * \brief A request for mailbox-related records (MB, MG or MR)
- */
- KNOT_RRTYPE_MAILB = 253,
- /*!
- * \brief A request for mail agent RRs (Obsolete - see MX)
- */
- KNOT_RRTYPE_MAILA = 254,
- KNOT_RRTYPE_ANY = 255, /*!< any type (wildcard) */
-
- // totally weird numbers (cannot use for indexing)
- KNOT_RRTYPE_TA = 32768, /*!< DNSSEC Trust Authorities */
- KNOT_RRTYPE_DLV = 32769, /*!< RFC 4431 */
-
- /*! \brief Last normal RR type. */
- KNOT_RRTYPE_LAST = KNOT_RRTYPE_TSIG
- /*! \todo [TSIG] Is it allright to include all <= RR TSIG?
- * Because TSIG is normal RR type. */
-};
-
-typedef enum knot_rr_type knot_rr_type_t;
-
-/*! \brief Constants characterising the wire format of RDATA items. */
-enum knot_rdata_wireformat {
- /*!
- * \brief Possibly compressed domain name.
- */
- KNOT_RDATA_WF_COMPRESSED_DNAME = 50,
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME = 51, /*!< Uncompressed domain name. */
- KNOT_RDATA_WF_LITERAL_DNAME = 52, /*!< Literal (not downcased) dname. */
- KNOT_RDATA_WF_BYTE = 1, /*!< 8-bit integer. */
- KNOT_RDATA_WF_SHORT = 2, /*!< 16-bit integer. */
- KNOT_RDATA_WF_LONG = 4, /*!< 32-bit integer. */
- KNOT_RDATA_WF_UINT48 = 8, /*!< 48-bit integer. */
- KNOT_RDATA_WF_TEXT = 53, /*!< Array of text strings. */
- KNOT_RDATA_WF_A = 58, /*!< 32-bit IPv4 address. */
- KNOT_RDATA_WF_AAAA = 16, /*!< 128-bit IPv6 address. */
- KNOT_RDATA_WF_BINARY = 54, /*!< Binary data (unknown length). */
- /*!
- * \brief Binary data preceded by 1 byte length
- */
- KNOT_RDATA_WF_BINARYWITHLENGTH = 55,
- KNOT_RDATA_WF_APL = 56, /*!< APL data. */
- KNOT_RDATA_WF_IPSECGATEWAY = 57, /*!< IPSECKEY gateway ip4, ip6 or dname. */
- KNOT_RDATA_WF_BINARYWITHSHORT = 59,
- KNOT_RDATA_WF_TEXT_SINGLE = 60 /*!< Text string. */
-};
-
-/*! \brief Constants characterising the format of RDATA items in zone file. */
-enum knot_rdata_zoneformat
-{
- KNOT_RDATA_ZF_DNAME, /* Domain name. */
- KNOT_RDATA_ZF_LITERAL_DNAME, /* DNS name (not lowercased domain name). */
- KNOT_RDATA_ZF_TEXT, /* Array of text strings. */
- KNOT_RDATA_ZF_TEXT_SINGLE, /* Text string. */
- KNOT_RDATA_ZF_BYTE, /* 8-bit integer. */
- KNOT_RDATA_ZF_SHORT, /* 16-bit integer. */
- KNOT_RDATA_ZF_LONG, /* 32-bit integer. */
- KNOT_RDATA_ZF_A, /* 32-bit IPv4 address. */
- KNOT_RDATA_ZF_AAAA, /* 128-bit IPv6 address. */
- KNOT_RDATA_ZF_RRTYPE, /* RR type. */
- KNOT_RDATA_ZF_ALGORITHM, /* Cryptographic algorithm. */
- KNOT_RDATA_ZF_CERTIFICATE_TYPE,
- KNOT_RDATA_ZF_PERIOD, /* Time period. */
- KNOT_RDATA_ZF_TIME,
- KNOT_RDATA_ZF_BASE64, /* Base-64 binary data. */
- KNOT_RDATA_ZF_BASE32, /* Base-32 binary data. */
- KNOT_RDATA_ZF_HEX, /* Hexadecimal binary data. */
- KNOT_RDATA_ZF_HEX_LEN, /* Hexadecimal binary data. Skip initial length byte. */
- KNOT_RDATA_ZF_NSAP, /* NSAP. */
- KNOT_RDATA_ZF_APL, /* APL. */
- KNOT_RDATA_ZF_IPSECGATEWAY, /* IPSECKEY gateway ip4, ip6 or dname. */
- KNOT_RDATA_ZF_SERVICES, /* Protocol and port number bitmap. */
- KNOT_RDATA_ZF_NXT, /* NXT type bitmap. */
- KNOT_RDATA_ZF_NSEC, /* NSEC type bitmap. */
- KNOT_RDATA_ZF_LOC, /* Location data. */
- KNOT_RDATA_ZF_UNKNOWN /* Unknown data. */
-};
-
-/*! \brief Constants characterising the wire format of RDATA items. */
-typedef enum knot_rdata_zoneformat knot_rdata_zoneformat_t;
-
-/*! \brief Enum containing wireformat codes. */
-typedef enum knot_rdatawireformat knot_rdata_wireformat_t;
-
-/*! \brief Constants for DNSSEC algorithm types.
- *
- * Source: http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml
- */
-enum knot_dnssec_algorithm
-{
- KNOT_DNSSEC_ALG_RSAMD5 = 1,
- KNOT_DNSSEC_ALG_DH = 2,
- KNOT_DNSSEC_ALG_DSA = 3,
- KNOT_DNSSEC_ALG_RSASHA1 = 5,
- KNOT_DNSSEC_ALG_DSA_NSEC3_SHA1 = 6,
- KNOT_DNSSEC_ALG_RSASHA1_NSEC3_SHA1 = 7,
- KNOT_DNSSEC_ALG_RSASHA256 = 8,
- KNOT_DNSSEC_ALG_RSASHA512 = 10,
- KNOT_DNSSEC_ALG_ECC_GOST = 12,
- KNOT_DNSSEC_ALG_ECDSAP256SHA256 = 13,
- KNOT_DNSSEC_ALG_ECDSAP384SHA384 = 14
-};
-
-typedef enum knot_dnssec_algorithm knot_dnssec_algorithm_t;
-
-/*! \brief Constants for DNSSEC algorithm types.
- *
- * Source: http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xml
- */
-enum knot_ds_algorithm
-{
- KNOT_DS_ALG_SHA1 = 1, /* 20B - RFC 3658 */
- KNOT_DS_ALG_SHA256 = 2, /* 32B - RFC 4509 */
- KNOT_DS_ALG_GOST = 3, /* 32B - RFC 5933 */
- KNOT_DS_ALG_SHA384 = 4 /* 48B - RFC 6605 */
-};
-
-typedef enum knot_ds_algorithm knot_ds_algorithm_t;
-
-/*! \brief Structure holding RR descriptor. */
-struct knot_rrtype_descriptor {
- uint16_t type; /*!< RR type */
- const char *name; /*!< Textual name. */
- uint8_t length; /*!< Maximum number of RDATA items. */
-
- /*! \brief Wire format specification for the RDATA. */
- uint8_t wireformat[KNOT_MAX_RDATA_ITEMS];
-
- /*! \brief Zone file format specification for the RDATA. */
- uint8_t zoneformat[KNOT_MAX_RDATA_ITEMS];
-
- bool fixed_items; /*!< Has fixed number of RDATA items? */
-};
-
-/*! \brief Structure holding RR descriptor. */
-typedef struct knot_rrtype_descriptor knot_rrtype_descriptor_t;
-
-/*!
- * \brief Gets RR descriptor for given RR type.
- *
- * \param type Code of RR type whose descriptor should be returned.
- *
- * \return RR descriptor for given type code, NULL descriptor if
- * unknown type.
- *
- * \todo Change return value to const.
- */
-knot_rrtype_descriptor_t *knot_rrtype_descriptor_by_type(uint16_t type);
-
-/*!
- * \brief Gets RR descriptor for given RR name.
- *
- * \param name Mnemonic of RR type whose descriptor should be returned.
- *
- * \return RR descriptor for given name, NULL descriptor if
- * unknown type.
- *
- * \todo Change return value to const.
- */
-knot_rrtype_descriptor_t *knot_rrtype_descriptor_by_name(const char *name);
-
-/*!
- * \brief Converts numeric type representation to mnemonic string.
- *
- * \param rrtype Type RR type code to be converted.
- *
- * \return Mnemonic string if found, str(TYPE[rrtype]) otherwise.
- */
-const char *knot_rrtype_to_string(uint16_t rrtype);
-
-/*!
- * \brief Converts mnemonic string representation of a type to numeric one.
- *
- * \param name Mnemonic string to be converted.
- *
- * \return Correct code if found, 0 otherwise.
- */
-uint16_t knot_rrtype_from_string(const char *name);
-
-/*!
- * \brief Converts numeric class representation to string one.
- *
- * \param rrclass Class code to be converted.
- *
- * \return String represenation of class if found,
- * str(CLASS[rrclass]) otherwise.
- */
-const char *knot_rrclass_to_string(uint16_t rrclass);
-
-/*!
- * \brief Converts string representation of a class to numeric one.
- *
- * \param name Class string to be converted.
- *
- * \return Correct code if found, 0 otherwise.
- */
-uint16_t knot_rrclass_from_string(const char *name);
-
-/*!
- * \brief Returns size of wireformat type in bytes.
- *
- * \param wire_type Wireformat type.
- *
- * \retval Size of given type on success.
- * \retval 0 on unknown type or type that has no length.
- */
-size_t knot_wireformat_size(unsigned int wire_type);
-
-int knot_rrtype_is_metatype(uint16_t type);
-
-size_t knot_ds_digest_length(uint8_t algorithm);
-
-#endif /* _KNOT_DESCRIPTOR_H_ */
-
-/*! @} */
-
diff --git a/src/tests/libknot/realdata/libknot/packet_tests_realdata.h b/src/libknot/util/endian.h
index c0e0479..1702bbc 100644
--- a/src/tests/libknot/realdata/libknot/packet_tests_realdata.h
+++ b/src/libknot/util/endian.h
@@ -14,12 +14,26 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_PACKET_REALDATA_TESTS_H_
-#define _KNOTD_PACKET_REALDATA_TESTS_H_
+#ifndef _KNOT_ENDIAN_H
+#define _KNOT_ENDIAN_H
-#include "common/libtap/tap_unit.h"
+#if defined(__linux__)
+# include <endian.h>
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+# include <sys/endian.h>
+#elif defined(__OpenBSD__)
+# include <sys/types.h>
+# define be16toh(x) betoh16(x)
+# define be32toh(x) betoh32(x)
+# define be64toh(x) betoh64(x)
+#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)
+#endif
-/* Unit API. */
-unit_api packet_tests_api;
-
-#endif /* _KNOTD_PACKET_REALDATA_TESTS_H_ */
+#endif /* _KNOT_ENDIAN_H_ */
diff --git a/src/libknot/util/tolower.c b/src/libknot/util/tolower.c
index d71c467..d8ca17d 100644
--- a/src/libknot/util/tolower.c
+++ b/src/libknot/util/tolower.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "util/tolower.h"
const uint8_t char_table[CHAR_TABLE_SIZE] = {
diff --git a/src/libknot/util/tolower.h b/src/libknot/util/tolower.h
index 2e92258..55f3eb7 100644
--- a/src/libknot/util/tolower.h
+++ b/src/libknot/util/tolower.h
@@ -42,7 +42,7 @@ extern const uint8_t char_table[CHAR_TABLE_SIZE];
/*!
* \brief Converts ASCII character to lowercase.
- *
+ *
* \param c ASCII character code.
*
* \return \a c converted to lowercase (or \a c if not applicable).
diff --git a/src/libknot/util/utils.c b/src/libknot/util/utils.c
index 04e12c5..e64e297 100644
--- a/src/libknot/util/utils.c
+++ b/src/libknot/util/utils.c
@@ -56,59 +56,6 @@ knot_lookup_table_t *knot_lookup_by_id(knot_lookup_table_t *table,
/*----------------------------------------------------------------------------*/
-size_t knot_strlcpy(char *dst, const char *src, size_t size)
-{
- char *d = dst;
- const char *s = src;
- size_t n = size;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0) {
- do {
- if ((*d++ = *s++) == 0) {
- break;
- }
- } while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (size != 0) {
- *d = '\0'; /* NUL-terminate dst */
- }
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
-
-/*! \brief TLS key for rand seed. */
-static pthread_key_t _qr_key;
-static pthread_once_t _qr_once = PTHREAD_ONCE_INIT;
-
-/*! \brief TLS key initializer. */
-static void _qr_init()
-{
- (void) pthread_key_create(&_qr_key, NULL);
- (void) pthread_setspecific(_qr_key, (void*)time(0));
-}
-
-size_t knot_quick_rand()
-{
- (void) pthread_once(&_qr_once, _qr_init);
- size_t x = (size_t)pthread_getspecific(_qr_key);
-
- /* Numerical Recipes in C.
- * The Art of Scientific Computing, 2nd Edition,
- * 1992, ISBN 0-521-43108-5.
- * Page 284.
- */
- x = 1664525L * x + 1013904223L;
- (void) pthread_setspecific(_qr_key, (void*)x);
- return x;
-}
-
uint16_t knot_random_id()
{
return (uint16_t)(tls_rand() * ((uint16_t)~0));
@@ -124,4 +71,3 @@ struct flock* knot_file_lock(short type, short whence)
ret.l_pid = getpid();
return &ret;
}
-
diff --git a/src/libknot/util/utils.h b/src/libknot/util/utils.h
index fd275b3..0aa7a55 100644
--- a/src/libknot/util/utils.h
+++ b/src/libknot/util/utils.h
@@ -27,6 +27,7 @@
#ifndef _KNOT_UTILS_H_
#define _KNOT_UTILS_H_
+#include "util/endian.h"
#include <string.h>
#include <stdint.h>
#include <stdio.h>
@@ -67,19 +68,6 @@ knot_lookup_table_t *knot_lookup_by_name(knot_lookup_table_t *table,
knot_lookup_table_t *knot_lookup_by_id(knot_lookup_table_t *table,
int id);
-/*!
- * \brief Strlcpy - safe string copy function, based on FreeBSD implementation.
- *
- * http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/
- *
- * \param dst Destination string.
- * \param src Source string.
- * \param size How many characters to copy - 1.
- *
- * \return strlen(src), if retval >= siz, truncation occurred.
- */
-size_t knot_strlcpy(char *dst, const char *src, size_t size);
-
/*
* Writing / reading arbitrary data to / from wireformat.
*/
@@ -89,13 +77,11 @@ size_t knot_strlcpy(char *dst, const char *src, size_t size);
*
* \param pos Data to read the 2 bytes from.
*
- * \todo Wrong assumption of endianness (issue #1558).
- *
- * \return The 2 bytes read, in inverse endian.
+ * \return The 2 bytes read, in host byte order.
*/
static inline uint16_t knot_wire_read_u16(const uint8_t *pos)
{
- return (pos[0] << 8) | pos[1];
+ return be16toh(*(uint16_t *)pos);
}
/*!
@@ -103,13 +89,11 @@ static inline uint16_t knot_wire_read_u16(const uint8_t *pos)
*
* \param pos Data to read the 4 bytes from.
*
- * \todo Wrong assumption of endianness (issue #1558).
- *
- * \return The 4 bytes read, in inverse endian.
+ * \return The 4 bytes read, in host byte order.
*/
static inline uint32_t knot_wire_read_u32(const uint8_t *pos)
{
- return (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | pos[3];
+ return be32toh(*(uint32_t *)pos);
}
/*!
@@ -117,80 +101,83 @@ static inline uint32_t knot_wire_read_u32(const uint8_t *pos)
*
* \param pos Data to read the 6 bytes from.
*
- * \todo Wrong assumption of endianness (issue #1558).
- *
- * \return The 6 bytes read, in inverse endian.
+ * \return The 6 bytes read, in host byte order.
*/
static inline uint64_t knot_wire_read_u48(const uint8_t *pos)
{
- return ((uint64_t)(pos[0]) << 40) | ((uint64_t)(pos[1]) << 32)
- | ((uint64_t)(pos[2]) << 24) | ((uint64_t)(pos[3]) << 16)
- | ((uint64_t)(pos[4]) << 8) | (uint64_t)pos[5];
+ uint64_t input = 0;
+ memcpy((void *)&input + 1, (void *)pos, 6);
+ return be64toh(input) >> 8;
}
/*!
- * \brief Writes 2 bytes in wireformat.
+ * \brief Read 8 bytes from the wireformat data.
*
- * The endian of the data is inverted.
+ * \param pos Data to read the 8 bytes from.
+ *
+ * \return The 8 bytes read, in host byte order.
+ */
+static inline uint64_t knot_wire_read_u64(const uint8_t *pos)
+{
+ return be64toh(*(uint64_t *)pos);
+}
+
+/*!
+ * \brief Writes 2 bytes in wireformat.
*
- * \todo Wrong assumption of endianness (issue #1558).
+ * The data are stored in network byte order (big endian).
*
* \param pos Position where to put the 2 bytes.
* \param data Data to put.
*/
static inline void knot_wire_write_u16(uint8_t *pos, uint16_t data)
{
- *(pos++) = (uint8_t)((data >> 8) & 0xff);
- *pos = (uint8_t)(data & 0xff);
+ *(uint16_t *)pos = htobe16(data);
}
/*!
* \brief Writes 4 bytes in wireformat.
*
- * The endian of the data is inverted.
- *
- * \todo Wrong assumption of endianness (issue #1558).
+ * The data are stored in network byte order (big endian).
*
* \param pos Position where to put the 4 bytes.
* \param data Data to put.
*/
static inline void knot_wire_write_u32(uint8_t *pos, uint32_t data)
{
- *(pos++) = (uint8_t)((data >> 24) & 0xff);
- *(pos++) = (uint8_t)((data >> 16) & 0xff);
- *(pos++) = (uint8_t)((data >> 8) & 0xff);
- *pos = (uint8_t)(data & 0xff);
+ *(uint32_t *)pos = htobe32(data);
}
/*!
* \brief Writes 6 bytes in wireformat.
*
- * The endian of the data is inverted.
- *
- * \todo Wrong assumption of endianness (issue #1558).
+ * The data are stored in network byte order (big endian).
*
* \param pos Position where to put the 4 bytes.
* \param data Data to put.
*/
static inline void knot_wire_write_u48(uint8_t *pos, uint64_t data)
{
- *(pos++) = (uint8_t)((data >> 40) & 0xff);
- *(pos++) = (uint8_t)((data >> 32) & 0xff);
- *(pos++) = (uint8_t)((data >> 24) & 0xff);
- *(pos++) = (uint8_t)((data >> 16) & 0xff);
- *(pos++) = (uint8_t)((data >> 8) & 0xff);
- *pos = (uint8_t)(data & 0xff);
+ uint64_t swapped = htobe64(data << 8);
+ memcpy((void *)pos, (uint8_t *)&swapped + 1, 6);
}
/*!
- * \brief Linear congruential generator.
+ * \brief Writes 8 bytes in wireformat.
+ *
+ * The data are stored in network byte order (big endian).
*
- * Simple pseudorandom generator for general purpose.
- * \warning Do not use for cryptography.
- * \return Random number <0, (size_t)~0>
+ * \param pos Position where to put the 8 bytes.
+ * \param data Data to put.
*/
-size_t knot_quick_rand();
+static inline void knot_wire_write_u64(uint8_t *pos, uint64_t data)
+{
+ *(uint64_t *)pos = htobe64(data);
+}
+/*!
+ * \brief Get random packet id.
+ */
uint16_t knot_random_id();
/*!
@@ -206,4 +193,3 @@ struct flock* knot_file_lock(short type, short whence);
#endif /* _KNOT_UTILS_H_ */
/*! @} */
-
diff --git a/src/libknot/util/wire.h b/src/libknot/util/wire.h
index 0a24ff1..e2f283d 100644
--- a/src/libknot/util/wire.h
+++ b/src/libknot/util/wire.h
@@ -886,8 +886,12 @@ static inline void knot_wire_flags_clear_ra(uint8_t *flags2)
*/
enum knot_wire_pointer_consts {
- /*! \brief DNS packet pointer designation (first two bits set to 1). */
- KNOT_WIRE_PTR = (uint8_t)0xc0U
+ /*! \brief DNS packet pointer designation (first two bits set to 1). */
+ KNOT_WIRE_PTR = (uint8_t)0xC0,
+ /*! \brief DNS packet minimal pointer (KNOT_WIRE_PTR + 1 zero byte). */
+ KNOT_WIRE_PTR_BASE = (uint16_t)0xC000,
+ /*! \brief DNS packet maximal offset (KNOT_WIRE_BASE complement). */
+ KNOT_WIRE_PTR_MAX = (uint16_t)0x3FFF
};
/*!
@@ -897,28 +901,31 @@ enum knot_wire_pointer_consts {
* \param ptr Relative position of the item to which the pointer should point in
* the wire format of the packet.
*/
-static inline void knot_wire_put_pointer(uint8_t *pos, size_t ptr)
+static inline void knot_wire_put_pointer(uint8_t *pos, uint16_t ptr)
{
- uint16_t p = ptr;
- knot_wire_write_u16(pos, p);
- assert((pos[0] & KNOT_WIRE_PTR) == 0);
- pos[0] |= KNOT_WIRE_PTR;
+ knot_wire_write_u16(pos, ptr); // Write pointer offset.
+ assert((pos[0] & KNOT_WIRE_PTR) == 0); // Check for maximal offset.
+ pos[0] |= KNOT_WIRE_PTR; // Add pointer mark.
}
static inline int knot_wire_is_pointer(const uint8_t *pos)
{
- return ((pos[0] & KNOT_WIRE_PTR) != 0);
+ return ((pos[0] & KNOT_WIRE_PTR) == KNOT_WIRE_PTR);
}
-static inline size_t knot_wire_get_pointer(const uint8_t *pos)
+static inline uint16_t knot_wire_get_pointer(const uint8_t *pos)
{
- /*! \todo memcpy() is not needed, may be directly assigned. */
- uint16_t p = 0;
- memcpy(&p, pos, 2);
- p &= ~KNOT_WIRE_PTR;
+ assert((pos[0] & KNOT_WIRE_PTR) == KNOT_WIRE_PTR); // Check pointer.
+ return (knot_wire_read_u16(pos) - KNOT_WIRE_PTR_BASE); // Return offset.
+}
- uint16_t p2 = knot_wire_read_u16((uint8_t *)&p);
- return p2;
+static inline uint8_t *knot_wire_next_label(uint8_t *lp, uint8_t *wire)
+{
+ lp = lp + (lp[0] + sizeof(uint8_t));
+ if (knot_wire_is_pointer(lp)) {
+ lp = wire + knot_wire_get_pointer(lp);
+ }
+ return lp;
}
#endif /* _KNOT_WIRE_H_ */
diff --git a/src/libknot/zone/dname-table.c b/src/libknot/zone/dname-table.c
deleted file mode 100644
index f86bb90..0000000
--- a/src/libknot/zone/dname-table.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stddef.h>
-
-#include "zone/dname-table.h"
-
-/*!< Tree functions. */
-TREE_DEFINE(dname_table_node, avl);
-
-struct knot_dname_table_fnc_data {
- void (*func)(knot_dname_t *dname, void *data);
- void *data;
-};
-
-static void knot_dname_table_apply(struct dname_table_node *node, void *data)
-{
- assert(data != NULL);
- assert(node != NULL);
- struct knot_dname_table_fnc_data *d =
- (struct knot_dname_table_fnc_data *)data;
- d->func(node->dname, d->data);
-}
-
-/*!
- * \brief Comparison function to be used with tree.
- *
- * \param n1 First dname to be compared.
- * \param n2 Second dname to be compared.
- *
- * \return strncmp of dname's wireformats.
- */
-static int compare_dname_table_nodes(struct dname_table_node *n1,
- struct dname_table_node *n2)
-{
- assert(n1 && n2);
- return (strncmp((char *)n1->dname->name, (char *)n2->dname->name,
- (n1->dname->size < n2->dname->size) ?
- (n1->dname->size):(n2->dname->size)));
-}
-
-/*!
- * \brief Deletes tree node along with its domain name.
- *
- * \param node Node to be deleted.
- * \param data If <> 0, dname in the node will be freed as well.
- */
-static void delete_dname_table_node(struct dname_table_node *node, void *data)
-{
- if ((ssize_t)data == 1) {
- knot_dname_release(node->dname);
- } else if ((ssize_t)data == 2) {
- knot_dname_free(&node->dname);
- }
-
- /*!< \todo it would be nice to set pointers to NULL. */
- free(node);
-}
-
-static void knot_dname_table_delete_subtree(struct dname_table_node *root)
-{
- if (root == NULL) {
- return;
- }
-
- knot_dname_table_delete_subtree(root->avl.avl_left);
- knot_dname_table_delete_subtree(root->avl.avl_right);
- free(root);
-}
-
-static int knot_dname_table_copy_node(const struct dname_table_node *from,
- struct dname_table_node **to)
-{
- if (from == NULL) {
- return KNOT_EOK;
- }
-
- *to = (struct dname_table_node *)
- malloc(sizeof(struct dname_table_node));
- if (*to == NULL) {
- return KNOT_ENOMEM;
- }
- memset(*to, 0, sizeof(struct dname_table_node));
-
- (*to)->dname = from->dname;
- knot_dname_retain((*to)->dname);
- (*to)->avl.avl_height = from->avl.avl_height;
-
- int ret = knot_dname_table_copy_node(from->avl.avl_left,
- &(*to)->avl.avl_left);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- ret = knot_dname_table_copy_node(from->avl.avl_right,
- &(*to)->avl.avl_right);
- if (ret != KNOT_EOK) {
- knot_dname_table_delete_subtree((*to)->avl.avl_left);
- (*to)->avl.avl_left = NULL;
- return ret;
- }
-
- return KNOT_EOK;
-}
-
-knot_dname_table_t *knot_dname_table_new()
-{
- knot_dname_table_t *ret = malloc(sizeof(knot_dname_table_t));
- CHECK_ALLOC_LOG(ret, NULL);
-
- ret->tree = malloc(sizeof(table_tree_t));
- if (ret->tree == NULL) {
- ERR_ALLOC_FAILED;
- free(ret);
- return NULL;
- }
-
- TREE_INIT(ret->tree, compare_dname_table_nodes);
-
- ret->id_counter = 1;
-
- return ret;
-}
-
-knot_dname_t *knot_dname_table_find_dname(const knot_dname_table_t *table,
- knot_dname_t *dname)
-{
- if (table == NULL || dname == NULL) {
- return NULL;
- }
-
- struct dname_table_node *node = NULL;
- struct dname_table_node sought;
- sought.dname = dname;
-
- node = TREE_FIND(table->tree, dname_table_node, avl, &sought);
-
- if (node == NULL) {
- return NULL;
- } else {
- /* Increase reference counter. */
- knot_dname_retain(node->dname);
-
- return node->dname;
- }
-}
-
-int knot_dname_table_add_dname(knot_dname_table_t *table,
- knot_dname_t *dname)
-{
- if (dname == NULL || table == NULL) {
- return KNOT_EINVAL;
- }
-
- /* Node for insertion has to be created */
- struct dname_table_node *node =
- malloc(sizeof(struct dname_table_node));
- CHECK_ALLOC_LOG(node, KNOT_ENOMEM);
-
- // convert the dname to lowercase
- knot_dname_to_lower(dname);
-
- node->dname = dname;
- node->avl.avl_height = 0;
- node->avl.avl_left = NULL;
- node->avl.avl_right = NULL;
-
- node->dname->id = table->id_counter++;
- assert(node->dname->id != 0);
-
- /* Increase reference counter. */
- knot_dname_retain(dname);
-
- TREE_INSERT(table->tree, dname_table_node, avl, node);
- return KNOT_EOK;
-}
-
-int knot_dname_table_add_dname_check(knot_dname_table_t *table,
- knot_dname_t **dname)
-{
- knot_dname_t *found_dname = NULL;
-
- if (table == NULL || dname == NULL || *dname == NULL) {
- return KNOT_EINVAL;
- }
-
- /* Fetch dname, need to release it later. */
- found_dname = knot_dname_table_find_dname(table ,*dname);
-
- if (!found_dname) {
- /* Store reference in table. */
- return knot_dname_table_add_dname(table, *dname);
- } else {
- /*! \todo Remove the check for equality. */
- if (found_dname != *dname) {
- /* Replace dname with found. */
- knot_dname_release(*dname);
- *dname = found_dname;
- return 1; /*! \todo Error code? */
-
- } else {
- /* If the dname is already in the table, there is already
- * a reference to it.
- */
- knot_dname_release(found_dname);
- }
- }
-
- return KNOT_EOK;
-}
-
-int knot_dname_table_shallow_copy(knot_dname_table_t *from,
- knot_dname_table_t *to)
-{
- to->id_counter = from->id_counter;
-
- if (to->tree == NULL) {
- to->tree = malloc(sizeof(table_tree_t));
- if (to->tree == NULL) {
- ERR_ALLOC_FAILED;
- return KNOT_ENOMEM;
- }
-
- TREE_INIT(to->tree, compare_dname_table_nodes);
- }
-
- return knot_dname_table_copy_node(from->tree->th_root,
- &to->tree->th_root);
-}
-
-void knot_dname_table_free(knot_dname_table_t **table)
-{
- if (table == NULL || *table == NULL) {
- return;
- }
-
- /* Walk the tree and free each node, but not the dnames. */
- TREE_POST_ORDER_APPLY((*table)->tree, dname_table_node, avl,
- delete_dname_table_node, 0);
-
- free((*table)->tree);
-
- free(*table);
- *table = NULL;
-}
-
-void knot_dname_table_deep_free(knot_dname_table_t **table)
-{
- if (table == NULL || *table == NULL) {
- return;
- }
-
- /* Walk the tree and free each node, but free the dnames. */
- TREE_POST_ORDER_APPLY((*table)->tree, dname_table_node, avl,
- delete_dname_table_node, (void *) 1);
-
- free((*table)->tree);
-
- free(*table);
- *table = NULL;
-}
-
-void knot_dname_table_destroy(knot_dname_table_t **table)
-{
- if (table == NULL || *table == NULL) {
- return;
- }
-
- /* Walk the tree and free each node, but free the dnames. */
- TREE_POST_ORDER_APPLY((*table)->tree, dname_table_node, avl,
- delete_dname_table_node, (void *) 2);
-
- free((*table)->tree);
-
- free(*table);
- *table = NULL;
-}
-
-void knot_dname_table_tree_inorder_apply(const knot_dname_table_t *table,
- void (*applied_function)(knot_dname_t *node,
- void *data),
- void *data)
-{
- struct knot_dname_table_fnc_data d;
- d.data = data;
- d.func = applied_function;
-
- TREE_FORWARD_APPLY(table->tree, dname_table_node, avl,
- knot_dname_table_apply, &d);
-}
-
-static void knot_dump_node_of_table(knot_dname_t *dname, void *data)
-{
- UNUSED(data);
- char *name = knot_dname_to_str(dname);
- fprintf(stderr, "%s (%p)\n", name, dname);
- free(name);
-}
-
-void knot_dname_table_dump(const knot_dname_table_t *table)
-{
- fprintf(stderr, "-------DNAME TABLE-------\n");
- knot_dname_table_tree_inorder_apply(table, knot_dump_node_of_table,
- NULL);
- fprintf(stderr, "-----END DNAME TABLE-----\n");
-}
-
diff --git a/src/libknot/zone/dname-table.h b/src/libknot/zone/dname-table.h
deleted file mode 100644
index 945b6de..0000000
--- a/src/libknot/zone/dname-table.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*!
- * \file dname-table.h
- *
- * \author Jan Kadlec <jan.kadlec.@nic.cz>
- *
- * \brief Structures representing dname table and functions for
- * manipulating these structures.
- *
- * \addtogroup libknot
- * @{
- */
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOT_DNAME_TABLE_H_
-#define _KNOT_DNAME_TABLE_H_
-
-#include <config.h>
-
-#include "common/tree.h"
-
-#include "dname.h"
-#include "common.h"
-
-
-/*!
- * \brief Structure encapsulating
- */
-struct dname_table_node {
- knot_dname_t *dname; /*!< Dname stored in node. */
- TREE_ENTRY(dname_table_node) avl; /*!< Tree variables. */
-};
-
-/*!
- * \brief Tree structure.
- */
-typedef TREE_HEAD(avl, dname_table_node) table_tree_t;
-
-/*!
- * \brief Structure holding tree together with dname ID counter.
- */
-struct knot_dname_table {
- unsigned int id_counter; /*!< ID counter (starts from 1) */
- table_tree_t *tree; /*!< AVL tree */
-};
-
-typedef struct knot_dname_table knot_dname_table_t;
-
-/*!
- * \brief Creates new empty domain name table.
- *
- * \retval Created table on success.
- * \retval NULL on memory error.
- */
-knot_dname_table_t *knot_dname_table_new();
-
-/*!
- * \brief Finds name in the domain name table.
- *
- * \note Reference count to dname will be incremented, caller is responsible
- * for releasing it.
- *
- * \param table Domain name table to be searched.
- * \param dname Dname to be searched.
- *
- * \retval Pointer to found dname when dname is present in the table.
- * \retval NULL when dname is not present.
- */
-knot_dname_t *knot_dname_table_find_dname(const knot_dname_table_t *table,
- knot_dname_t *dname);
-
-/*!
- * \brief Adds domain name to domain name table.
- *
- * \param table Domain name table to be added to.
- * \param dname Domain name to be added.
- *
- * \warning Function does not check for duplicates!
- *
- * \note This function encapsulates dname in a structure and saves it to a tree.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_ENOMEM when memory runs out.
- */
-int knot_dname_table_add_dname(knot_dname_table_t *table,
- knot_dname_t *dname);
-
-/*!
- * \brief Adds domain name to domain name table and checks for duplicates.
- *
- * \param table Domain name table to be added to.
- * \param dname Domain name to be added.
- *
- * \note This function encapsulates dname in a structure and saves it to a tree.
- * \note If a duplicate is found, \a dname is replaced by the name from table.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_ENOMEM when memory runs out.
- */
-int knot_dname_table_add_dname_check(knot_dname_table_t *table,
- knot_dname_t **dname);
-
-/*!
- * \brief Creates a shallow copy of the domain name table.
- *
- * Expects an existing knot_dname_table_t structure to be passed via \a to,
- * and fills it with the same data (domain names) as the original. Actual
- * tree nodes are created, but domain names are not copied (just referenced).
- *
- * \param from Original domain name table.
- * \param to Copy of the domain name table.
- */
-int knot_dname_table_shallow_copy(knot_dname_table_t *from,
- knot_dname_table_t *to);
-
-/*!
- * \brief Frees dname table without its nodes. Sets pointer to NULL.
- *
- * \param table Table to be freed.
- */
-void knot_dname_table_free(knot_dname_table_t **table);
-
-/*!
- * \brief Frees dname table and all its nodes (and release dnames in the nodes)
- * Sets pointer to NULL.
- *
- * \param table Table to be freed.
- */
-void knot_dname_table_deep_free(knot_dname_table_t **table);
-
-/*!
- * \brief Frees dname table and all its nodes (including dnames in the nodes)
- * Sets pointer to NULL.
- *
- * \param table Table to be freed.
- */
-void knot_dname_table_destroy(knot_dname_table_t **table);
-
-/*!
- * \brief Encapsulation of domain name table tree traversal function.
- *
- * \param table Table containing tree to be traversed.
- * \param applied_function Function to be used to process nodes.
- * \param data Data to be passed to processing function.
- */
-void knot_dname_table_tree_inorder_apply(const knot_dname_table_t *table,
- void (*applied_function)(knot_dname_t *dname,
- void *data),
- void *data);
-
-
-/*!
- * \brief Dumps dname table to stderr.
- *
- * \param table Table to be dumped.
- */
-void knot_dname_table_dump(const knot_dname_table_t *table);
-
-
-#endif // _KNOT_DNAME_TABLE_H_
-
-/*! @} */
-
diff --git a/src/libknot/zone/node.c b/src/libknot/zone/node.c
index eca4abc..5ebdb0e 100644
--- a/src/libknot/zone/node.c
+++ b/src/libknot/zone/node.c
@@ -25,7 +25,6 @@
#include "zone/node.h"
#include "rrset.h"
#include "common/skip-list.h"
-#include "common/tree.h"
#include "util/debug.h"
/*----------------------------------------------------------------------------*/
@@ -127,28 +126,6 @@ static inline uint8_t knot_node_flags_get_empty(uint8_t flags)
}
/*----------------------------------------------------------------------------*/
-/*!
- * \brief Compares the two keys as RR types.
- *
- * \note This function may be used in data structures requiring generic
- * comparation function.
- *
- * \param key1 First RR type.
- * \param key2 Second RR type.
- *
- * \retval 0 if \a key1 is equal to \a key2.
- * \retval < 0 if \a key1 is lower than \a key2.
- * \retval > 0 if \a key1 is higher than \a key2.
- */
-static int compare_rrset_types(void *rr1, void *rr2)
-{
- knot_rrset_t *rrset1 = (knot_rrset_t *)rr1;
- knot_rrset_t *rrset2 = (knot_rrset_t *)rr2;
- return ((rrset1->type > rrset2->type) ? 1 :
- (rrset1->type == rrset2->type) ? 0 : -1);
-}
-
-/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -165,58 +142,69 @@ knot_node_t *knot_node_new(knot_dname_t *owner, knot_node_t *parent,
knot_dname_retain(owner);
ret->owner = owner;
knot_node_set_parent(ret, parent);
- ret->rrset_tree = gen_tree_new(compare_rrset_types);
+ ret->rrset_tree = NULL;
ret->flags = flags;
-
+
assert(ret->children == 0);
return ret;
}
-/*----------------------------------------------------------------------------*/
-/*! \todo Consider replacing rrset_merge() with rrset_merge_no_dupl(). Currently
- * this function is never called with merge=1, so it's not a problem,
- * but it may be in the future.
- */
-int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
- int merge)
+
+int knot_node_add_rrset_no_merge(knot_node_t *node, knot_rrset_t *rrset)
{
if (node == NULL) {
return KNOT_EINVAL;
}
- int ret = 0;
+ size_t nlen = (node->rrset_count + 1) * sizeof(knot_rrset_t*);
+ void *p = realloc(node->rrset_tree, nlen);
+ if (p == NULL) {
+ return KNOT_ENOMEM;
+ }
+ node->rrset_tree = p;
+ node->rrset_tree[node->rrset_count] = rrset;
+ ++node->rrset_count;
+ return KNOT_EOK;
+}
- if ((ret = (gen_tree_add(node->rrset_tree, rrset,
- (merge) ? knot_rrset_merge : NULL))) < 0) {
- dbg_node("Failed to add rrset to node->rrset_tree.\n");
- return KNOT_ERROR;
+int knot_node_add_rrset_replace(knot_node_t *node, knot_rrset_t *rrset)
+{
+ if (node == NULL) {
+ return KNOT_EINVAL;
}
- if (ret >= 0) {
- node->rrset_count += (ret > 0 ? 0 : 1);
- return ret;
- } else {
- return KNOT_ERROR;
+ for (uint16_t i = 0; i < node->rrset_count; ++i) {
+ if (node->rrset_tree[i]->type == rrset->type) {
+ node->rrset_tree[i] = rrset;
+ }
}
+
+ return knot_node_add_rrset_no_merge(node, rrset);
}
-int knot_node_add_rrset_no_dupl(knot_node_t *node, knot_rrset_t *rrset)
+int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset)
{
- int ret = 0;
-
- if ((ret = (gen_tree_add(node->rrset_tree, rrset,
- knot_rrset_merge_no_dupl))) < 0) {
- dbg_node("Failed to add rrset to node->rrset_tree.\n");
- return KNOT_ERROR;
+ if (node == NULL) {
+ return KNOT_EINVAL;
}
- if (ret >= 0) {
- node->rrset_count += (ret > 0 ? 0 : 1);
- return ret;
- } else {
- return KNOT_ERROR;
+ for (uint16_t i = 0; i < node->rrset_count; ++i) {
+ if (node->rrset_tree[i]->type == rrset->type) {
+ int merged, deleted_rrs;
+ int ret = knot_rrset_merge_no_dupl(node->rrset_tree[i],
+ rrset, &merged, &deleted_rrs);
+ if (ret != KNOT_EOK) {
+ return ret;
+ } else if (merged || deleted_rrs) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
}
+
+ return knot_node_add_rrset_no_merge(node, rrset);
}
/*----------------------------------------------------------------------------*/
@@ -224,14 +212,7 @@ int knot_node_add_rrset_no_dupl(knot_node_t *node, knot_rrset_t *rrset)
const knot_rrset_t *knot_node_rrset(const knot_node_t *node,
uint16_t type)
{
- if (node == NULL) {
- return NULL;
- }
-
- assert(node->rrset_tree != NULL);
- knot_rrset_t rrset;
- rrset.type = type;
- return (const knot_rrset_t *)gen_tree_find(node->rrset_tree, &rrset);
+ return knot_node_get_rrset(node, type);
}
/*----------------------------------------------------------------------------*/
@@ -242,9 +223,14 @@ knot_rrset_t *knot_node_get_rrset(const knot_node_t *node, uint16_t type)
return NULL;
}
- knot_rrset_t rrset;
- rrset.type = type;
- return (knot_rrset_t *)gen_tree_find(node->rrset_tree, &rrset);
+ knot_rrset_t **rrs = node->rrset_tree;
+ for (uint16_t i = 0; i < node->rrset_count; ++i) {
+ if (rrs[i]->type == type) {
+ return rrs[i];
+ }
+ }
+
+ return NULL;
}
/*----------------------------------------------------------------------------*/
@@ -255,15 +241,24 @@ knot_rrset_t *knot_node_remove_rrset(knot_node_t *node, uint16_t type)
return NULL;
}
- knot_rrset_t dummy_rrset;
- dummy_rrset.type = type;
- knot_rrset_t *rrset =
- (knot_rrset_t *)gen_tree_find(node->rrset_tree, &dummy_rrset);
- if (rrset != NULL) {
- gen_tree_remove(node->rrset_tree, rrset);
- node->rrset_count--;
+ uint16_t i = 0;
+ knot_rrset_t *ret = NULL;
+ knot_rrset_t **rrs = node->rrset_tree;
+ for (; i < node->rrset_count && ret == NULL; ++i) {
+ if (rrs[i]->type == type) {
+ ret = rrs[i];
+ memmove(rrs + i, rrs + i + 1, (node->rrset_count - i - 1) * sizeof(knot_rrset_t *));
+ --node->rrset_count;
+ }
}
- return rrset;
+
+ /*!< \todo I've added this to fix a leak, but probably this wasn't the cause. Remove once tests are availabe. */
+ void *tmp = realloc(node->rrset_tree,
+ node->rrset_count * sizeof(knot_rrset_t *));
+ assert(tmp || node->rrset_count == 0); //Realloc to smaller memory, if it fails, something is really odd.
+ node->rrset_tree = tmp;
+
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -275,9 +270,7 @@ void knot_node_remove_all_rrsets(knot_node_t *node)
}
// remove RRSets but do not delete them
- gen_tree_clear(node->rrset_tree);
node->rrset_count = 0;
-
}
/*----------------------------------------------------------------------------*/
@@ -301,40 +294,19 @@ struct knot_node_save_rrset_arg {
/*----------------------------------------------------------------------------*/
-static void save_rrset_to_array(void *node, void *data)
-{
- struct knot_node_save_rrset_arg *args =
- (struct knot_node_save_rrset_arg *)data;
- knot_rrset_t *rrset = (knot_rrset_t *)node;
-
- if (args->count > args->max_count) {
- ++args->count;
- return;
- }
-
- args->array[args->count++] = rrset;
-}
-
-/*----------------------------------------------------------------------------*/
-
knot_rrset_t **knot_node_get_rrsets(const knot_node_t *node)
{
if (node == NULL || node->rrset_count == 0) {
return NULL;
}
- knot_rrset_t **rrsets = (knot_rrset_t **)malloc(
- node->rrset_count * sizeof(knot_rrset_t *));
- CHECK_ALLOC_LOG(rrsets, NULL);
- struct knot_node_save_rrset_arg args;
- args.array = rrsets;
- args.count = 0;
- args.max_count = node->rrset_count;
- gen_tree_apply_inorder(node->rrset_tree, save_rrset_to_array, &args);
-
- assert(args.count == node->rrset_count);
+ size_t rrlen = node->rrset_count * sizeof(knot_rrset_t*);
+ knot_rrset_t **cpy = malloc(rrlen);
+ if (cpy != NULL) {
+ memcpy(cpy, node->rrset_tree, rrlen);
+ }
- return rrsets;
+ return cpy;
}
/*----------------------------------------------------------------------------*/
@@ -348,31 +320,21 @@ const knot_rrset_t **knot_node_rrsets(const knot_node_t *node)
return (const knot_rrset_t **)knot_node_get_rrsets(node);
}
-/*----------------------------------------------------------------------------*/
-
-static void count_rrsets(void *node, void *data)
-{
- assert(node != NULL);
- assert(data != NULL);
-
- int *count = (int *)data;
- ++(*count);
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_node_count_rrsets(const knot_node_t *node)
+knot_rrset_t **knot_node_get_rrsets_no_copy(const knot_node_t *node)
{
if (node == NULL) {
- return KNOT_EINVAL;
+ return NULL;
}
- int count = 0;
- gen_tree_apply_inorder(node->rrset_tree, count_rrsets, (void *)&count);
+ return node->rrset_tree;
+}
- return count;
+const knot_rrset_t **knot_node_rrsets_no_copy(const knot_node_t *node)
+{
+ return (const knot_rrset_t **)knot_node_get_rrsets_no_copy(node);
}
+
/*----------------------------------------------------------------------------*/
const knot_node_t *knot_node_parent(const knot_node_t *node)
@@ -409,7 +371,7 @@ void knot_node_set_parent(knot_node_t *node, knot_node_t *parent)
}
// set the parent
node->parent = parent;
-
+
// increase the count of children of the new parent
if (parent != NULL) {
++parent->children;
@@ -445,7 +407,7 @@ knot_node_t *knot_node_get_previous(const knot_node_t *node)
if (node == NULL) {
return NULL;
}
-
+
return node->prev;
}
@@ -467,7 +429,7 @@ knot_node_t *knot_node_get_nsec3_node(const knot_node_t *node)
if (node == NULL) {
return NULL;
}
-
+
return node->nsec3_node;
}
@@ -491,9 +453,6 @@ void knot_node_set_nsec3_node(knot_node_t *node, knot_node_t *nsec3_node)
}
node->nsec3_node = nsec3_node;
- if (nsec3_node != NULL) {
- nsec3_node->nsec3_referer = node;
- }
}
/*----------------------------------------------------------------------------*/
@@ -638,8 +597,6 @@ void knot_node_update_refs(knot_node_t *node)
knot_node_update_ref(&node->wildcard_child);
// reference to NSEC3 node
knot_node_update_ref(&node->nsec3_node);
- // reference to NSEC3 referrer
- knot_node_update_ref(&node->nsec3_referer);
}
/*----------------------------------------------------------------------------*/
@@ -725,29 +682,16 @@ void knot_node_set_empty(knot_node_t *node)
/*----------------------------------------------------------------------------*/
-static void knot_node_free_rrsets_from_tree(void *item, void *data)
-{
- if (item == NULL) {
- return;
- }
-
- knot_rrset_t *rrset = (knot_rrset_t *)(item);
- knot_rrset_deep_free(&rrset, 0, 1, *((int *)data));
-}
-
-/*----------------------------------------------------------------------------*/
-
void knot_node_free_rrsets(knot_node_t *node, int free_rdata_dnames)
{
if (node == NULL) {
return;
}
- char *name = knot_dname_to_str(node->owner);
- free(name);
-
- gen_tree_destroy(&node->rrset_tree, knot_node_free_rrsets_from_tree,
- (void *)&free_rdata_dnames);
+ knot_rrset_t **rrs = node->rrset_tree;
+ for (uint16_t i = 0; i < node->rrset_count; ++i) {
+ knot_rrset_deep_free(&(rrs[i]), 1, free_rdata_dnames);
+ }
}
/*----------------------------------------------------------------------------*/
@@ -757,12 +701,14 @@ void knot_node_free(knot_node_t **node)
if (node == NULL || *node == NULL) {
return;
}
-
+
dbg_node_detail("Freeing node: %p\n", *node);
if ((*node)->rrset_tree != NULL) {
dbg_node_detail("Freeing RRSets.\n");
- gen_tree_destroy(&(*node)->rrset_tree, NULL, NULL);
+ free((*node)->rrset_tree);
+ (*node)->rrset_tree = NULL;
+ (*node)->rrset_count = 0;
}
// set owner's node pointer to NULL, but only if the 'node' does
@@ -772,7 +718,6 @@ void knot_node_free(knot_node_t **node)
knot_dname_set_node((*node)->owner, NULL);
}
- dbg_node_detail("Releasing owner.\n");
knot_dname_release((*node)->owner);
free(*node);
@@ -804,25 +749,107 @@ int knot_node_shallow_copy(const knot_node_t *from, knot_node_t **to)
return KNOT_ENOMEM;
}
- // set the parent by hand, so that the children count is not affected
- (*to)->parent = from->parent;
-
- /* Free old rrset_tree, as it will be replaced by shallow copy. */
- gen_tree_destroy(&(*to)->rrset_tree, 0, 0);
-
- // copy references
- // do not use the API function to set parent, so that children count
+ // copy references
+ // do not use the API function to set parent, so that children count
// is not changed
memcpy(*to, from, sizeof(knot_node_t));
// copy RRSets
- (*to)->rrset_tree = gen_tree_shallow_copy(from->rrset_tree);
-
+ size_t rrlen = sizeof(knot_rrset_t*) * from->rrset_count;
+ (*to)->rrset_tree = malloc(rrlen);
if ((*to)->rrset_tree == NULL) {
free(*to);
*to = NULL;
return KNOT_ENOMEM;
}
+ memcpy((*to)->rrset_tree, from->rrset_tree, rrlen);
return KNOT_EOK;
}
+
+//const knot_node_t *knot_node_current(const knot_node_t *node)
+//{
+// if (node == NULL || node->zone == NULL
+// || knot_zone_contents(node->zone) == NULL) {
+// return node;
+// }
+
+// int new_gen = knot_node_zone_gen_is_new(node);
+// int old_gen = knot_node_zone_gen_is_old(node);
+//// short ver = knot_node_zone_generation(node);
+
+// if (old_gen && knot_node_is_new(node)) {
+// return NULL;
+// } else if (new_gen && knot_node_is_old(node)) {
+// assert(node->new_node != NULL);
+// return node->new_node;
+// }
+// return node;
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//knot_node_t *knot_node_get_current(knot_node_t *node)
+//{
+// if (node == NULL || node->zone == NULL
+// || knot_zone_contents(node->zone) == NULL) {
+// return node;
+// }
+
+// int new_gen = knot_node_zone_gen_is_new(node);
+// int old_gen = knot_node_zone_gen_is_old(node);
+//// short ver = knot_node_zone_generation(node);
+
+// if (old_gen && knot_node_is_new(node)) {
+// return NULL;
+// } else if (new_gen && knot_node_is_old(node)) {
+// assert(node->new_node != NULL);
+// return node->new_node;
+// }
+
+// assert((old_gen && knot_node_is_old(node))
+// || (new_gen && knot_node_is_new(node))
+// || (!old_gen && !new_gen));
+
+// return node;
+//}
+
+//int knot_node_is_new(const knot_node_t *node)
+//{
+// return knot_node_flags_get_new(node->flags);
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//int knot_node_is_old(const knot_node_t *node)
+//{
+// return knot_node_flags_get_old(node->flags);
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//void knot_node_set_new(knot_node_t *node)
+//{
+// knot_node_flags_set_new(&node->flags);
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//void knot_node_set_old(knot_node_t *node)
+//{
+// knot_node_flags_set_old(&node->flags);
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//void knot_node_clear_new(knot_node_t *node)
+//{
+// knot_node_flags_clear_new(&node->flags);
+//}
+
+///*----------------------------------------------------------------------------*/
+
+//void knot_node_clear_old(knot_node_t *node)
+//{
+// knot_node_flags_clear_old(&node->flags);
+//}
diff --git a/src/libknot/zone/node.h b/src/libknot/zone/node.h
index 4e0b2c4..a244952 100644
--- a/src/libknot/zone/node.h
+++ b/src/libknot/zone/node.h
@@ -31,8 +31,6 @@
#include "dname.h"
#include "common/skip-list.h"
#include "rrset.h"
-#include "common/tree.h"
-#include "common/general-tree.h"
struct knot_zone;
@@ -48,7 +46,7 @@ struct knot_node {
struct knot_node *parent; /*!< Parent node in the name hierarchy. */
/*! \brief Type-ordered list of RRSets belonging to this node. */
- general_tree_t *rrset_tree;
+ knot_rrset_t **rrset_tree;
/*! \brief Wildcard node being the direct descendant of this node. */
struct knot_node *wildcard_child;
@@ -70,15 +68,13 @@ struct knot_node {
*/
struct knot_node *nsec3_node;
- struct knot_node *nsec3_referer;
-
const struct knot_zone *zone;
struct knot_node *new_node;
-
+
unsigned int children;
- unsigned short rrset_count; /*!< Number of RRSets stored in the node. */
+ uint16_t rrset_count; /*!< Number of RRSets stored in the node. */
/*!
* \brief Various flags.
@@ -134,10 +130,11 @@ knot_node_t *knot_node_new(knot_dname_t *owner, knot_node_t *parent,
* \retval KNOT_EOK on success.
* \retval KNOT_ERROR if the RRSet could not be inserted.
*/
-int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
- int merge);
+int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset);
+
+int knot_node_add_rrset_replace(knot_node_t *node, knot_rrset_t *rrset);
-int knot_node_add_rrset_no_dupl(knot_node_t *node, knot_rrset_t *rrset);
+int knot_node_add_rrset_no_merge(knot_node_t *node, knot_rrset_t *rrset);
/*!
* \brief Returns the RRSet of the given type from the node.
@@ -195,6 +192,8 @@ knot_rrset_t **knot_node_get_rrsets(const knot_node_t *node);
* \return Newly allocated array of RRSets or NULL if an error occured.
*/
const knot_rrset_t **knot_node_rrsets(const knot_node_t *node);
+const knot_rrset_t **knot_node_rrsets_no_copy(const knot_node_t *node);
+knot_rrset_t **knot_node_get_rrsets_no_copy(const knot_node_t *node);
int knot_node_count_rrsets(const knot_node_t *node);
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c
index 90aee0d..ff1a1d4 100644
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -14,13 +14,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
#include "zone/zone-contents.h"
#include "util/debug.h"
+#include "libknot/rrset.h"
#include "common/base32hex.h"
-/*! \todo XXX TODO FIXME remove once testing is done. */
-#include "zcompile/zcompile.h"
+#include "common/descriptor.h"
+#include "common/hattrie/hat-trie.h"
+#include "libknot/zone/zone-tree.h"
#include "consts.h"
/*----------------------------------------------------------------------------*/
@@ -36,6 +39,7 @@ typedef struct {
knot_node_t *first_node;
knot_zone_contents_t *zone;
knot_node_t *previous_node;
+ hattrie_t *lookup_tree;
int err;
} knot_zone_adjust_arg_t;
@@ -50,7 +54,7 @@ const uint8_t KNOT_ZONE_FLAGS_ANY = 4; /* 00000100 */
/*----------------------------------------------------------------------------*/
-static void knot_zone_tree_apply(knot_zone_tree_node_t *node,
+static void tree_apply_cb(knot_node_t **node,
void *data)
{
if (node == NULL || data == NULL) {
@@ -58,7 +62,7 @@ static void knot_zone_tree_apply(knot_zone_tree_node_t *node,
}
knot_zone_tree_func_t *f = (knot_zone_tree_func_t *)data;
- f->func(node->node, f->data);
+ f->func(*node, f->data);
}
/*----------------------------------------------------------------------------*/
@@ -87,13 +91,13 @@ static int knot_zone_contents_check_node(
assert(contents->apex != NULL);
if (!knot_dname_is_subdomain(node->owner,
- knot_node_owner(contents->apex))) {
+ knot_node_owner(contents->apex))) {
dbg_zone_exec(
char *node_owner = knot_dname_to_str(knot_node_owner(node));
char *apex_owner = knot_dname_to_str(contents->apex->owner);
dbg_zone("zone: Trying to insert foreign node to a "
- "zone. Node owner: %s, zone apex: %s\n",
- node_owner, apex_owner);
+ "zone. Node owner: %s, zone apex: %s\n",
+ node_owner, apex_owner);
free(node_owner);
free(apex_owner);
);
@@ -112,166 +116,14 @@ dbg_zone_exec(
* \param data Unused parameter.
*/
static void knot_zone_contents_destroy_node_rrsets_from_tree(
- knot_zone_tree_node_t *tnode, void *data)
+ knot_node_t **tnode, void *data)
{
assert(tnode != NULL);
- assert(tnode->node != NULL);
+ if (*tnode == NULL) return; /* non-existent node */
int free_rdata_dnames = (int)((intptr_t)data);
- knot_node_free_rrsets(tnode->node, free_rdata_dnames);
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Destroys node owner.
- *
- * This function is designed to be used in the tree-iterating functions.
- *
- * \param node Node to destroy the owner of.
- * \param data Unused parameter.
- */
-static void knot_zone_contents_destroy_node_owner_from_tree(
- knot_zone_tree_node_t *tnode, void *data)
-{
- assert(tnode != NULL);
- assert(tnode->node != NULL);
-
- UNUSED(data);
- /*!< \todo change completely! */
- knot_node_free(&tnode->node);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int knot_zone_contents_dnames_from_rdata_to_table(
- knot_dname_table_t *table, knot_rdata_t *rdata,
- knot_rrtype_descriptor_t *d)
-{
- unsigned int count = knot_rdata_item_count(rdata);
- int rc = 0;
- if (d->fixed_items) {
- assert(count <= d->length);
- }
- // for each RDATA item
- for (unsigned int j = 0; j < count; ++j) {
- if (d->wireformat[j]
- == KNOT_RDATA_WF_COMPRESSED_DNAME
- || d->wireformat[j]
- == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || d->wireformat[j]
- == KNOT_RDATA_WF_LITERAL_DNAME) {
- rc = knot_dname_table_add_dname_check(table,
- &knot_rdata_get_item(rdata, j)->dname);
- if (rc < 0) {
- dbg_zone("Error: %s\n", knot_strerror(rc));
- return rc;
- }
- }
- }
-
- dbg_zone_detail("RDATA OK.\n");
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int knot_zone_contents_dnames_from_rrset_to_table(
- knot_dname_table_t *table, knot_rrset_t *rrset, int replace_owner,
- knot_dname_t *owner)
-{
- assert(table != NULL && rrset != NULL && owner != NULL);
-
-dbg_zone_exec_detail(
- char *name = knot_dname_to_str(knot_rrset_owner(rrset));
- dbg_zone_detail("Putting dnames from RRSet to table: owner: (%p) %s,"
- " type: %s\n", knot_rrset_owner(rrset),
- name, knot_rrtype_to_string(
- knot_rrset_type(rrset)));
- free(name);
-);
-
- if (replace_owner) {
- // discard the old owner and replace it with the new
- knot_rrset_set_owner(rrset, owner);
- }
- dbg_zone_detail("RRSet owner: %p\n", rrset->owner);
-
- knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(
- knot_rrset_type(rrset));
- if (desc == NULL) {
- // not recognized RR type, ignore
- dbg_zone("RRSet type not recognized.\n");
- return KNOT_EOK;
- }
- // for each RDATA in RRSet
- knot_rdata_t *rdata = knot_rrset_get_rdata(rrset);
- while (rdata != NULL) {
- int rc = knot_zone_contents_dnames_from_rdata_to_table(table,
- rdata, desc);
- if (rc != KNOT_EOK) {
- return rc;
- }
-
- rdata = knot_rrset_rdata_get_next(rrset, rdata);
- }
-
- dbg_zone("RRSet OK.\n");
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int knot_zone_contents_dnames_from_node_to_table(
- knot_dname_table_t *table, knot_node_t *node)
-{
- /*
- * Assuming that all the RRSets have the same owner as the node.
- */
-
- // insert owner
- char *name = knot_dname_to_str(node->owner);
- dbg_zone_detail("Node owner before inserting to dname table: %p.\n",
- node->owner);
- dbg_zone_detail("Node owner before inserting to dname table: %s.\n",
- name);
- free(name);
- //knot_dname_t *old_owner = node->owner;
- int rc = knot_dname_table_add_dname_check(table, &node->owner);
- if (rc < 0) {
- dbg_zone("Failed to add dname to dname table.\n");
- return rc;
- }
- int replace_owner = (rc > 0);
-
-dbg_zone_exec_detail(
- name = knot_dname_to_str(node->owner);
- dbg_zone_detail("Node owner after inserting to dname table: %p (%s).\n",
- node->owner, name);
- free(name);
-);
-
- knot_rrset_t **rrsets = knot_node_get_rrsets(node);
- // for each RRSet
- for (int i = 0; i < knot_node_rrset_count(node); ++i) {
- dbg_zone_detail("Inserting RRSets from node to table.\n");
- rc = knot_zone_contents_dnames_from_rrset_to_table(table,
- rrsets[i], replace_owner, node->owner);
-
- if (rc == KNOT_EOK && knot_rrset_rrsigs(rrsets[i]) != NULL) {
- rc = knot_zone_contents_dnames_from_rrset_to_table(
- table, knot_rrset_get_rrsigs(rrsets[i]),
- replace_owner, node->owner);
- }
-
- if (rc != KNOT_EOK) {
- return rc;
- }
- }
-
- free(rrsets);
-
- dbg_zone("Node OK\n");
- return KNOT_EOK;
+ knot_node_free_rrsets(*tnode, free_rdata_dnames);
+ knot_node_free(tnode);
}
/*----------------------------------------------------------------------------*/
@@ -286,7 +138,7 @@ static const knot_node_t *knot_zone_contents_find_wildcard_child(
CHECK_ALLOC(tmp, NULL);
knot_dname_t *wildcard = knot_dname_cat(tmp, knot_node_owner(
- closest_encloser));
+ closest_encloser));
if (wildcard == NULL) {
free(tmp);
return NULL;
@@ -298,14 +150,14 @@ dbg_zone_exec_detail(
char *name = knot_dname_to_str(knot_node_owner(closest_encloser));
char *name2 = knot_dname_to_str(wildcard);
dbg_zone_detail("Searching for wildcard child of %s (%s)\n", name,
- name2);
+ name2);
free(name);
free(name2);
);
const knot_node_t *found = NULL, *ce = NULL, *prev = NULL;
int ret = knot_zone_contents_find_dname(zone, wildcard, &found, &ce,
- &prev);
+ &prev);
knot_dname_free(&wildcard);
@@ -316,6 +168,29 @@ dbg_zone_exec_detail(
}
}
+void knot_zone_contents_insert_dname_into_table(knot_dname_t **in_dname,
+ hattrie_t *lookup_tree)
+{
+ if (lookup_tree == NULL) {
+ /* = Do not check duplicates. */
+ return;
+ }
+ assert(in_dname && *in_dname);
+ /* First thing - make sure dname is not duplicated. */
+ knot_dname_t *found_dname = hattrie_get_dname(lookup_tree, *in_dname);
+ if (found_dname != NULL && found_dname != *in_dname) {
+ /* Duplicate. */
+ knot_dname_release(*in_dname);
+ knot_dname_retain(found_dname);
+ *in_dname = found_dname;
+ } else if (found_dname == NULL) {
+ /* Into the tree it goes. */
+ hattrie_insert_dname(lookup_tree, *in_dname);
+ } else {
+ assert(found_dname == *in_dname);
+ }
+}
+
/*----------------------------------------------------------------------------*/
/*!
* \brief Adjusts one RDATA item by replacing domain name by one present in the
@@ -333,49 +208,48 @@ dbg_zone_exec_detail(
* \param zone Zone to which the RDATA belongs.
* \param pos Position of the RDATA item in the RDATA.
*/
-static void knot_zone_contents_adjust_rdata_item(knot_rdata_t *rdata,
- knot_zone_contents_t *zone,
- knot_node_t *node, int pos)
-{
- const knot_rdata_item_t *dname_item = knot_rdata_item(rdata, pos);
-
- assert(dname_item);
-
- if (dname_item != NULL) {
- knot_dname_t *dname = dname_item->dname;
-
- /*
- * The case when dname.node is already set is handled here.
- * No use to check it later.
- */
- if (knot_dname_node(dname) != NULL
- || !knot_dname_is_subdomain(dname, knot_node_owner(
- knot_zone_contents_apex(zone)))) {
- // The name's node is either already set
- // or the name does not belong to the zone
- dbg_zone_detail("Name's (%p) node either set or the name"
- "does not belong to the zone (%p).\n",
- dname, knot_dname_node(dname));
- return;
- }
+static void knot_zone_contents_adjust_rdata_dname(knot_zone_contents_t *zone,
+ hattrie_t *lookup_tree,
+ knot_node_t *node,
+ knot_dname_t **in_dname)
+{
+// const knot_node_t *old_dname_node = (*in_dname)->node;
+ knot_zone_contents_insert_dname_into_table(in_dname, lookup_tree);
+// assert((*in_dname)->node == old_dname_node || old_dname_node == NULL);
- const knot_node_t *n = NULL;
- const knot_node_t *closest_encloser = NULL;
- const knot_node_t *prev = NULL;
+ knot_dname_t *dname = *in_dname;
+ /*
+ * The case when dname.node is already set is handled here.
+ * No use to check it later.
+ */
+ if (knot_dname_node(dname) != NULL
+ || !knot_dname_is_subdomain(dname, knot_node_owner(
+ knot_zone_contents_apex(zone)))) {
+ // The name's node is either already set
+ // or the name does not belong to the zone
+ dbg_zone_detail("Name's node either set or the name "
+ "does not belong to the zone (%p).\n",
+ knot_dname_node(dname));
+ return;
+ }
- int ret = knot_zone_contents_find_dname(zone, dname, &n,
- &closest_encloser, &prev);
+ const knot_node_t *n = NULL;
+ const knot_node_t *closest_encloser = NULL;
+ const knot_node_t *prev = NULL;
- if (ret == KNOT_EINVAL || ret == KNOT_EBADZONE) {
- // TODO: do some cleanup if needed
- dbg_zone_detail("Failed to find the name in zone: %s\n",
- knot_strerror(ret));
- return;
- }
+ int ret = knot_zone_contents_find_dname(zone, dname, &n,
+ &closest_encloser, &prev);
- assert(ret != KNOT_ZONE_NAME_FOUND || n == closest_encloser);
+ if (ret == KNOT_EINVAL || ret == KNOT_EBADZONE) {
+ // TODO: do some cleanup if needed
+ dbg_zone_detail("Failed to find the name in zone: %s\n",
+ knot_strerror(ret));
+ return;
+ }
- if (ret != KNOT_ZONE_NAME_FOUND && (closest_encloser != NULL)) {
+ assert(ret != KNOT_ZONE_NAME_FOUND || n == closest_encloser);
+
+ if (ret != KNOT_ZONE_NAME_FOUND && (closest_encloser != NULL)) {
/*!
* \note There is no need to set closer encloser to the
* name. We may find the possible wildcard child
@@ -388,57 +262,22 @@ static void knot_zone_contents_adjust_rdata_item(knot_rdata_t *rdata,
dbg_zone_verb("Trying to find wildcard child.\n");
n = knot_zone_contents_find_wildcard_child(zone,
- closest_encloser);
+ closest_encloser);
if (n != NULL) {
knot_dname_set_node(dname, (knot_node_t *)n);
dbg_zone_exec_detail(
char *name = knot_dname_to_str(
- knot_node_owner(n));
+ knot_node_owner(n));
char *name2 = knot_dname_to_str(dname);
dbg_zone_detail("Set wildcard node %s "
- "to RDATA dname %s.\n",
- name, name2);
+ "to RDATA dname %s.\n",
+ name, name2);
free(name);
free(name2);
);
}
- }
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int knot_zone_contents_adjust_rdata(knot_rdata_t *rdata,
- knot_rrtype_descriptor_t *desc,
- knot_zone_contents_t *zone,
- knot_node_t *node)
-{
- for (int i = 0; i < rdata->count; ++i) {
- if (desc->wireformat[i]
- == KNOT_RDATA_WF_COMPRESSED_DNAME
- || desc->wireformat[i]
- == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || desc->wireformat[i]
- == KNOT_RDATA_WF_LITERAL_DNAME) {
- dbg_zone_detail("Adjusting domain name at position %d"
- " of the RDATA\n", i);
- knot_zone_contents_adjust_rdata_item(rdata, zone, node,
- i);
- }
- }
-
- /*
- * DS digest length check (#2050).
- */
- int ret;
- if (desc->type == KNOT_RRTYPE_DS
- && (ret = knot_rdata_ds_check(rdata)) != KNOT_EOK) {
- dbg_zone("DS RDATA check failed: %s\n", knot_strerror(ret));
- return KNOT_EMALF;
}
-
- return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -453,51 +292,18 @@ static int knot_zone_contents_adjust_rdata(knot_rdata_t *rdata,
* \param rrset RRSet to adjust RDATA in.
* \param zone Zone to which the RRSet belongs.
*/
-static int knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
- knot_zone_contents_t *zone,
- knot_node_t *node)
+static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
+ hattrie_t *lookup_tree,
+ knot_zone_contents_t *zone,
+ knot_node_t *node)
{
- uint16_t type = knot_rrset_type(rrset);
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- assert(desc);
-
- knot_rdata_t *rdata_first = knot_rrset_get_rdata(rrset);
- knot_rdata_t *rdata = rdata_first;
-
- if (rdata == NULL) {
- return KNOT_EOK;
- }
-
- int i = 1;
- int ret;
- while (rdata->next != rdata_first) {
-dbg_zone_exec_detail(
- char *name = knot_dname_to_str(knot_rrset_owner(rrset));
- dbg_zone_detail("Adjusting domain name at %d. RDATA of RRSet "
- "with owner %s and type %s.\n", i, name,
- knot_rrtype_to_string(type));
- free(name);
-);
- ret = knot_zone_contents_adjust_rdata(rdata, desc,
- zone, node);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- rdata = rdata->next;
- ++i;
+ knot_dname_t **dn = NULL;
+ while((dn = knot_rrset_get_next_dname(rrset, dn))) {
+ knot_zone_contents_adjust_rdata_dname(zone,
+ lookup_tree,
+ node,
+ dn);
}
-
-dbg_zone_exec_detail(
- char *name = knot_dname_to_str(knot_rrset_owner(rrset));
- dbg_zone_detail("Adjusting domain name at %d. RDATA of RRSet "
- "with owner %s and type %s.\n", i, name,
- knot_rrtype_to_string(type));
- free(name);
-);
- return knot_zone_contents_adjust_rdata(rdata, desc, zone, node);
}
/*----------------------------------------------------------------------------*/
@@ -512,36 +318,46 @@ dbg_zone_exec_detail(
* \param zone Zone to which the node belongs.
*/
static int knot_zone_contents_adjust_rrsets(knot_node_t *node,
- knot_zone_contents_t *zone)
+ hattrie_t *lookup_tree,
+ knot_zone_contents_t *zone)
{
- knot_rrset_t **rrsets = knot_node_get_rrsets(node);
+ knot_rrset_t **rrsets = knot_node_get_rrsets_no_copy(node);
short count = knot_node_rrset_count(node);
assert(count == 0 || rrsets != NULL);
- int ret = KNOT_EOK;
for (int r = 0; r < count; ++r) {
assert(rrsets[r] != NULL);
- dbg_zone("Adjusting next RRSet.\n");
- ret = knot_zone_contents_adjust_rdata_in_rrset(rrsets[r], zone,
- node);
+ /* Make sure that RRSet owner is the same as node's. */
+ if (node->owner != rrsets[r]->owner) {
+ knot_rrset_set_owner(rrsets[r], node->owner);
+ }
+
+ dbg_zone("Adjusting next RRSet.\n");
+ knot_rrset_dump(rrsets[r]);
+ knot_zone_contents_adjust_rdata_in_rrset(rrsets[r],
+ lookup_tree, zone,
+ node);
knot_rrset_t *rrsigs = rrsets[r]->rrsigs;
- if (ret == KNOT_EOK && rrsigs != NULL) {
+ if (rrsigs != NULL) {
dbg_zone("Adjusting next RRSIGs.\n");
- ret = knot_zone_contents_adjust_rdata_in_rrset(rrsigs,
- zone,
- node);
+ knot_rrset_dump(rrsigs);
+ knot_zone_contents_adjust_rdata_in_rrset(rrsigs,
+ lookup_tree, zone,
+ node);
}
- if (ret != KNOT_EOK) {
- break;
+ if (rrsets[r]->type == KNOT_RRTYPE_DS) {
+ int ret = knot_rrset_ds_check(rrsets[r]);
+ if (ret != KNOT_EOK) {
+ dbg_zone("DS RDATA check failed: %s\n", knot_strerror(ret));
+ return KNOT_EMALF;
+ }
}
}
- free(rrsets);
-
- return ret;
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
/*!
@@ -561,15 +377,20 @@ static int knot_zone_contents_adjust_rrsets(knot_node_t *node,
* old changeset processing).
*/
static int knot_zone_contents_adjust_node(knot_node_t *node,
+ hattrie_t *lookup_tree,
knot_zone_contents_t *zone)
{
// adjust domain names in RDATA
- /*! \note Enabled again after a LONG time. Should test thoroughly. */
- int ret = knot_zone_contents_adjust_rrsets(node, zone);
+ int ret = knot_zone_contents_adjust_rrsets(node, lookup_tree,
+ zone);
if (ret != KNOT_EOK) {
return ret;
}
+// const knot_node_t *old_dname_node = node->owner->node;
+ knot_zone_contents_insert_dname_into_table(&node->owner, lookup_tree);
+// assert(node->owner->node == old_dname_node || old_dname_node == NULL);
+
// assure that owner has proper node
if (knot_dname_node(knot_node_owner(node)) == NULL) {
knot_dname_set_node(knot_node_get_owner(node), node);
@@ -582,25 +403,30 @@ static int knot_zone_contents_adjust_node(knot_node_t *node,
}
// NSEC3 node (only if NSEC3 tree is not empty)
- const knot_node_t *prev;
- const knot_node_t *nsec3;
- int match = knot_zone_contents_find_nsec3_for_name(zone,
- knot_node_owner(node),
- &nsec3, &prev);
- UNUSED(prev);
-
- if (match != KNOT_ZONE_NAME_FOUND) {
- nsec3 = NULL;
+ /*! \todo We need only exact matches, what if node has no nsec3 node? */
+ /* This is faster, as it doesn't need ordered access. */
+ knot_node_t *nsec3 = NULL;
+ knot_dname_t *nsec3_name = NULL;
+ ret = knot_zone_contents_nsec3_name(zone, knot_node_owner(node),
+ &nsec3_name);
+ if (ret == KNOT_EOK) {
+ assert(nsec3_name);
+ knot_zone_tree_get(zone->nsec3_nodes, nsec3_name, &nsec3);
+ knot_node_set_nsec3_node(node, nsec3);
+ } else if (ret == KNOT_ENSEC3PAR) {
+ knot_node_set_nsec3_node(node, NULL);
+ } else {
+ /* Something could be in DNAME. */
+ knot_dname_free(&nsec3_name);
+ return ret;
}
-
- knot_node_set_nsec3_node(node, (knot_node_t *)nsec3);
+ knot_dname_free(&nsec3_name);
dbg_zone_detail("Set flags to the node: \n");
dbg_zone_detail("Delegation point: %s\n",
- knot_node_is_deleg_point(node) ? "yes" : "no");
+ knot_node_is_deleg_point(node) ? "yes" : "no");
dbg_zone_detail("Non-authoritative: %s\n",
- knot_node_is_non_auth(node) ? "yes" : "no");
-
+ knot_node_is_non_auth(node) ? "yes" : "no");
return KNOT_EOK;
}
@@ -615,18 +441,17 @@ static int knot_zone_contents_adjust_node(knot_node_t *node,
* \param data Zone the node belongs to.
*/
static void knot_zone_contents_adjust_node_in_tree(
- knot_zone_tree_node_t *tnode, void *data)
+ knot_node_t **tnode, void *data)
{
assert(data != NULL);
assert(tnode != NULL);
- assert(tnode->node != NULL);
knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data;
- knot_node_t *node = tnode->node;
+ knot_node_t *node = *tnode;
if (args->err != KNOT_EOK) {
dbg_xfrin_detail("Error during adjusting: %s, skipping node.\n",
- knot_strerror(args->err));
+ knot_strerror(args->err));
return;
}
@@ -639,43 +464,22 @@ dbg_zone_exec_verb(
knot_zone_contents_t *zone = args->zone;
/*
- * 1) Store domain names to dname table.
- * TODO: make optional!
- */
- assert(zone->dname_table != NULL);
-
- int ret = knot_zone_contents_dnames_from_node_to_table(
- zone->dname_table, node);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add dnames from adjusted node to "
- "table: %s\n", knot_strerror(ret));
- args->err = ret;
- return;
- }
-
- /*
- * 2) Do other adjusting (flags, closest enclosers, wildcard children,
+ * Do other adjusting (flags, closest enclosers, wildcard children,
* etc.).
*/
- ret = knot_zone_contents_adjust_node(node, zone);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to adjust node: %s\n", knot_strerror(ret));
- args->err = ret;
- return;
- }
+ args->err = knot_zone_contents_adjust_node(node, args->lookup_tree, zone);
}
/*----------------------------------------------------------------------------*/
static void knot_zone_contents_adjust_node_in_tree_ptr(
- knot_zone_tree_node_t *tnode, void *data)
+ knot_node_t **tnode, void *data)
{
assert(data != NULL);
assert(tnode != NULL);
- assert(tnode->node != NULL);
knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data;
- knot_node_t *node = tnode->node;
+ knot_node_t *node = *tnode;
dbg_zone_exec_detail(
if (knot_node_parent(node)) {
@@ -736,18 +540,17 @@ static void knot_zone_contents_adjust_node_in_tree_ptr(
* \param data Zone the node belongs to.
*/
static void knot_zone_contents_adjust_nsec3_node_in_tree(
- knot_zone_tree_node_t *tnode, void *data)
+ knot_node_t **tnode, void *data)
{
assert(data != NULL);
assert(tnode != NULL);
- assert(tnode->node != NULL);
+ knot_node_t *node = *tnode;
knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data;
- knot_node_t *node = tnode->node;
if (args->err != KNOT_EOK) {
dbg_xfrin_detail("Error during adjusting: %s, skipping node.\n",
- knot_strerror(args->err));
+ knot_strerror(args->err));
return;
}
@@ -757,32 +560,24 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree(
}
/*
- * Store domain names to dname table.
+ * We assume, that NSEC3 nodes have none DNAMEs in their RDATA and
+ * that node owners are all unique. \todo Harmful?
*/
+
knot_zone_contents_t *zone = args->zone;
assert(zone != NULL);
-
- int ret = knot_zone_contents_dnames_from_node_to_table(
- zone->dname_table, node);
- if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add dnames from adjusted node to "
- "table: %s\n", knot_strerror(ret));
- args->err = ret;
- return;
- }
}
/*----------------------------------------------------------------------------*/
static void knot_zone_contents_adjust_nsec3_node_in_tree_ptr(
- knot_zone_tree_node_t *tnode, void *data)
+ knot_node_t **tnode, void *data)
{
assert(data != NULL);
assert(tnode != NULL);
- assert(tnode->node != NULL);
knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data;
- knot_node_t *node = tnode->node;
+ knot_node_t *node = *tnode;
// set previous node
knot_node_set_previous(node, args->previous_node);
@@ -796,23 +591,8 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree_ptr(
}
/*----------------------------------------------------------------------------*/
-/*!
- * \brief Creates a NSEC3 hashed name for the given domain name.
- *
- * \note The zone's NSEC3PARAM record must be parsed prior to calling this
- * function (see knot_zone_load_nsec3param()).
- *
- * \param zone Zone from which to take the NSEC3 parameters.
- * \param name Domain name to hash.
- * \param nsec3_name Hashed name.
- *
- * \retval KNOT_EOK
- * \retval KNOT_ENSEC3PAR
- * \retval KNOT_ECRYPTO
- * \retval KNOT_ERROR if an error occured while creating a new domain name
- * from the hash or concatenating it with the zone name.
- */
-static int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone,
+
+int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone,
const knot_dname_t *name,
knot_dname_t **nsec3_name)
{
@@ -842,8 +622,8 @@ dbg_zone_exec_verb(
);
int res = knot_nsec3_sha1(nsec3_params, knot_dname_name(name),
- knot_dname_size(name), &hashed_name,
- &hash_size);
+ knot_dname_size(name), &hashed_name,
+ &hash_size);
if (res != 0) {
char *n = knot_dname_to_str(name);
@@ -856,29 +636,31 @@ dbg_zone_exec_verb(
dbg_zone_hex((char *)hashed_name, hash_size);
dbg_zone("\n");
- char *name_b32 = NULL;
- int32_t b32_ret = base32hex_encode_alloc(hashed_name, hash_size,
- (uint8_t **)(&name_b32));
+ uint8_t *name_b32 = NULL;
+ size_t size = base32hex_encode_alloc(hashed_name, hash_size,
+ &name_b32);
- if (b32_ret <= 0) {
+ if (size == 0) {
char *n = knot_dname_to_str(name);
dbg_zone("Error while encoding hashed name %s to base32.\n", n);
free(n);
- if (name_b32 != NULL) {
- free(name_b32);
- }
+ free(name_b32);
return KNOT_ECRYPTO;
}
- size_t size = b32_ret;
-
assert(name_b32 != NULL);
free(hashed_name);
- dbg_zone_verb("Base32-encoded hash: %s\n", name_b32);
+dbg_zone_exec_verb(
+ /* name_b32 is not 0-terminated. */
+ char b32_string[hash_size + 1];
+ memset(b32_string, 0, hash_size + 1);
+ memcpy(b32_string, name_b32, hash_size);
+ dbg_zone_verb("Base32-encoded hash: %s\n", b32_string);
+);
/* Will be returned to caller, make sure it is released after use. */
- *nsec3_name = knot_dname_new_from_str(name_b32, size, NULL);
+ *nsec3_name = knot_dname_new_from_str((char *)name_b32, size, NULL);
free(name_b32);
@@ -886,13 +668,14 @@ dbg_zone_exec_verb(
dbg_zone("Error while creating domain name for hashed name.\n");
return KNOT_ERROR;
}
+ knot_dname_to_lower(*nsec3_name);
assert(zone->apex->owner != NULL);
knot_dname_t *ret = knot_dname_cat(*nsec3_name, zone->apex->owner);
if (ret == NULL) {
dbg_zone("Error while creating NSEC3 domain name for "
- "hashed name.\n");
+ "hashed name.\n");
knot_dname_release(*nsec3_name);
return KNOT_ERROR;
}
@@ -932,7 +715,7 @@ static int knot_zone_contents_find_in_tree(knot_zone_tree_t *tree,
knot_node_t *found = NULL, *prev = NULL;
int exact_match = knot_zone_tree_get_less_or_equal(tree, name, &found,
- &prev);
+ &prev);
assert(exact_match >= 0);
*node = found;
@@ -943,201 +726,29 @@ static int knot_zone_contents_find_in_tree(knot_zone_tree_t *tree,
/*----------------------------------------------------------------------------*/
-static void knot_zone_contents_node_to_hash(knot_zone_tree_node_t *tnode,
- void *data)
-{
- assert(tnode != NULL && tnode->node != NULL
- && tnode->node->owner != NULL && data != NULL);
-
- knot_node_t *node = tnode->node;
-
- knot_zone_contents_t *zone = (knot_zone_contents_t *)data;
- /*
- * By the original approach, only authoritative nodes and delegation
- * points should be added to the hash table, but currently, all nodes
- * are being added when the zone is created (don't know why actually:),
- * so we will do no distinction here neither.
- */
-
-#ifdef USE_HASH_TABLE
- // add the node also to the hash table if authoritative, or deleg. point
- if (zone->table != NULL
- && ck_insert_item(zone->table,
- (const char *)node->owner->name,
- node->owner->size, (void *)node) != 0) {
- dbg_zone("Error inserting node into hash table!\n");
- }
-#endif
-}
-
-/*----------------------------------------------------------------------------*/
-/* CNAME chain checking */
-/*----------------------------------------------------------------------------*/
-
-typedef struct cname_chain {
- const knot_node_t *node;
- struct cname_chain *next;
-} cname_chain_t;
-
-/*----------------------------------------------------------------------------*/
-
-static int cname_chain_add(cname_chain_t **last, const knot_node_t *node)
-{
- assert(last != NULL);
-
- cname_chain_t *new_cname =
- (cname_chain_t *)malloc(sizeof(cname_chain_t));
- CHECK_ALLOC_LOG(new_cname, KNOT_ENOMEM);
-
- new_cname->node = node;
- new_cname->next = NULL;
-
- if (*last != NULL) {
- (*last)->next = new_cname;
- } else {
- *last = new_cname;
- }
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int cname_chain_contains(cname_chain_t *chain, const knot_node_t *node)
-{
- cname_chain_t *act = chain;
- while (act != NULL) {
- if (act->node == node) {
- return 1;
- }
- act = act->next;
- }
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void cname_chain_free(cname_chain_t *chain)
-{
- cname_chain_t *act = chain;
-
- while (act != NULL) {
- chain = chain->next;
- free(act);
- act = chain;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-typedef struct loop_check_data {
- knot_zone_contents_t *zone;
- int err;
-} loop_check_data_t;
-
-/*----------------------------------------------------------------------------*/
-
-static void knot_zone_contents_check_loops_in_tree(knot_zone_tree_node_t *tnode,
- void *data)
+static int knot_zc_nsec3_parameters_match(const knot_rrset_t *rrset,
+ const knot_nsec3_params_t *params,
+ size_t rdata_pos)
{
- assert(tnode != NULL);
- assert(tnode->node != NULL);
- assert(data != NULL);
-
- loop_check_data_t *args = (loop_check_data_t *)data;
- const knot_node_t *node = tnode->node;
-
- assert(args->zone != NULL);
-
- if (args->err != KNOT_EOK) {
- dbg_xfrin_detail("Error during CNAME loop checking, skipping "
- "node.\n");
- return;
- }
-
- // if there is CNAME in the node
- const knot_rrset_t *cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME);
- cname_chain_t *chain = NULL;
- cname_chain_t **act_cname = &chain;
- int ret = 0;
-
- while (cname != NULL && !cname_chain_contains(chain, node)) {
- ret = cname_chain_add(act_cname, node);
- if (ret != KNOT_EOK) {
- cname_chain_free(chain);
- args->err = ret;
- return;
- }
- act_cname = &(*act_cname)->next;
-
- // follow the CNAME chain, including wildcards and
- // remember the nodes passed through
- const knot_dname_t *next_name = knot_rdata_cname_name(
- knot_rrset_rdata(cname));
- assert(next_name != NULL);
- const knot_node_t *next_node = knot_dname_node(next_name);
- if (next_node == NULL) {
- // try to find the name in the zone
- const knot_node_t *ce = NULL;
- ret = knot_zone_contents_find_dname_hash(
- args->zone, next_name,
- &next_node, &ce);
-
- if (ret != KNOT_ZONE_NAME_FOUND
- && ce != NULL) {
- // try to find wildcard child
- assert(knot_dname_is_subdomain(next_name,
- knot_node_owner(ce)));
- next_node = knot_node_wildcard_child(ce);
- }
-
- assert(next_node == NULL || knot_dname_compare(
- knot_node_owner(next_node), next_name) == 0
- || knot_dname_is_wildcard(knot_node_owner(next_node)));
- }
-
- if (next_node == NULL) {
- // no CNAME node to follow
- cname = NULL;
- } else {
- node = next_node;
- cname = knot_node_rrset(node, KNOT_RRTYPE_CNAME);
- }
- }
-
- if (cname != NULL) {
- // this means the node is in the chain already
- args->err = KNOT_ECNAME;
- }
-
- cname_chain_free(chain);
-}
-
-/*----------------------------------------------------------------------------*/
+ assert(rrset != NULL && params != NULL);
-static int knot_zc_nsec3_parameters_match(const knot_rdata_t *rdata,
- const knot_nsec3_params_t *params)
-{
- assert(rdata != NULL && params != NULL);
-
dbg_zone_detail("RDATA algo: %u, iterations: %u, salt length: %u, salt:"
- " %.*s\n",
- knot_rdata_nsec3_algorithm(rdata),
- knot_rdata_nsec3_iterations(rdata),
- knot_rdata_nsec3_salt_length(rdata),
- knot_rdata_nsec3_salt_length(rdata),
- knot_rdata_nsec3_salt(rdata));
+ " %.*s\n",
+ knot_rrset_rdata_nsec3_algorithm(rrset, rdata_pos),
+ knot_rrset_rdata_nsec3_iterations(rrset, rdata_pos),
+ knot_rrset_rdata_nsec3_salt_length(rrset, rdata_pos),
+ knot_rrset_rdata_nsec3_salt_length(rrset, rdata_pos),
+ knot_rrset_rdata_nsec3_salt(rrset, rdata_pos));
dbg_zone_detail("NSEC3PARAM algo: %u, iterations: %u, salt length: %u, "
- "salt: %.*s\n", params->algorithm, params->iterations,
- params->salt_length, params->salt_length, params->salt);
-
- return (knot_rdata_nsec3_algorithm(rdata) == params->algorithm
- && knot_rdata_nsec3_iterations(rdata) == params->iterations
- && knot_rdata_nsec3_salt_length(rdata) == params->salt_length
- && strncmp((const char *)knot_rdata_nsec3_salt(rdata),
- (const char *)params->salt, params->salt_length)
- == 0);
+ "salt: %.*s\n", params->algorithm, params->iterations,
+ params->salt_length, params->salt_length, params->salt);
+
+ return (knot_rrset_rdata_nsec3_algorithm(rrset, rdata_pos) == params->algorithm
+ && knot_rrset_rdata_nsec3_iterations(rrset, rdata_pos) == params->iterations
+ && knot_rrset_rdata_nsec3_salt_length(rrset, rdata_pos) == params->salt_length
+ && strncmp((const char *)knot_rrset_rdata_nsec3_salt(rrset, rdata_pos),
+ (const char *)params->salt, params->salt_length)
+ == 0);
}
/*----------------------------------------------------------------------------*/
@@ -1145,13 +756,10 @@ static int knot_zc_nsec3_parameters_match(const knot_rdata_t *rdata,
/*----------------------------------------------------------------------------*/
knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
- uint node_count,
- int use_domain_table,
struct knot_zone *zone)
{
- dbg_zone("Creating contents for %u nodes.\n", node_count);
knot_zone_contents_t *contents = (knot_zone_contents_t *)
- calloc(1, sizeof(knot_zone_contents_t));
+ calloc(1, sizeof(knot_zone_contents_t));
if (contents == NULL) {
ERR_ALLOC_FAILED;
return NULL;
@@ -1163,32 +771,19 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
contents->node_count = 1;
dbg_zone_verb("Creating tree for normal nodes.\n");
- contents->nodes = malloc(sizeof(knot_zone_tree_t));
+ contents->nodes = knot_zone_tree_create();
if (contents->nodes == NULL) {
ERR_ALLOC_FAILED;
goto cleanup;
}
dbg_zone_verb("Creating tree for NSEC3 nodes.\n");
- contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t));
+ contents->nsec3_nodes = knot_zone_tree_create();
if (contents->nsec3_nodes == NULL) {
ERR_ALLOC_FAILED;
goto cleanup;
}
- if (use_domain_table) {
- dbg_zone_verb("Creating domain name table.\n");
- contents->dname_table = knot_dname_table_new();
- if (contents->dname_table == NULL) {
- ERR_ALLOC_FAILED;
- goto cleanup;
- }
- } else {
- contents->dname_table = NULL;
- }
-
- //contents->node_count = node_count;
-
/* Initialize NSEC3 params */
dbg_zone_verb("Initializing NSEC3 parameters.\n");
contents->nsec3_params.algorithm = 0;
@@ -1197,57 +792,16 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
contents->nsec3_params.salt_length = 0;
contents->nsec3_params.salt = NULL;
- dbg_zone_verb("Initializing zone trees.\n");
- if (knot_zone_tree_init(contents->nodes) != KNOT_EOK
- || knot_zone_tree_init(contents->nsec3_nodes) != KNOT_EOK) {
- goto cleanup;
- }
-
dbg_zone_verb("Inserting apex into the zone tree.\n");
if (knot_zone_tree_insert(contents->nodes, apex) != KNOT_EOK) {
dbg_zone("Failed to insert apex to the zone tree.\n");
goto cleanup;
}
-#ifdef USE_HASH_TABLE
- if (node_count > 0) {
- dbg_zone_verb("Creating hash table.\n");
- contents->table = ck_create_table(node_count);
- if (contents->table == NULL) {
- goto cleanup;
- }
-
- // insert the apex into the hash table
- dbg_zone_verb("Inserting apex into the hash table.\n");
- if (ck_insert_item(contents->table,
- (const char *)knot_dname_name(
- knot_node_owner(apex)),
- knot_dname_size(knot_node_owner(apex)),
- (void *)apex) != 0) {
- ck_destroy_table(&contents->table, NULL, 0);
- goto cleanup;
- }
- } else {
- contents->table = NULL;
- }
-#endif
-
- // insert names from the apex to the domain table
- if (use_domain_table) {
- dbg_zone_verb("Inserting names from apex to table.\n");
- int rc = knot_zone_contents_dnames_from_node_to_table(
- contents->dname_table, apex);
- if (rc != KNOT_EOK) {
- ck_destroy_table(&contents->table, NULL, 0);
- goto cleanup;
- }
- }
-
return contents;
cleanup:
dbg_zone_verb("Cleaning up.\n");
- free(contents->dname_table);
free(contents->nodes);
free(contents->nsec3_nodes);
free(contents);
@@ -1259,7 +813,7 @@ cleanup:
int knot_zone_contents_gen_is_old(const knot_zone_contents_t *contents)
{
return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK)
- == KNOT_ZONE_FLAGS_GEN_OLD);
+ == KNOT_ZONE_FLAGS_GEN_OLD);
}
/*----------------------------------------------------------------------------*/
@@ -1267,7 +821,7 @@ int knot_zone_contents_gen_is_old(const knot_zone_contents_t *contents)
int knot_zone_contents_gen_is_new(const knot_zone_contents_t *contents)
{
return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK)
- == KNOT_ZONE_FLAGS_GEN_NEW);
+ == KNOT_ZONE_FLAGS_GEN_NEW);
}
/*----------------------------------------------------------------------------*/
@@ -1275,7 +829,7 @@ int knot_zone_contents_gen_is_new(const knot_zone_contents_t *contents)
int knot_zone_contents_gen_is_finished(const knot_zone_contents_t *contents)
{
return ((contents->flags & KNOT_ZONE_FLAGS_GEN_MASK)
- == KNOT_ZONE_FLAGS_GEN_FIN);
+ == KNOT_ZONE_FLAGS_GEN_FIN);
}
/*----------------------------------------------------------------------------*/
@@ -1307,7 +861,7 @@ void knot_zone_contents_set_gen_new_finished(knot_zone_contents_t *contents)
int knot_zone_contents_any_disabled(const knot_zone_contents_t *contents)
{
return ((contents->flags & KNOT_ZONE_FLAGS_ANY_MASK)
- == KNOT_ZONE_FLAGS_ANY);
+ == KNOT_ZONE_FLAGS_ANY);
}
/*----------------------------------------------------------------------------*/
@@ -1334,14 +888,14 @@ uint16_t knot_zone_contents_class(const knot_zone_contents_t *contents)
}
return knot_rrset_class(knot_node_rrset(contents->apex,
- KNOT_RRTYPE_SOA));
+ KNOT_RRTYPE_SOA));
}
/*----------------------------------------------------------------------------*/
int knot_zone_contents_add_node(knot_zone_contents_t *zone,
knot_node_t *node, int create_parents,
- uint8_t flags, int use_domain_table)
+ uint8_t flags)
{
if (zone == NULL || node == NULL) {
return KNOT_EINVAL;
@@ -1359,37 +913,12 @@ dbg_zone_exec_detail(
return ret;
}
- if (use_domain_table) {
- ret = knot_zone_contents_dnames_from_node_to_table(
- zone->dname_table, node);
- if (ret != KNOT_EOK) {
- dbg_zone("Failed to add dnames into table.\n");
- return ret;
- }
- }
-
ret = knot_zone_tree_insert(zone->nodes, node);
if (ret != KNOT_EOK) {
dbg_zone("Failed to insert node into zone tree.\n");
return ret;
}
-#ifdef USE_HASH_TABLE
- // add the node also to the hash table if authoritative, or deleg. point
- if (zone->table != NULL
- && ck_insert_item(zone->table,
- (const char *)node->owner->name,
- node->owner->size, (void *)node) != 0) {
- dbg_zone("Error inserting node into hash table!\n");
- knot_zone_tree_node_t *removed;
- (void)knot_zone_tree_remove(zone->nodes, knot_node_owner(node),
- &removed);
- assert(removed->node == node);
- return KNOT_EHASH;
- }
-#endif
- assert(knot_zone_contents_find_node(zone, node->owner));
-
knot_node_set_zone(node, zone->zone);
++zone->node_count;
@@ -1404,11 +933,11 @@ dbg_zone_exec_detail(
knot_dname_left_chop(knot_node_owner(node));
if(chopped == NULL) {
/* Root domain and root domain only. */
- assert(node->owner && node->owner->labels &&
+ assert(node->owner && node->owner->labels &&
node->owner->labels[0] == 0);
return KNOT_EOK;
}
-
+
if (knot_dname_compare(knot_node_owner(zone->apex), chopped) == 0) {
dbg_zone_detail("Zone apex is the parent.\n");
knot_node_set_parent(node, zone->apex);
@@ -1425,7 +954,7 @@ dbg_zone_exec_detail(
chopped != NULL) {
/* Adding new dname to zone + add to table. */
dbg_zone_detail("Creating new node.\n");
-
+
assert(chopped);
next_node = knot_node_new(chopped, NULL, flags);
if (next_node == NULL) {
@@ -1433,17 +962,13 @@ dbg_zone_exec_detail(
knot_dname_free(&chopped);
return KNOT_ENOMEM;
}
-
- if (use_domain_table) {
- ret =
- knot_zone_contents_dnames_from_node_to_table(
- zone->dname_table, next_node);
- if (ret != KNOT_EOK) {
- knot_node_free(&next_node);
- knot_dname_release(chopped);
- return ret;
- }
- }
+ //TODO possible leak
+// ret = knot_zone_contents_solve_node_dnames(zone,
+// next_node);
+// if (ret != KNOT_EOK) {
+// knot_node_free(&next_node);
+// knot_dname_release(chopped);
+// }
if (next_node->owner != chopped) {
/* Node owner was in RDATA */
@@ -1459,39 +984,16 @@ dbg_zone_exec_detail(
dbg_zone_detail("Inserting new node to zone tree.\n");
ret = knot_zone_tree_insert(zone->nodes,
- next_node);
+ next_node);
if (ret != KNOT_EOK) {
dbg_zone("Failed to insert new node "
- "to zone tree.\n");
+ "to zone tree.\n");
/*! \todo Delete the node?? */
/* Directly discard. */
knot_dname_release(chopped);
return ret;
}
-#ifdef USE_HASH_TABLE
-dbg_zone_exec_detail(
- char *name = knot_dname_to_str(
- knot_node_owner(next_node));
- dbg_zone_detail("Adding new node with owner %s to "
- "hash table.\n", name);
- free(name);
-);
-
- if (zone->table != NULL
- && ck_insert_item(zone->table,
- (const char *)knot_dname_name(
- knot_node_owner(next_node)),
- knot_dname_size(knot_node_owner(next_node)),
- (void *)next_node) != 0) {
- dbg_zone("Error inserting node into "
- "hash table!\n");
- /*! \todo Delete the node?? */
- /* Directly discard. */
- knot_dname_release(chopped);
- return KNOT_EHASH;
- }
-#endif
// set parent
knot_node_set_parent(node, next_node);
@@ -1536,8 +1038,7 @@ dbg_zone_exec_detail(
int knot_zone_contents_add_rrset(knot_zone_contents_t *zone,
knot_rrset_t *rrset, knot_node_t **node,
- knot_rrset_dupl_handling_t dupl,
- int use_domain_table)
+ knot_rrset_dupl_handling_t dupl)
{
if (zone == NULL || rrset == NULL || zone->apex == NULL
|| zone->apex->owner == NULL || node == NULL) {
@@ -1546,22 +1047,22 @@ int knot_zone_contents_add_rrset(knot_zone_contents_t *zone,
dbg_zone_exec_detail(
char *name = knot_dname_to_str(knot_rrset_owner(rrset));
- dbg_zone_detail("Adding RRSet to zone contents: %s, type %s\n",
- name, knot_rrtype_to_string(knot_rrset_type(rrset)));
+ dbg_zone_detail("Adding RRSet to zone contents: %s, type %d\n",
+ name, knot_rrset_type(rrset));
free(name);
);
// check if the RRSet belongs to the zone
if (knot_dname_compare(knot_rrset_owner(rrset),
- zone->apex->owner) != 0
+ zone->apex->owner) != 0
&& !knot_dname_is_subdomain(knot_rrset_owner(rrset),
- zone->apex->owner)) {
+ zone->apex->owner)) {
return KNOT_EBADZONE;
}
if ((*node) == NULL
&& (*node = knot_zone_contents_get_node(zone,
- knot_rrset_owner(rrset))) == NULL) {
+ knot_rrset_owner(rrset))) == NULL) {
return KNOT_ENONODE;
}
@@ -1572,9 +1073,9 @@ dbg_zone_exec_detail(
/*! \todo REMOVE RRSET */
if (dupl == KNOT_RRSET_DUPL_MERGE) {
- rc = knot_node_add_rrset_no_dupl(*node, rrset);
+ rc = knot_node_add_rrset(*node, rrset);
} else {
- rc = knot_node_add_rrset(*node, rrset, 0);
+ rc = knot_node_add_rrset_no_merge(*node, rrset);
}
if (rc < 0) {
@@ -1584,40 +1085,17 @@ dbg_zone_exec_detail(
int ret = rc;
- if (use_domain_table) {
- dbg_zone_detail("Saving RRSet to table.\n");
- rc = knot_zone_contents_dnames_from_rrset_to_table(
- zone->dname_table, rrset, 0, (*node)->owner);
- if (rc != KNOT_EOK) {
- dbg_zone("Error saving domain names from "
- "RRSIGs to the domain name table.\n "
- "The zone may be in an inconsistent state.\n");
- // WARNING: the zone is not in consistent state now -
- // there may be domain names in it that are not inserted
- // into the domain table
- return rc;
- }
- }
-
- // replace RRSet's owner with the node's owner (that is already in the
- // table)
- /*! \todo Do even if domain table is not used?? */
- if (ret == KNOT_EOK && rrset->owner != (*node)->owner) {
- knot_rrset_set_owner(rrset, (*node)->owner);
- }
-
- dbg_zone_detail("RRSet OK.\n");
+ dbg_zone_detail("RRSet OK (%d).\n", ret);
return ret;
}
/*----------------------------------------------------------------------------*/
int knot_zone_contents_add_rrsigs(knot_zone_contents_t *zone,
- knot_rrset_t *rrsigs,
- knot_rrset_t **rrset,
- knot_node_t **node,
- knot_rrset_dupl_handling_t dupl,
- int use_domain_table)
+ knot_rrset_t *rrsigs,
+ knot_rrset_t **rrset,
+ knot_node_t **node,
+ knot_rrset_dupl_handling_t dupl)
{
dbg_zone_verb("Adding RRSIGs to zone contents.\n");
@@ -1625,11 +1103,11 @@ int knot_zone_contents_add_rrsigs(knot_zone_contents_t *zone,
|| zone->apex == NULL || zone->apex->owner == NULL) {
dbg_zone_exec(
dbg_zone("Parameters: zone=%p, rrsigs=%p, rrset=%p, "
- "node=%p\n", zone, rrsigs, rrset, node);
+ "node=%p\n", zone, rrsigs, rrset, node);
if (zone != NULL) {
dbg_zone("zone->apex=%p\n", zone->apex);
if (zone->apex != NULL) {
- dbg_zone("zone->apex->owner=%p\n",
+ dbg_zone("zone->apex->owner=%p\n",
zone->apex->owner);
}
}
@@ -1640,16 +1118,16 @@ dbg_zone_exec(
// check if the RRSet belongs to the zone
if (*rrset != NULL
&& knot_dname_compare(knot_rrset_owner(*rrset),
- zone->apex->owner) != 0
+ zone->apex->owner) != 0
&& !knot_dname_is_subdomain(knot_rrset_owner(*rrset),
- zone->apex->owner)) {
+ zone->apex->owner)) {
return KNOT_EBADZONE;
}
// check if the RRSIGs belong to the RRSet
if (*rrset != NULL
&& (knot_dname_compare(knot_rrset_owner(rrsigs),
- knot_rrset_owner(*rrset)) != 0)) {
+ knot_rrset_owner(*rrset)) != 0)) {
dbg_zone("RRSIGs do not belong to the given RRSet.\n");
return KNOT_EINVAL;
}
@@ -1659,15 +1137,14 @@ dbg_zone_exec(
// even no node given
// find proper node
knot_node_t *(*get_node)(const knot_zone_contents_t *,
- const knot_dname_t *)
- = (knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(rrsigs)) == KNOT_RRTYPE_NSEC3)
+ const knot_dname_t *)
+ = (knot_rrset_rdata_rrsig_type_covered(rrsigs) == KNOT_RRTYPE_NSEC3)
? knot_zone_contents_get_nsec3_node
: knot_zone_contents_get_node;
if (*node == NULL
&& (*node = get_node(
- zone, knot_rrset_owner(rrsigs))) == NULL) {
+ zone, knot_rrset_owner(rrsigs))) == NULL) {
dbg_zone("Failed to find node for RRSIGs.\n");
return KNOT_ENONODE;
}
@@ -1676,13 +1153,10 @@ dbg_zone_exec(
// find the RRSet in the node
// take only the first RDATA from the RRSIGs
- dbg_zone_detail("Finding RRSet for type %s\n",
- knot_rrtype_to_string(
- knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(rrsigs))));
+ dbg_zone_detail("Finding RRSet for type %d\n",
+ knot_rrset_rdata_rrsig_type_covered(rrsigs));
*rrset = knot_node_get_rrset(
- *node, knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(rrsigs)));
+ *node, knot_rrset_rdata_rrsig_type_covered(rrsigs));
if (*rrset == NULL) {
dbg_zone("Failed to find RRSet for RRSIGs.\n");
return KNOT_ENORRSET;
@@ -1704,28 +1178,6 @@ dbg_zone_exec(
ret = 1;
}
- // add all domain names from the RRSet to domain name table
- if (use_domain_table) {
- dbg_zone_detail("Saving RRSIG RRSet to table.\n");
- rc = knot_zone_contents_dnames_from_rrset_to_table(
- zone->dname_table, (*rrset)->rrsigs, 0, (*rrset)->owner);
- if (rc != KNOT_EOK) {
- dbg_zone("Error saving domain names from "
- "RRSIGs to the domain name table.\n "
- "The zone may be in an inconsistent state.\n");
- // WARNING: the zone is not in consistent state now -
- // there may be domain names in it that are not inserted
- // into the domain table
- return rc;
- }
- }
-
- // replace RRSet's owner with the node's owner (that is already in the
- // table)
- if ((*rrset)->owner != (*rrset)->rrsigs->owner) {
- knot_rrset_set_owner((*rrset)->rrsigs, (*rrset)->owner);
- }
-
dbg_zone_detail("RRSIGs OK\n");
return ret;
}
@@ -1734,7 +1186,7 @@ dbg_zone_exec(
int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone,
knot_node_t *node, int create_parents,
- uint8_t flags, int use_domain_table)
+ uint8_t flags)
{
UNUSED(create_parents);
UNUSED(flags);
@@ -1750,25 +1202,13 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone,
}
// how to know if this is successfull??
-// TREE_INSERT(zone->nsec3_nodes, knot_node, avl, node);
ret = knot_zone_tree_insert(zone->nsec3_nodes, node);
if (ret != KNOT_EOK) {
dbg_zone("Failed to insert node into NSEC3 tree: %s.\n",
- knot_strerror(ret));
+ knot_strerror(ret));
return ret;
}
- if (use_domain_table) {
- ret = knot_zone_contents_dnames_from_node_to_table(
- zone->dname_table, node);
- if (ret != KNOT_EOK) {
- /*! \todo Remove the node from the tree. */
- dbg_zone("Failed to add dnames into table: %s.\n",
- knot_strerror(ret));
- return ret;
- }
- }
-
// no parents to be created, the only parent is the zone apex
// set the apex as the parent of the node
knot_node_set_parent(node, zone->apex);
@@ -1786,8 +1226,7 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone,
int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone,
knot_rrset_t *rrset,
knot_node_t **node,
- knot_rrset_dupl_handling_t dupl,
- int use_domain_table)
+ knot_rrset_dupl_handling_t dupl)
{
if (zone == NULL || rrset == NULL || zone->apex == NULL
|| zone->apex->owner == NULL || node == NULL) {
@@ -1796,28 +1235,26 @@ int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone,
// check if the RRSet belongs to the zone
if (knot_dname_compare(knot_rrset_owner(rrset),
- zone->apex->owner) != 0
+ zone->apex->owner) != 0
&& !knot_dname_is_subdomain(knot_rrset_owner(rrset),
- zone->apex->owner)) {
+ zone->apex->owner)) {
return KNOT_EBADZONE;
}
if ((*node) == NULL
&& (*node = knot_zone_contents_get_nsec3_node(
- zone, knot_rrset_owner(rrset))) == NULL) {
+ zone, knot_rrset_owner(rrset))) == NULL) {
return KNOT_ENONODE;
}
assert(*node != NULL);
-
- // add all domain names from the RRSet to domain name table
int rc;
/*! \todo REMOVE RRSET */
if (dupl == KNOT_RRSET_DUPL_MERGE) {
- rc = knot_node_add_rrset_no_dupl(*node, rrset);
+ rc = knot_node_add_rrset(*node, rrset);
} else {
- rc = knot_node_add_rrset(*node, rrset, 0);
+ rc = knot_node_add_rrset_no_merge(*node, rrset);
}
if (rc < 0) {
@@ -1826,37 +1263,14 @@ int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone,
int ret = rc;
- if (use_domain_table) {
- dbg_zone_detail("Saving NSEC3 RRSet to table.\n");
- rc = knot_zone_contents_dnames_from_rrset_to_table(
- zone->dname_table, rrset, 0, (*node)->owner);
- if (rc != KNOT_EOK) {
- dbg_zone("Error saving domain names from "
- "RRSIGs to the domain name table.\n "
- "The zone may be in an inconsistent state.\n");
- // WARNING: the zone is not in consistent state now -
- // there may be domain names in it that are not inserted
- // into the domain table
- return rc;
- }
- }
-
- // replace RRSet's owner with the node's owner (that is already in the
- // table)
- /*! \todo Do even if domain table is not used? */
- if (rrset->owner != (*node)->owner) {
- knot_rrset_set_owner(rrset, (*node)->owner);
- }
-
dbg_zone_detail("NSEC3 OK\n");
return ret;
}
/*----------------------------------------------------------------------------*/
-int knot_zone_contents_remove_node(knot_zone_contents_t *contents,
- const knot_node_t *node, knot_zone_tree_node_t **removed_tree,
- ck_hash_table_item_t **removed_hash)
+int knot_zone_contents_remove_node(knot_zone_contents_t *contents,
+ const knot_node_t *node, knot_node_t **removed_tree)
{
if (contents == NULL || node == NULL) {
return KNOT_EINVAL;
@@ -1870,15 +1284,6 @@ dbg_zone_exec_verb(
free(name);
);
- // 1) remove the node from hash table
- *removed_hash = NULL;
- *removed_hash = ck_remove_item(contents->table,
- (const char *)knot_dname_name(owner),
- knot_dname_size(owner));
- if (*removed_hash == NULL) {
- return KNOT_ENONODE;
- }
-
// 2) remove the node from the zone tree
*removed_tree = NULL;
int ret = knot_zone_tree_remove(contents->nodes, owner, removed_tree);
@@ -1891,8 +1296,8 @@ dbg_zone_exec_verb(
/*----------------------------------------------------------------------------*/
-int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents,
- const knot_node_t *node, knot_zone_tree_node_t **removed)
+int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents,
+ const knot_node_t *node, knot_node_t **removed)
{
if (contents == NULL || node == NULL) {
return KNOT_EINVAL;
@@ -1912,56 +1317,6 @@ int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
-int knot_zone_contents_create_and_fill_hash_table(
- knot_zone_contents_t *zone)
-{
- if (zone == NULL || zone->apex == NULL || zone->apex->owner == NULL) {
- return KNOT_EINVAL;
- }
- /*
- * 1) Create hash table.
- */
-#ifdef USE_HASH_TABLE
- if (zone->node_count > 0) {
- zone->table = ck_create_table(zone->node_count);
- if (zone->table == NULL) {
- return KNOT_ENOMEM;
- }
-
- // insert the apex into the hash table
- if (ck_insert_item(zone->table,
- (const char *)zone->apex->owner->name,
- zone->apex->owner->size,
- (void *)zone->apex) != 0) {
- return KNOT_EHASH;
- }
- } else {
- zone->table = NULL;
- return KNOT_EOK; // OK?
- }
-
- /*
- * 2) Fill in the hash table.
- *
- * In this point, the nodes in the zone must be adjusted, so that only
- * relevant nodes (authoritative and delegation points are inserted.
- *
- * TODO: how to know if this was successful??
- */
- /*! \todo Replace by zone tree. */
- int ret = knot_zone_tree_forward_apply_inorder(zone->nodes,
- knot_zone_contents_node_to_hash, zone);
- if (ret != KNOT_EOK) {
- dbg_zone("Failed to insert nodes to hash table.\n");
- return ret;
- }
-
-#endif
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
knot_node_t *knot_zone_contents_get_node(const knot_zone_contents_t *zone,
const knot_dname_t *name)
{
@@ -1993,7 +1348,7 @@ knot_node_t *knot_zone_contents_get_nsec3_node(
if (ret != KNOT_EOK) {
dbg_zone("Failed to find NSEC3 name in the zone tree."
- "\n");
+ "\n");
return NULL;
}
@@ -2026,7 +1381,7 @@ dbg_zone_exec_verb(
char *name_str = knot_dname_to_str(name);
char *zone_str = knot_dname_to_str(zone->apex->owner);
dbg_zone_verb("Searching for name %s in zone %s...\n",
- name_str, zone_str);
+ name_str, zone_str);
free(name_str);
free(zone_str);
);
@@ -2046,19 +1401,19 @@ dbg_zone_exec_verb(
knot_node_t *found = NULL, *prev = NULL;
int exact_match = knot_zone_contents_find_in_tree(zone->nodes, name,
- &found, &prev);
+ &found, &prev);
assert(exact_match >= 0);
*node = found;
*previous = prev;
dbg_zone_exec_detail(
char *name_str = (*node) ? knot_dname_to_str((*node)->owner)
- : "(nil)";
+ : "(nil)";
char *name_str2 = (*previous != NULL)
- ? knot_dname_to_str((*previous)->owner)
- : "(nil)";
+ ? knot_dname_to_str((*previous)->owner)
+ : "(nil)";
dbg_zone_detail("Search function returned %d, node %s (%p) and prev: %s (%p)\n",
- exact_match, name_str, *node, name_str2, *previous);
+ exact_match, name_str, *node, name_str2, *previous);
if (*node) {
free(name_str);
@@ -2118,7 +1473,7 @@ knot_node_t *knot_zone_contents_get_previous(
knot_node_t *found = NULL, *prev = NULL;
int exact_match = knot_zone_contents_find_in_tree(zone->nodes, name,
- &found, &prev);
+ &found, &prev);
assert(exact_match >= 0);
assert(prev != NULL);
@@ -2145,7 +1500,7 @@ knot_node_t *knot_zone_contents_get_previous_nsec3(
knot_node_t *found = NULL, *prev = NULL;
int exact_match = knot_zone_contents_find_in_tree(zone->nsec3_nodes,
- name, &found, &prev);
+ name, &found, &prev);
assert(exact_match >= 0);
assert(prev != NULL);
@@ -2162,99 +1517,6 @@ const knot_node_t *knot_zone_contents_find_previous_nsec3(
/*----------------------------------------------------------------------------*/
-static void knot_zone_contents_left_chop(char *name, size_t *size)
-{
- short label_size = (unsigned char)name[0];
-
- memmove(name, name + label_size + 1, *size -label_size - 1);
- *size = *size - label_size - 1;
-}
-
-/*----------------------------------------------------------------------------*/
-#ifdef USE_HASH_TABLE
-int knot_zone_contents_find_dname_hash(const knot_zone_contents_t *zone,
- const knot_dname_t *name,
- const knot_node_t **node,
- const knot_node_t **closest_encloser)
-{
- if (zone == NULL || name == NULL || node == NULL
- || closest_encloser == NULL) {
- return KNOT_EINVAL;
- }
-
-dbg_zone_exec_verb(
- char *name_str = knot_dname_to_str(name);
- char *zone_str = knot_dname_to_str(zone->apex->owner);
- dbg_zone_verb("Searching for name %s in zone %s...\n",
- name_str, zone_str);
- free(name_str);
- free(zone_str);
-);
-
- if (knot_dname_compare(name, zone->apex->owner) == 0) {
- *node = zone->apex;
- *closest_encloser = *node;
- return KNOT_ZONE_NAME_FOUND;
- }
-
- if (!knot_dname_is_subdomain(name, zone->apex->owner)) {
- *node = NULL;
- *closest_encloser = NULL;
- return KNOT_EBADZONE;
- }
-
- // temporary name used for hashing
- char name_tmp[KNOT_MAX_DNAME_LENGTH];
- size_t name_size = name->size;
- if (knot_dname_to_lower_copy(name, name_tmp, KNOT_MAX_DNAME_LENGTH)
- != KNOT_EOK) {
- return KNOT_ERROR;
- }
-
- assert(zone->table != NULL);
- const ck_hash_table_item_t *item = ck_find_item(zone->table,
- name_tmp, name_size);
-
- if (item != NULL) {
- *node = (const knot_node_t *)item->value;
- *closest_encloser = *node;
-
- dbg_zone_detail("Found node in hash table: %p (owner %p, "
- "labels: %d)\n", *node, (*node)->owner,
- knot_dname_label_count((*node)->owner));
- assert(*node != NULL);
- assert(*closest_encloser != NULL);
- return KNOT_ZONE_NAME_FOUND;
- }
-
- *node = NULL;
-
- // chop leftmost labels until some node is found
- // copy the name for chopping
-
- dbg_zone_detail("Finding closest encloser..\nStarting with: %.*s\n",
- (int)name_size, name_tmp);
-
- while (item == NULL) {
- knot_zone_contents_left_chop(name_tmp, &name_size);
-dbg_zone_exec_detail(
- dbg_zone_detail("Chopped leftmost label: %.*s\n",
- (int)name_size, name_tmp);
-);
- // not satisfied in root zone!!
- assert(name_size > 0);
-
- item = ck_find_item(zone->table, name_tmp, name_size);
- }
-
- assert(item != NULL);
- *closest_encloser = (const knot_node_t *)item->value;
-
- return KNOT_ZONE_NAME_NOT_FOUND;
-}
-#endif
-/*----------------------------------------------------------------------------*/
-
const knot_node_t *knot_zone_contents_find_nsec3_node(
const knot_zone_contents_t *zone, const knot_dname_t *name)
{
@@ -2281,7 +1543,7 @@ int knot_zone_contents_find_nsec3_for_name(const knot_zone_contents_t *zone,
}
// check if the NSEC3 tree is not empty
- if (zone->nsec3_nodes->th_root == NULL) {
+ if (knot_zone_tree_weight(zone->nsec3_nodes) == 0) {
dbg_zone("NSEC3 tree is empty.\n");
knot_dname_release(nsec3_name);
return KNOT_ENSEC3CHAIN;
@@ -2341,39 +1603,40 @@ dbg_zone_exec_detail(
}
dbg_zone_verb("find_nsec3_for_name() returning %d\n", exact_match);
-
- /* The previous may be from wrong NSEC3 chain. Search for previous
- * from the right chain. Check iterations, hash algorithm and salt
+
+ /* The previous may be from wrong NSEC3 chain. Search for previous
+ * from the right chain. Check iterations, hash algorithm and salt
* values and compare them to the ones from NSEC3PARAM.
*/
- const knot_rrset_t *nsec3_rrset = knot_node_rrset(*nsec3_previous,
- KNOT_RRTYPE_NSEC3);
- const knot_rdata_t *nsec3_rdata = (nsec3_rrset != NULL)
- ? knot_rrset_rdata(nsec3_rrset)
- : NULL;
+ const knot_rrset_t *nsec3_rrset = knot_node_rrset(*nsec3_previous,
+ KNOT_RRTYPE_NSEC3);
+ assert(nsec3_rrset);
const knot_node_t *original_prev = *nsec3_previous;
-
- while (nsec3_rdata != NULL
- && !knot_zc_nsec3_parameters_match(nsec3_rdata,
- &zone->nsec3_params)) {
- /* Try other RDATA if there are some. In case of name collision
- * the node would contain records from both NSEC3 chains.
- */
- if ((nsec3_rdata = knot_rrset_rdata_next(
- nsec3_rrset, nsec3_rdata)) != NULL) {
- continue;
+
+ int match = 0;
+
+ while (nsec3_rrset && !match) {
+ for (uint16_t i = 0;
+ i < knot_rrset_rdata_rr_count(nsec3_rrset) && !match;
+ i++) {
+ if (knot_zc_nsec3_parameters_match(nsec3_rrset,
+ &zone->nsec3_params,
+ i)) {
+ /* Matching NSEC3PARAM match at position nr.: i. */
+ match = 1;
+ }
}
-
- /* If there is none, try previous node. */
-
+
+ if (match) {
+ break;
+ }
+
+ /* This RRSET was not a match, try the one from previous node. */
*nsec3_previous = knot_node_previous(*nsec3_previous);
- nsec3_rrset = knot_node_rrset(*nsec3_previous,
- KNOT_RRTYPE_NSEC3);
- nsec3_rdata = (nsec3_rrset != NULL)
- ? knot_rrset_rdata(nsec3_rrset)
- : NULL;
-dbg_zone_exec_detail(
- char *name = (*nsec3_previous)
+ nsec3_rrset = knot_node_rrset(*nsec3_previous,
+ KNOT_RRTYPE_NSEC3);
+ dbg_zone_exec_detail(
+ char *name = (*nsec3_previous)
? knot_dname_to_str(
knot_node_owner(*nsec3_previous))
: "none";
@@ -2383,7 +1646,7 @@ dbg_zone_exec_detail(
free(name);
}
);
- if (*nsec3_previous == original_prev || nsec3_rdata == NULL) {
+ if (*nsec3_previous == original_prev || nsec3_rrset == NULL) {
// cycle
*nsec3_previous = NULL;
break;
@@ -2420,43 +1683,63 @@ knot_node_t *knot_zone_contents_get_apex(const knot_zone_contents_t *zone)
/*----------------------------------------------------------------------------*/
-int knot_zone_contents_adjust(knot_zone_contents_t *zone)
+int knot_zone_contents_adjust(knot_zone_contents_t *zone,
+ knot_node_t **first_nsec3_node,
+ knot_node_t **last_nsec3_node, int dupl_check)
{
if (zone == NULL) {
return KNOT_EINVAL;
}
+ /* Heal zone indexes. */
+ hattrie_build_index(zone->nodes);
+ hattrie_build_index(zone->nsec3_nodes);
+
// load NSEC3PARAM (needed on adjusting function)
knot_zone_contents_load_nsec3param(zone);
+ hattrie_t *lookup_tree = NULL;
+ if (dupl_check) {
+ lookup_tree = hattrie_create();
+ if (lookup_tree == NULL) {
+ dbg_zone("Failed to create out of zone lookup structure.\n");
+ return KNOT_ERROR;
+ }
+ }
+
knot_zone_adjust_arg_t adjust_arg;
adjust_arg.zone = zone;
adjust_arg.first_node = NULL;
adjust_arg.previous_node = NULL;
+ adjust_arg.lookup_tree = lookup_tree;
adjust_arg.err = KNOT_EOK;
/*
* First of all we must set node.prev pointers, as these are used in
* the search functions.
- *
- * We must also set flags, as these are required to set the prev
- * pointers well.
*/
dbg_zone("Setting 'prev' pointers to NSEC3 nodes.\n");
- int ret = knot_zone_tree_forward_apply_inorder(zone->nsec3_nodes,
- knot_zone_contents_adjust_nsec3_node_in_tree_ptr, &adjust_arg);
+ int ret = knot_zone_tree_apply_inorder(zone->nsec3_nodes,
+ knot_zone_contents_adjust_nsec3_node_in_tree_ptr, &adjust_arg);
assert(ret == KNOT_EOK);
if (adjust_arg.err != KNOT_EOK) {
dbg_zone("Failed to set 'prev' pointers to NSEC3 nodes: %s\n",
- knot_strerror(adjust_arg.err));
+ knot_strerror(adjust_arg.err));
+ hattrie_free(lookup_tree);
return adjust_arg.err;
}
// set the last node as previous of the first node
if (adjust_arg.first_node) {
knot_node_set_previous(adjust_arg.first_node,
- adjust_arg.previous_node);
+ adjust_arg.previous_node);
+ }
+ if (first_nsec3_node) {
+ *first_nsec3_node = adjust_arg.first_node;
+ }
+ if (last_nsec3_node) {
+ *last_nsec3_node = adjust_arg.previous_node;
}
dbg_zone("Done.\n");
@@ -2464,13 +1747,14 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone)
adjust_arg.previous_node = NULL;
dbg_zone("Setting 'prev' pointers to normal nodes.\n");
- ret = knot_zone_tree_forward_apply_inorder(zone->nodes,
- knot_zone_contents_adjust_node_in_tree_ptr, &adjust_arg);
+ ret = knot_zone_tree_apply_inorder(zone->nodes,
+ knot_zone_contents_adjust_node_in_tree_ptr, &adjust_arg);
assert(ret == KNOT_EOK);
if (adjust_arg.err != KNOT_EOK) {
dbg_zone("Failed to set 'prev' pointers to normal nodes: %s\n",
- knot_strerror(adjust_arg.err));
+ knot_strerror(adjust_arg.err));
+ hattrie_free(lookup_tree);
return adjust_arg.err;
}
@@ -2486,60 +1770,35 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone)
*/
dbg_zone("Adjusting NSEC3 nodes.\n");
- ret = knot_zone_tree_forward_apply_inorder(zone->nsec3_nodes,
- knot_zone_contents_adjust_nsec3_node_in_tree, &adjust_arg);
+ ret = knot_zone_tree_apply_inorder(zone->nsec3_nodes,
+ knot_zone_contents_adjust_nsec3_node_in_tree, &adjust_arg);
assert(ret == KNOT_EOK);
if (adjust_arg.err != KNOT_EOK) {
dbg_zone("Failed to adjust NSEC3 nodes: %s\n",
- knot_strerror(adjust_arg.err));
+ knot_strerror(adjust_arg.err));
+ hattrie_free(lookup_tree);
return adjust_arg.err;
}
dbg_zone("Adjusting normal nodes.\n");
- ret = knot_zone_tree_forward_apply_inorder(zone->nodes,
- knot_zone_contents_adjust_node_in_tree,
- &adjust_arg);
+ ret = knot_zone_tree_apply_inorder(zone->nodes,
+ knot_zone_contents_adjust_node_in_tree,
+ &adjust_arg);
assert(ret == KNOT_EOK);
if (adjust_arg.err != KNOT_EOK) {
dbg_zone("Failed to adjust normal nodes: %s\n",
- knot_strerror(adjust_arg.err));
+ knot_strerror(adjust_arg.err));
+ hattrie_free(lookup_tree);
return adjust_arg.err;
}
dbg_zone("Done.\n");
- return ret;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_zone_contents_check_loops(knot_zone_contents_t *zone)
-{
- if (zone == NULL) {
- return KNOT_EINVAL;
- }
-
- dbg_zone("Checking CNAME and wildcard loops.\n");
-
- loop_check_data_t data;
- data.err = KNOT_EOK;
- data.zone = zone;
-
- assert(zone->nodes != NULL);
- knot_zone_tree_forward_apply_inorder(zone->nodes,
- knot_zone_contents_check_loops_in_tree,
- (void *)&data);
-
- if (data.err != KNOT_EOK) {
- dbg_zone("Found CNAME loop in data. Aborting transfer.\n");
- return data.err;
- }
+ hattrie_free(lookup_tree);
- dbg_zone("Done\n");
-
- return KNOT_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -2551,11 +1810,15 @@ int knot_zone_contents_load_nsec3param(knot_zone_contents_t *zone)
}
const knot_rrset_t *rrset = knot_node_rrset(zone->apex,
- KNOT_RRTYPE_NSEC3PARAM);
+ KNOT_RRTYPE_NSEC3PARAM);
if (rrset != NULL) {
int r = knot_nsec3_params_from_wire(&zone->nsec3_params, rrset);
- assert(r == KNOT_EOK);
+ if (r != KNOT_EOK) {
+ dbg_zone("Failed to load NSEC3PARAM (%s).\n",
+ knot_strerror(r));
+ return r;
+ }
} else {
memset(&zone->nsec3_params, 0, sizeof(knot_nsec3_params_t));
}
@@ -2572,7 +1835,7 @@ int knot_zone_contents_nsec3_enabled(const knot_zone_contents_t *zone)
}
return (zone->nsec3_params.algorithm != 0
- && zone->nsec3_nodes->th_root != NULL);
+ && knot_zone_tree_weight(zone->nsec3_nodes) != 0);
}
/*----------------------------------------------------------------------------*/
@@ -2593,24 +1856,6 @@ const knot_nsec3_params_t *knot_zone_contents_nsec3params(
/*----------------------------------------------------------------------------*/
-int knot_zone_contents_tree_apply_postorder(knot_zone_contents_t *zone,
- void (*function)(knot_node_t *node, void *data),
- void *data)
-{
- if (zone == NULL) {
- return KNOT_EINVAL;
- }
-
- knot_zone_tree_func_t f;
- f.func = function;
- f.data = data;
-
- return knot_zone_tree_forward_apply_postorder(zone->nodes,
- knot_zone_tree_apply, &f);
-}
-
-/*----------------------------------------------------------------------------*/
-
int knot_zone_contents_tree_apply_inorder(knot_zone_contents_t *zone,
void (*function)(knot_node_t *node, void *data),
void *data)
@@ -2623,8 +1868,8 @@ int knot_zone_contents_tree_apply_inorder(knot_zone_contents_t *zone,
f.func = function;
f.data = data;
- return knot_zone_tree_forward_apply_inorder(zone->nodes,
- knot_zone_tree_apply, &f);
+ return knot_zone_tree_apply_inorder(zone->nodes,
+ tree_apply_cb, &f);
}
/*----------------------------------------------------------------------------*/
@@ -2641,26 +1886,8 @@ int knot_zone_contents_tree_apply_inorder_reverse(
f.func = function;
f.data = data;
- return knot_zone_tree_reverse_apply_inorder(zone->nodes,
- knot_zone_tree_apply, &f);
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_zone_contents_nsec3_apply_postorder(knot_zone_contents_t *zone,
- void (*function)(knot_node_t *node, void *data),
- void *data)
-{
- if (zone == NULL) {
- return KNOT_EINVAL;
- }
-
- knot_zone_tree_func_t f;
- f.func = function;
- f.data = data;
-
- return knot_zone_tree_forward_apply_postorder(
- zone->nsec3_nodes, knot_zone_tree_apply, &f);
+ return knot_zone_tree_apply_recursive(zone->nodes,
+ tree_apply_cb, &f);
}
/*----------------------------------------------------------------------------*/
@@ -2677,8 +1904,8 @@ int knot_zone_contents_nsec3_apply_inorder(knot_zone_contents_t *zone,
f.func = function;
f.data = data;
- return knot_zone_tree_forward_apply_inorder(
- zone->nsec3_nodes, knot_zone_tree_apply, &f);
+ return knot_zone_tree_apply_inorder(
+ zone->nsec3_nodes, tree_apply_cb, &f);
}
/*----------------------------------------------------------------------------*/
@@ -2695,8 +1922,8 @@ int knot_zone_contents_nsec3_apply_inorder_reverse(
f.func = function;
f.data = data;
- return knot_zone_tree_reverse_apply_inorder(
- zone->nsec3_nodes, knot_zone_tree_apply, &f);
+ return knot_zone_tree_apply_recursive(
+ zone->nsec3_nodes, tree_apply_cb, &f);
}
/*----------------------------------------------------------------------------*/
@@ -2717,31 +1944,6 @@ knot_zone_tree_t *knot_zone_contents_get_nsec3_nodes(
/*----------------------------------------------------------------------------*/
-ck_hash_table_t *knot_zone_contents_get_hash_table(
- knot_zone_contents_t *contents)
-{
- return contents->table;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_zone_contents_dname_table_apply(knot_zone_contents_t *contents,
- void (*function)(knot_dname_t *,
- void *),
- void *data)
-{
- if (contents == NULL || function == NULL) {
- return KNOT_EINVAL;
- }
-
- knot_dname_table_tree_inorder_apply(contents->dname_table,
- function, data);
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
knot_zone_contents_t **to)
{
@@ -2757,7 +1959,7 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
int ret = KNOT_EOK;
knot_zone_contents_t *contents = (knot_zone_contents_t *)calloc(
- 1, sizeof(knot_zone_contents_t));
+ 1, sizeof(knot_zone_contents_t));
if (contents == NULL) {
ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
@@ -2765,35 +1967,6 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
contents->apex = from->apex;
- contents->nodes = malloc(sizeof(knot_zone_tree_t));
- if (contents->nodes == NULL) {
- ERR_ALLOC_FAILED;
- ret = KNOT_ENOMEM;
- goto cleanup;
- }
-
- contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t));
- if (contents->nsec3_nodes == NULL) {
- ERR_ALLOC_FAILED;
- ret = KNOT_ENOMEM;
- goto cleanup;
- }
-
- if (from->dname_table != NULL) {
- contents->dname_table = knot_dname_table_new();
- if (contents->dname_table == NULL) {
- ERR_ALLOC_FAILED;
- ret = KNOT_ENOMEM;
- goto cleanup;
- }
- if ((ret = knot_dname_table_shallow_copy(from->dname_table,
- contents->dname_table)) != KNOT_EOK) {
- goto cleanup;
- }
- } else {
- contents->dname_table = NULL;
- }
-
contents->node_count = from->node_count;
contents->flags = from->flags;
@@ -2804,25 +1977,12 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
sizeof(knot_nsec3_params_t));
if ((ret = knot_zone_tree_shallow_copy(from->nodes,
- contents->nodes)) != KNOT_EOK
+ &contents->nodes)) != KNOT_EOK
|| (ret = knot_zone_tree_shallow_copy(from->nsec3_nodes,
- contents->nsec3_nodes)) != KNOT_EOK) {
+ &contents->nsec3_nodes)) != KNOT_EOK) {
goto cleanup;
}
-#ifdef USE_HASH_TABLE
- if (from->table != NULL) {
-// ret = ck_copy_table(from->table, &contents->table);
- ret = ck_shallow_copy(from->table, &contents->table);
- if (ret != 0) {
- dbg_zone_verb("knot_zone_contents_shallow_copy: "
- "hash table copied\n");
- ret = KNOT_ERROR;
- goto cleanup;
- }
- }
-#endif
-
dbg_zone("knot_zone_contents_shallow_copy: finished OK\n");
*to = contents;
@@ -2831,7 +1991,6 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
cleanup:
knot_zone_tree_free(&contents->nodes);
knot_zone_tree_free(&contents->nsec3_nodes);
- free(contents->dname_table);
free(contents);
return ret;
}
@@ -2853,7 +2012,7 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
int ret = KNOT_EOK;
knot_zone_contents_t *contents = (knot_zone_contents_t *)calloc(
- 1, sizeof(knot_zone_contents_t));
+ 1, sizeof(knot_zone_contents_t));
if (contents == NULL) {
ERR_ALLOC_FAILED;
return KNOT_ENOMEM;
@@ -2861,35 +2020,6 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
//contents->apex = from->apex;
- contents->nodes = malloc(sizeof(knot_zone_tree_t));
- if (contents->nodes == NULL) {
- ERR_ALLOC_FAILED;
- ret = KNOT_ENOMEM;
- goto cleanup;
- }
-
- contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t));
- if (contents->nsec3_nodes == NULL) {
- ERR_ALLOC_FAILED;
- ret = KNOT_ENOMEM;
- goto cleanup;
- }
-
- if (from->dname_table != NULL) {
- contents->dname_table = knot_dname_table_new();
- if (contents->dname_table == NULL) {
- ERR_ALLOC_FAILED;
- ret = KNOT_ENOMEM;
- goto cleanup;
- }
- if ((ret = knot_dname_table_shallow_copy(from->dname_table,
- contents->dname_table)) != KNOT_EOK) {
- goto cleanup;
- }
- } else {
- contents->dname_table = NULL;
- }
-
contents->node_count = from->node_count;
contents->flags = from->flags;
// set the 'new' flag
@@ -2898,23 +2028,12 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
contents->zone = from->zone;
if ((ret = knot_zone_tree_deep_copy(from->nodes,
- contents->nodes)) != KNOT_EOK
+ &contents->nodes)) != KNOT_EOK
|| (ret = knot_zone_tree_deep_copy(from->nsec3_nodes,
- contents->nsec3_nodes)) != KNOT_EOK) {
+ &contents->nsec3_nodes)) != KNOT_EOK) {
goto cleanup;
}
-#ifdef USE_HASH_TABLE
- if (from->table != NULL) {
- ret = ck_deep_copy(from->table, &contents->table);
- if (ret != 0) {
- dbg_zone_verb("knot_zone_contents_shallow_copy: "
- "hash table copied\n");
- ret = KNOT_ERROR;
- goto cleanup;
- }
- }
-#endif
contents->apex = knot_node_get_new_node(from->apex);
dbg_zone("knot_zone_contents_shallow_copy: finished OK\n");
@@ -2925,7 +2044,6 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
cleanup:
knot_zone_tree_free(&contents->nodes);
knot_zone_tree_free(&contents->nsec3_nodes);
- free(contents->dname_table);
free(contents);
return ret;
}
@@ -2942,14 +2060,7 @@ void knot_zone_contents_free(knot_zone_contents_t **contents)
knot_zone_tree_free(&(*contents)->nodes);
knot_zone_tree_free(&(*contents)->nsec3_nodes);
-#ifdef USE_HASH_TABLE
- if ((*contents)->table != NULL) {
- ck_destroy_table(&(*contents)->table, NULL, 0);
- }
-#endif
knot_nsec3_params_free(&(*contents)->nsec3_params);
-
- knot_dname_table_free(&(*contents)->dname_table);
free(*contents);
*contents = NULL;
@@ -2957,43 +2068,28 @@ void knot_zone_contents_free(knot_zone_contents_t **contents)
/*----------------------------------------------------------------------------*/
-void knot_zone_contents_deep_free(knot_zone_contents_t **contents,
- int destroy_dname_table)
+void knot_zone_contents_deep_free(knot_zone_contents_t **contents)
{
if (contents == NULL || *contents == NULL) {
return;
}
if ((*contents) != NULL) {
-
-#ifdef USE_HASH_TABLE
- if ((*contents)->table != NULL) {
- ck_destroy_table(&(*contents)->table, NULL, 0);
- }
-#endif
/* has to go through zone twice, rdata may contain references to
node owners earlier in the zone which may be already freed */
/* NSEC3 tree is deleted first as it may contain references to
the normal tree. */
- knot_zone_tree_reverse_apply_postorder(
+ knot_zone_tree_apply_recursive(
(*contents)->nsec3_nodes,
knot_zone_contents_destroy_node_rrsets_from_tree,
(void*)1);
- knot_zone_tree_reverse_apply_postorder(
- (*contents)->nsec3_nodes,
- knot_zone_contents_destroy_node_owner_from_tree, 0);
-
- knot_zone_tree_reverse_apply_postorder(
+ knot_zone_tree_apply_recursive(
(*contents)->nodes,
knot_zone_contents_destroy_node_rrsets_from_tree,
(void*)1);
- knot_zone_tree_reverse_apply_postorder(
- (*contents)->nodes,
- knot_zone_contents_destroy_node_owner_from_tree, 0);
-
// free the zone tree, but only the structure
// (nodes are already destroyed)
dbg_zone("Destroying zone tree.\n");
@@ -3002,16 +2098,6 @@ void knot_zone_contents_deep_free(knot_zone_contents_t **contents,
knot_zone_tree_free(&(*contents)->nsec3_nodes);
knot_nsec3_params_free(&(*contents)->nsec3_params);
-
- if (destroy_dname_table) {
- /*
- * Hack, used in zcompile - destroys the table using
- * dname_free() instead of dname_retain().
- */
- knot_dname_table_destroy(&(*contents)->dname_table);
- } else {
- knot_dname_table_deep_free(&(*contents)->dname_table);
- }
}
free((*contents));
@@ -3040,7 +2126,7 @@ static void knot_zc_integrity_check_previous(const knot_node_t *node,
// first, check if the previous and next pointers are set properly
if (check_data->previous != NULL) {
char *name_prev = knot_dname_to_str(
- knot_node_owner(check_data->previous));
+ knot_node_owner(check_data->previous));
if (knot_node_previous(node) != check_data->previous) {
char *name2 = knot_dname_to_str(knot_node_owner(
@@ -3066,8 +2152,8 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node,
if (node == knot_zone_contents_apex(check_data->contents)) {
if (!knot_node_is_auth(node)) {
fprintf(stderr, "Wrong flags: node %s, flags: %u. "
- "Should be non-authoritative.\n", name,
- node->flags);
+ "Should be non-authoritative.\n", name,
+ node->flags);
++check_data->errors;
}
return;
@@ -3076,12 +2162,12 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node,
// check the flags
if (check_data->deleg_point != NULL
&& knot_dname_is_subdomain(knot_node_owner(node),
- knot_node_owner(check_data->deleg_point))) {
+ knot_node_owner(check_data->deleg_point))) {
// this is a non-authoritative node
if (!knot_node_is_non_auth(node)) {
fprintf(stderr, "Wrong flags: node %s, flags: %u. "
- "Should be non-authoritative.\n", name,
- node->flags);
+ "Should be non-authoritative.\n", name,
+ node->flags);
++check_data->errors;
}
} else {
@@ -3089,8 +2175,8 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node,
// this is a delegation point
if (!knot_node_is_deleg_point(node)) {
fprintf(stderr, "Wrong flags: node %s, flags: "
- "%u. Should be deleg. point.\n", name,
- node->flags);
+ "%u. Should be deleg. point.\n", name,
+ node->flags);
++check_data->errors;
}
check_data->deleg_point = node;
@@ -3098,8 +2184,8 @@ static void knot_zc_integrity_check_flags(const knot_node_t *node,
// this is an authoritative node
if (!knot_node_is_auth(node)) {
fprintf(stderr, "Wrong flags: node %s, flags: "
- "%u. Should be authoritative.\n", name,
- node->flags);
+ "%u. Should be authoritative.\n", name,
+ node->flags);
++check_data->errors;
}
check_data->deleg_point = NULL;
@@ -3139,11 +2225,11 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node,
const knot_node_t *parent = knot_node_parent(node);
if (parent != check_data->parent) {
char *name2 = (parent != NULL)
- ? knot_dname_to_str(
- knot_node_owner(parent))
- : "none";
+ ? knot_dname_to_str(
+ knot_node_owner(parent))
+ : "none";
fprintf(stderr, "Wrong parent: node %s, parent %s. "
- " Should be %s\n", name, name2, pname);
+ " Should be %s\n", name, name2, pname);
if (parent != NULL) {
free(name2);
}
@@ -3157,14 +2243,14 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node,
&& knot_node_wildcard_child(check_data->parent)
!= node) {
char *wc = (knot_node_wildcard_child(
- check_data->parent) == NULL)
+ check_data->parent) == NULL)
? strdup("none")
: knot_dname_to_str(knot_node_owner(
- knot_node_wildcard_child(
- check_data->parent)));
+ knot_node_wildcard_child(
+ check_data->parent)));
fprintf(stderr, "Wrong wildcard child: node %s,"
- " wildcard child: %s. Should be %s\n",
- pname, wc, name);
+ " wildcard child: %s. Should be %s\n",
+ pname, wc, name);
if (knot_node_wildcard_child(
check_data->parent) != NULL) {
}
@@ -3181,24 +2267,6 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node,
/*----------------------------------------------------------------------------*/
-static void knot_zc_integrity_check_rrset_count(const knot_node_t *node,
- check_data_t *check_data,
- const char *name)
-{
- // count RRSets
- int real_count = knot_node_count_rrsets(node);
- int count = knot_node_rrset_count(node);
-
- if (count != real_count) {
- fprintf(stderr, "Wrong RRSet count: node %s, count %d. "
- "Should be %d\n", name, count, real_count);
-
- ++check_data->errors;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
typedef struct find_dname_data {
const knot_dname_t *to_find;
const knot_dname_t *found;
@@ -3206,132 +2274,25 @@ typedef struct find_dname_data {
/*----------------------------------------------------------------------------*/
-void find_in_dname_table(knot_dname_t *dname, void *data)
-{
- assert(dname != NULL);
- assert(data != NULL);
-
- find_dname_data_t *fdata = (find_dname_data_t *)data;
-
- if (fdata->found != NULL) {
- return;
- }
-
- if (knot_dname_compare(dname, fdata->to_find) == 0) {
- fdata->found = dname;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int knot_zc_integrity_check_find_dname(const knot_zone_contents_t *zone,
- const knot_dname_t *to_find,
- const char *node_name)
-{
- int ret = 0;
- if (!zone || !to_find || !node_name) {
- return KNOT_EINVAL;
- }
-
- knot_dname_t *found = knot_dname_table_find_dname(zone->dname_table,
- (knot_dname_t *)to_find);
-
- char *to_find_name = knot_dname_to_str(to_find);
-
- if (!found || found != to_find) {
- fprintf(stderr, "Dname not stored in dname table: "
- "node %s, name %s, found some dname: %s\n", node_name,
- to_find_name, (found != NULL) ? "yes" : "no");
- fprintf(stderr, "Dname to find: %p, found dname: %p\n",
- found, to_find);
- ret = 1;
- }
-
- free(to_find_name);
-
- knot_dname_release(found);
-
- return ret;
-}
-
-/*----------------------------------------------------------------------------*/
-
static void knot_zc_integrity_check_owner(const knot_node_t *node,
check_data_t *check_data,
const char *name)
{
// check node stored in owner
const knot_node_t *owner_node =
- knot_dname_node(knot_node_owner(node));
+ knot_dname_node(knot_node_owner(node));
if (owner_node != node) {
char *name2 = (owner_node != NULL)
- ? knot_dname_to_str(knot_node_owner(owner_node))
- : "none";
+ ? knot_dname_to_str(knot_node_owner(owner_node))
+ : "none";
fprintf(stderr, "Wrong owner's node: node %s, owner's node %s"
- "\n", name, name2);
+ "\n", name, name2);
if (owner_node != NULL) {
free(name2);
}
++check_data->errors;
}
-
- // check if the owner is stored in dname table
- check_data->errors += knot_zc_integrity_check_find_dname(
- check_data->contents, knot_node_owner(node), name);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void knot_zc_integrity_check_dnames_in_rrset(const knot_rrset_t *rrset,
- check_data_t *check_data,
- const char *name)
-{
- // check owner of the RRSet
- check_data->errors += knot_zc_integrity_check_find_dname(
- check_data->contents,
- knot_rrset_owner(rrset), name);
-
- knot_rrtype_descriptor_t *desc = knot_rrtype_descriptor_by_type(
- knot_rrset_type(rrset));
-
- assert(desc != NULL);
-
- const knot_rdata_t *rdata = knot_rrset_rdata(rrset);
- while (rdata != NULL) {
- for (int i = 0; i < knot_rdata_item_count(rdata); ++i) {
- if (desc->wireformat[i]
- == KNOT_RDATA_WF_COMPRESSED_DNAME
- || desc->wireformat[i]
- == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || desc->wireformat[i]
- == KNOT_RDATA_WF_LITERAL_DNAME) {
- knot_rdata_item_t *item = knot_rdata_get_item(
- rdata, i);
- check_data->errors +=
- knot_zc_integrity_check_find_dname(
- check_data->contents, item->dname, name);
- }
- }
- rdata = knot_rrset_rdata_next(rrset, rdata);
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void knot_zc_integrity_check_dnames(const knot_node_t *node,
- check_data_t *check_data,
- const char *name)
-{
- // check all dnames in all RRSets - both owners and in RDATA
- const knot_rrset_t **rrsets = knot_node_rrsets(node);
- if (rrsets != NULL) {
- for (int i = 0; i < knot_node_rrset_count(node); ++i) {
- knot_zc_integrity_check_dnames_in_rrset(rrsets[i],
- check_data, name);
- }
- }
- free(rrsets);
}
/*----------------------------------------------------------------------------*/
@@ -3356,15 +2317,9 @@ static void knot_zc_integrity_check_node(knot_node_t *node, void *data)
// & wildcard child
knot_zc_integrity_check_parent(node, check_data, name);
- // check RRSet count
- knot_zc_integrity_check_rrset_count(node, check_data, name);
-
// check owner
knot_zc_integrity_check_owner(node, check_data, name);
- // check dnames
- knot_zc_integrity_check_dnames(node, check_data, name);
-
/*! \todo Check NSEC3 node. */
free(name);
@@ -3390,74 +2345,70 @@ static void knot_zc_integrity_check_nsec3(knot_node_t *node, void *data)
// check if the node is child of the zone apex
if (node->parent != check_data->parent) {
fprintf(stderr, "NSEC3 node's parent is not apex. Node: %s.\n",
- name);
+ name);
++check_data->errors;
}
- // check RRSet count
- knot_zc_integrity_check_rrset_count(node, check_data, name);
-
// check owner
knot_zc_integrity_check_owner(node, check_data, name);
- // check dnames
- knot_zc_integrity_check_dnames(node, check_data, name);
-
free(name);
}
/*----------------------------------------------------------------------------*/
-void reset_child_count(knot_zone_tree_node_t *tree_node, void *data)
+void reset_child_count(knot_node_t **tnode, void *data)
{
- assert(tree_node != NULL);
+ assert(tnode != NULL);
assert(data != NULL);
+ knot_node_t *node = *tnode;
knot_node_t **apex_copy = (knot_node_t **)data;
if (*apex_copy == NULL) {
- *apex_copy = tree_node->node;
+ *apex_copy = node;
}
- if (tree_node->node != NULL) {
- tree_node->node->children = 0;
+ if (tnode != NULL) {
+ node->children = 0;
}
}
/*----------------------------------------------------------------------------*/
-void count_children(knot_zone_tree_node_t *tree_node, void *data)
+void count_children(knot_node_t **tnode, void *data)
{
UNUSED(data);
- if (tree_node->node != NULL && tree_node->node->parent != NULL) {
- assert(tree_node->node->parent->new_node != NULL);
+ knot_node_t *node = *tnode;
+ if (node != NULL && node->parent != NULL) {
+ assert(node->parent->new_node != NULL);
// fix parent pointer
- tree_node->node->parent = tree_node->node->parent->new_node;
- ++tree_node->node->parent->children;
+ node->parent = node->parent->new_node;
+ ++node->parent->children;
}
}
/*----------------------------------------------------------------------------*/
-void check_child_count(knot_zone_tree_node_t *tree_node, void *data)
+void check_child_count(knot_node_t **tnode, void *data)
{
- assert(tree_node != NULL);
+ assert(tnode != NULL);
assert(data != NULL);
check_data_t *check_data = (check_data_t *)data;
- knot_node_t *node = tree_node->node;
+ knot_node_t *node = *tnode;
// find corresponding node in the given contents
const knot_node_t *found = NULL;
found = knot_zone_contents_find_node(check_data->contents,
- knot_node_owner(node));
+ knot_node_owner(node));
assert(found != NULL);
if (knot_node_children(node) != knot_node_children(found)) {
char *name = knot_dname_to_str(knot_node_owner(node));
fprintf(stderr, "Wrong children count: node (%p) %s, count %u. "
- "Should be %u (%p)\n", found, name,
- knot_node_children(found),
- knot_node_children(node), node);
+ "Should be %u (%p)\n", found, name,
+ knot_node_children(found),
+ knot_node_children(node), node);
free(name);
++check_data->errors;
@@ -3466,26 +2417,25 @@ void check_child_count(knot_zone_tree_node_t *tree_node, void *data)
/*----------------------------------------------------------------------------*/
-static void reset_new_nodes(knot_zone_tree_node_t *tree_node, void *data)
+static void reset_new_nodes(knot_node_t **tnode, void *data)
{
- assert(tree_node != NULL);
+ assert(tnode != NULL);
UNUSED(data);
- knot_node_t *node = tree_node->node;
+ knot_node_t *node = *tnode;
knot_node_set_new_node(node, NULL);
}
/*----------------------------------------------------------------------------*/
-static void count_nsec3_nodes(knot_zone_tree_node_t *tree_node, void *data)
+static void count_nsec3_nodes(knot_node_t **tnode, void *data)
{
- assert(tree_node != NULL);
- assert(tree_node->node != NULL);
+ assert(tnode != NULL);
assert(data != NULL);
knot_node_t *apex = (knot_node_t *)data;
assert(apex != NULL);
-
+
apex->children += 1;
}
@@ -3496,44 +2446,40 @@ int knot_zc_integrity_check_child_count(check_data_t *data)
int errors = 0;
// do shallow copy of the node tree
- knot_zone_tree_t *nodes_copy = (knot_zone_tree_t *)
- malloc(sizeof(knot_zone_tree_t));
+ knot_zone_tree_t *nodes_copy = NULL;
+
+ int ret = knot_zone_tree_deep_copy(data->contents->nodes, &nodes_copy);
+ assert(ret == KNOT_EOK);
if (nodes_copy == NULL) {
return 1;
}
- knot_zone_tree_init(nodes_copy);
-
- int ret = knot_zone_tree_deep_copy(data->contents->nodes, nodes_copy);
- assert(ret == KNOT_EOK);
-
-
// set children count of all nodes to 0
// in the same walkthrough find the apex
knot_node_t *apex_copy = NULL;
- knot_zone_tree_forward_apply_inorder(nodes_copy, reset_child_count,
- (void *)&apex_copy);
+ knot_zone_tree_apply_inorder(nodes_copy, reset_child_count,
+ (void *)&apex_copy);
assert(apex_copy != NULL);
// now count children of all nodes, presuming the parent pointers are ok
- knot_zone_tree_forward_apply_inorder(nodes_copy, count_children, NULL);
+ knot_zone_tree_apply_inorder(nodes_copy, count_children, NULL);
// add count of NSEC3 nodes to the apex' children count
fprintf(stderr, "Children count of new apex before NSEC3: %d\n",
- data->contents->apex->new_node->children);
- knot_zone_tree_forward_apply_inorder(data->contents->nsec3_nodes,
- count_nsec3_nodes,
- (void *)apex_copy);
+ data->contents->apex->new_node->children);
+ knot_zone_tree_apply_inorder(data->contents->nsec3_nodes,
+ count_nsec3_nodes,
+ (void *)apex_copy);
// now compare the children counts
// iterate over the old zone and search for nodes in the copy
- knot_zone_tree_forward_apply_inorder(nodes_copy, check_child_count,
- (void *)data);
+ knot_zone_tree_apply_inorder(nodes_copy, check_child_count,
+ (void *)data);
// cleanup old zone tree - reset pointers to new node to NULL
- knot_zone_tree_forward_apply_inorder(data->contents->nodes,
- reset_new_nodes, NULL);
+ knot_zone_tree_apply_inorder(data->contents->nodes,
+ reset_new_nodes, NULL);
// destroy the shallow copy
knot_zone_tree_deep_free(&nodes_copy);
@@ -3570,8 +2516,8 @@ int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents)
data.contents = contents;
int ret = knot_zone_contents_tree_apply_inorder(
- (knot_zone_contents_t *)contents,
- knot_zc_integrity_check_node, (void *)&data);
+ (knot_zone_contents_t *)contents,
+ knot_zc_integrity_check_node, (void *)&data);
assert(ret == KNOT_EOK);
// if OK, we can continue with checking children count
@@ -3585,10 +2531,74 @@ int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents)
data.children = 0;
data.parent = contents->apex;
ret = knot_zone_contents_nsec3_apply_inorder(
- (knot_zone_contents_t *)contents,
- knot_zc_integrity_check_nsec3, (void *)&data);
+ (knot_zone_contents_t *)contents,
+ knot_zc_integrity_check_nsec3, (void *)&data);
assert(ret == KNOT_EOK);
return data.errors;
}
+struct dname_lookup_data {
+ const knot_dname_t *dname;
+ const knot_dname_t *found_dname;
+ int stopped;
+};
+
+static void find_dname_in_rdata(knot_node_t **tnode, void *data)
+{
+ struct dname_lookup_data *in_data = (struct dname_lookup_data *)data;
+ if (in_data->stopped) {
+ return;
+ }
+
+ /* For all RRSets in node. */
+ const knot_rrset_t **rrsets = knot_node_rrsets_no_copy(*tnode);
+ if (rrsets == NULL) {
+ return;
+ }
+
+ for (uint16_t i = 0; i < (*tnode)->rrset_count; i++) {
+ knot_dname_t **dname = NULL;
+ while ((dname = knot_rrset_get_next_dname(rrsets[i], dname))) {
+ if (*dname == in_data->dname) {
+ in_data->found_dname = *dname;
+ in_data->stopped = 1;
+ return;
+ } else if (knot_dname_compare(*dname,
+ in_data->dname) == 0) {
+ in_data->found_dname = *dname;
+ in_data->stopped = 1;
+ return;
+ }
+ }
+ }
+
+ assert(in_data->stopped == 0);
+}
+
+const knot_dname_t *knot_zone_contents_find_dname_in_rdata(
+ const knot_zone_contents_t *zone,
+ const knot_dname_t *dname)
+{
+ struct dname_lookup_data data;
+ data.stopped = 0;
+ data.dname = dname;
+ data.found_dname = NULL;
+ knot_zone_tree_apply_inorder(zone->nodes,
+ find_dname_in_rdata, &data);
+ if (data.stopped) {
+ /* Dname found. */
+ return data.found_dname;
+ } else {
+ assert(data.found_dname == NULL);
+ return NULL;
+ }
+}
+
+unsigned knot_zone_serial(const knot_zone_contents_t *zone)
+{
+ if (!zone) return 0;
+ const knot_rrset_t *soa = NULL;
+ soa = knot_node_rrset(knot_zone_contents_apex(zone), KNOT_RRTYPE_SOA);
+ return knot_rrset_rdata_soa_serial(soa);
+}
diff --git a/src/libknot/zone/zone-contents.h b/src/libknot/zone/zone-contents.h
index 52eaa40..19ba512 100644
--- a/src/libknot/zone/zone-contents.h
+++ b/src/libknot/zone/zone-contents.h
@@ -27,14 +27,9 @@
#ifndef _KNOT_ZONE_CONTENTS_H_
#define _KNOT_ZONE_CONTENTS_H_
-//#include <time.h>
-
#include "zone/node.h"
#include "dname.h"
#include "nsec3.h"
-#include "zone/dname-table.h"
-#include "common/tree.h"
-#include "hash/cuckoo-hash-table.h"
#include "zone-tree.h"
@@ -45,23 +40,20 @@ struct knot_zone;
typedef struct knot_zone_contents_t {
knot_node_t *apex; /*!< Apex node of the zone (holding SOA) */
- ck_hash_table_t *table; /*!< Hash table for holding zone nodes. */
knot_zone_tree_t *nodes;
knot_zone_tree_t *nsec3_nodes;
- knot_dname_table_t *dname_table;
-
struct knot_zone *zone;
knot_nsec3_params_t nsec3_params;
-
+
/*!
* \todo Unify the use of this field - authoritative nodes vs. all.
*/
- uint node_count;
+ size_t node_count;
/*! \brief Various flags
- *
+ *
* Two rightmost bits denote zone contents generation.
*
* Possible values:
@@ -77,11 +69,15 @@ typedef struct knot_zone_contents_t {
uint8_t flags;
} knot_zone_contents_t;
+/*!< \brief Helper linked list list for CNAME loop checking */
+typedef struct cname_chain {
+ const knot_node_t *node;
+ struct cname_chain *next;
+} cname_chain_t;
+
/*----------------------------------------------------------------------------*/
knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
- uint node_count,
- int use_domain_table,
struct knot_zone *zone);
int knot_zone_contents_gen_is_old(const knot_zone_contents_t *contents);
@@ -119,7 +115,7 @@ uint16_t knot_zone_contents_class(const knot_zone_contents_t *contents);
*/
int knot_zone_contents_add_node(knot_zone_contents_t *contents,
knot_node_t *node, int create_parents,
- uint8_t flags, int use_domain_table);
+ uint8_t flags);
/*!
* \brief Adds a RRSet to the given zone.
@@ -146,14 +142,12 @@ int knot_zone_contents_add_node(knot_zone_contents_t *contents,
int knot_zone_contents_add_rrset(knot_zone_contents_t *contents,
knot_rrset_t *rrset,
knot_node_t **node,
- knot_rrset_dupl_handling_t dupl,
- int use_domain_table);
+ knot_rrset_dupl_handling_t dupl);
int knot_zone_contents_add_rrsigs(knot_zone_contents_t *contents,
knot_rrset_t *rrsigs,
knot_rrset_t **rrset, knot_node_t **node,
- knot_rrset_dupl_handling_t dupl,
- int use_domain_table);
+ knot_rrset_dupl_handling_t dupl);
/*!
* \brief Adds a node holding NSEC3 records to the given zone.
@@ -172,30 +166,18 @@ int knot_zone_contents_add_rrsigs(knot_zone_contents_t *contents,
*/
int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *contents,
knot_node_t *node, int create_parents,
- uint8_t flags, int use_domain_table);
+ uint8_t flags);
int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *contents,
knot_rrset_t *rrset,
knot_node_t **node,
- knot_rrset_dupl_handling_t dupl,
- int use_domain_table);
+ knot_rrset_dupl_handling_t dupl);
-int knot_zone_contents_remove_node(knot_zone_contents_t *contents,
- const knot_node_t *node, knot_zone_tree_node_t **removed_tree,
- ck_hash_table_item_t **removed_hash);
+int knot_zone_contents_remove_node(knot_zone_contents_t *contents,
+ const knot_node_t *node, knot_node_t **removed_tree);
-int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents,
- const knot_node_t *node, knot_zone_tree_node_t **removed);
-
-/*!
- * \warning Always call knot_zone_adjust_dnames() prior to calling this
- * function. Otherwise the node count would not be set.
- *
- * \note Currently, all nodes (even non-authoritative) are inserted into the
- * hash table.
- */
-int knot_zone_contents_create_and_fill_hash_table(
- knot_zone_contents_t *contents);
+int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents,
+ const knot_node_t *node, knot_node_t **removed);
/*!
* \brief Tries to find a node with the specified name in the zone.
@@ -275,28 +257,6 @@ const knot_node_t *knot_zone_contents_find_previous_nsec3(
knot_node_t *knot_zone_contents_get_previous_nsec3(
const knot_zone_contents_t *contents, const knot_dname_t *name);
-#ifdef USE_HASH_TABLE
-/*!
- * \brief Tries to find domain name in the given zone using the hash table.
- *
- * \param[in] zone Zone to search for the name.
- * \param[in] name Domain name to search for.
- * \param[out] node The found node (if it was found, otherwise it may contain
- * arbitrary node).
- * \param[out] closest_encloser Closest encloser of the given name in the zone.
- * \param[out] previous Previous domain name in canonical order.
- *
- * \retval KNOT_ZONE_NAME_FOUND if node with owner \a name was found.
- * \retval KNOT_ZONE_NAME_NOT_FOUND if it was not found.
- * \retval KNOT_EINVAL
- * \retval KNOT_EBADZONE
- */
-int knot_zone_contents_find_dname_hash(const knot_zone_contents_t *contents,
- const knot_dname_t *name,
- const knot_node_t **node,
- const knot_node_t **closest_encloser);
-#endif
-
/*!
* \brief Tries to find a node with the specified name among the NSEC3 nodes
* of the zone.
@@ -354,10 +314,15 @@ knot_node_t *knot_zone_contents_get_apex(
/*!
* \brief Optimizes zone by replacing domain names in RDATA with references to
* domain names present in zone (as node owners).
- *
+ * \param first_nsec3_node First node in NSEC3 tree - needed in sem. checks.
+ * Will not be saved if set to NULL.
+ * \param last_nsec3_node Last node in NSEC3 tree - needed in sem. checks.
+ * Will not be saved if set to NULL.
* \param zone Zone to adjust domain names in.
*/
-int knot_zone_contents_adjust(knot_zone_contents_t *contents);
+int knot_zone_contents_adjust(knot_zone_contents_t *contents,
+ knot_node_t **first_nsec3_node,
+ knot_node_t **last_nsec3_node, int dupl_check);
int knot_zone_contents_check_loops(knot_zone_contents_t *zone);
@@ -410,20 +375,6 @@ const knot_nsec3_params_t *knot_zone_contents_nsec3params(
/*!
* \brief Applies the given function to each regular node in the zone.
*
- * This function uses post-order depth-first forward traversal, i.e. the
- * function is first recursively applied to subtrees and then to the root.
- *
- * \param zone Nodes of this zone will be used as parameters for the function.
- * \param function Function to be applied to each node of the zone.
- * \param data Arbitrary data to be passed to the function.
- */
-int knot_zone_contents_tree_apply_postorder(knot_zone_contents_t *contents,
- void (*function)(knot_node_t *node, void *data),
- void *data);
-
-/*!
- * \brief Applies the given function to each regular node in the zone.
- *
* This function uses in-order depth-first forward traversal, i.e. the function
* is first recursively applied to left subtree, then to the root and then to
* the right subtree.
@@ -460,21 +411,6 @@ int knot_zone_contents_tree_apply_inorder_reverse(
/*!
* \brief Applies the given function to each NSEC3 node in the zone.
*
- * This function uses post-order depth-first forward traversal, i.e. the
- * function is first recursively applied to subtrees and then to the root.
- *
- * \param zone NSEC3 nodes of this zone will be used as parameters for the
- * function.
- * \param function Function to be applied to each node of the zone.
- * \param data Arbitrary data to be passed to the function.
- */
-int knot_zone_contents_nsec3_apply_postorder(knot_zone_contents_t *contents,
- void (*function)(knot_node_t *node, void *data),
- void *data);
-
-/*!
- * \brief Applies the given function to each NSEC3 node in the zone.
- *
* This function uses in-order depth-first forward traversal, i.e. the function
* is first recursively applied to left subtree, then to the root and then to
* the right subtree.
@@ -516,9 +452,6 @@ knot_zone_tree_t *knot_zone_contents_get_nodes(
knot_zone_tree_t *knot_zone_contents_get_nsec3_nodes(
knot_zone_contents_t *contents);
-ck_hash_table_t *knot_zone_contents_get_hash_table(
- knot_zone_contents_t *contents);
-
int knot_zone_contents_dname_table_apply(knot_zone_contents_t *contents,
void (*function)(knot_dname_t *,
void *),
@@ -548,11 +481,46 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
void knot_zone_contents_free(knot_zone_contents_t **contents);
-void knot_zone_contents_deep_free(knot_zone_contents_t **contents,
- int destroy_dname_table);
+void knot_zone_contents_deep_free(knot_zone_contents_t **contents);
int knot_zone_contents_integrity_check(const knot_zone_contents_t *contents);
+const knot_dname_t *knot_zone_contents_find_dname_in_rdata(
+ const knot_zone_contents_t *zone,
+ const knot_dname_t *dname);
+
+/*!
+ * \brief Creates a NSEC3 hashed name for the given domain name.
+ *
+ * \note The zone's NSEC3PARAM record must be parsed prior to calling this
+ * function (see knot_zone_load_nsec3param()).
+ *
+ * \param zone Zone from which to take the NSEC3 parameters.
+ * \param name Domain name to hash.
+ * \param nsec3_name Hashed name.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_ENSEC3PAR
+ * \retval KNOT_ECRYPTO
+ * \retval KNOT_ERROR if an error occured while creating a new domain name
+ * from the hash or concatenating it with the zone name.
+ */
+int knot_zone_contents_nsec3_name(const knot_zone_contents_t *zone,
+ const knot_dname_t *name,
+ knot_dname_t **nsec3_name);
+
+void knot_zone_contents_insert_dname_into_table(knot_dname_t **in_dname,
+ hattrie_t *lookup_tree);
+
+/*!
+ * \brief Fetch zone serial.
+ *
+ * \param zone Zone.
+ *
+ * \return serial or 0
+ */
+unsigned knot_zone_serial(const knot_zone_contents_t *zone);
+
#endif
/*! @} */
diff --git a/src/libknot/zone/zone-diff.c b/src/libknot/zone/zone-diff.c
index a4efff9..009aa31 100644
--- a/src/libknot/zone/zone-diff.c
+++ b/src/libknot/zone/zone-diff.c
@@ -14,13 +14,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <assert.h>
#include <config.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <inttypes.h>
#include "libknot/util/debug.h"
-#include "libknot/rdata.h"
+#include "common/errcode.h"
#include "zone-diff.h"
#include "libknot/nameserver/name-server.h"
+#include "common/descriptor.h"
struct zone_diff_param {
const knot_zone_contents_t *contents;
@@ -58,8 +61,8 @@ static int knot_zone_diff_load_soas(const knot_zone_contents_t *zone1,
return KNOT_EINVAL;
}
- if (knot_rrset_rdata(soa_rrset1) == NULL ||
- knot_rrset_rdata(soa_rrset2) == NULL) {
+ if (knot_rrset_rdata_rr_count(soa_rrset1) == 0 ||
+ knot_rrset_rdata_rr_count(soa_rrset2) == 0) {
dbg_zonediff("zone_diff: "
"both zones must have apex nodes with SOA "
"RRs.\n");
@@ -67,34 +70,34 @@ static int knot_zone_diff_load_soas(const knot_zone_contents_t *zone1,
}
int64_t soa_serial1 =
- knot_rdata_soa_serial(knot_rrset_rdata(soa_rrset1));
+ knot_rrset_rdata_soa_serial(soa_rrset1);
if (soa_serial1 == -1) {
dbg_zonediff("zone_diff: load_soas: Got bad SOA.\n");
}
int64_t soa_serial2 =
- knot_rdata_soa_serial(knot_rrset_rdata(soa_rrset2));
-
+ knot_rrset_rdata_soa_serial(soa_rrset2);
+
if (soa_serial2 == -1) {
dbg_zonediff("zone_diff: load_soas: Got bad SOA.\n");
- }
+ }
if (ns_serial_compare(soa_serial1, soa_serial2) == 0) {
dbg_zonediff("zone_diff: "
"second zone must have higher serial than the "
- "first one. (%lld vs. %lld)\n",
+ "first one. (%"PRId64" vs. %"PRId64")\n",
soa_serial1, soa_serial2);
return KNOT_ENODIFF;
}
-
+
if (ns_serial_compare(soa_serial1, soa_serial2) > 0) {
dbg_zonediff("zone_diff: "
"second zone must have higher serial than the "
- "first one. (%lld vs. %lld)\n",
+ "first one. (%"PRId64" vs. %"PRId64")\n",
soa_serial1, soa_serial2);
return KNOT_ERANGE;
}
-
+
/* We will not touch SOA later, now is the time to handle RRSIGs. */
int ret = knot_zone_diff_rdata(knot_rrset_rrsigs(soa_rrset1),
knot_rrset_rrsigs(soa_rrset2),
@@ -112,9 +115,9 @@ static int knot_zone_diff_load_soas(const knot_zone_contents_t *zone1,
dbg_zonediff("zone_diff: load_soas: Cannot copy RRSet.\n");
return ret;
}
-
+
/* We MUST NOT save this RRSIG. */
- knot_rrset_deep_free(&changeset->soa_from->rrsigs, 1, 1, 1);
+ knot_rrset_deep_free(&changeset->soa_from->rrsigs, 1, 1);
assert(changeset->soa_from->rrsigs == NULL);
ret = knot_rrset_deep_copy(soa_rrset2, &changeset->soa_to, 1);
@@ -122,14 +125,14 @@ static int knot_zone_diff_load_soas(const knot_zone_contents_t *zone1,
dbg_zonediff("zone_diff: load_soas: Cannot copy RRSet.\n");
return ret;
}
-
- knot_rrset_deep_free(&changeset->soa_to->rrsigs, 1, 1, 1);
+
+ knot_rrset_deep_free(&changeset->soa_to->rrsigs, 1, 1);
assert(changeset->soa_to->rrsigs == NULL);
-
+
changeset->serial_from = soa_serial1;
changeset->serial_to = soa_serial2;
-
- dbg_zonediff_verb("zone_diff: load_soas: SOAs diffed. (%lld -> %lld)\n",
+
+ dbg_zonediff_verb("zone_diff: load_soas: SOAs diffed. (%"PRId64" -> %"PRId64")\n",
soa_serial1, soa_serial2);
return KNOT_EOK;
@@ -145,16 +148,16 @@ static int knot_zone_diff_changeset_add_rrset(knot_changeset_t *changeset,
dbg_zonediff("zone_diff: add_rrset: NULL parameters.\n");
return KNOT_EINVAL;
}
-
+
if (knot_rrset_rdata_rr_count(rrset) == 0) {
dbg_zonediff_detail("zone_diff: Nothing to add.\n");
return KNOT_EOK;
}
-
+
dbg_zonediff_detail("zone_diff: add_rrset: Adding RRSet (%d RRs):\n",
knot_rrset_rdata_rr_count(rrset));
- knot_rrset_dump(rrset, 1);
-
+ knot_rrset_dump(rrset);
+
knot_rrset_t *rrset_copy = NULL;
int ret = knot_rrset_deep_copy(rrset, &rrset_copy, 1);
if (ret != KNOT_EOK) {
@@ -162,15 +165,15 @@ static int knot_zone_diff_changeset_add_rrset(knot_changeset_t *changeset,
return ret;
}
if (rrset_copy->rrsigs != NULL) {
- knot_rrset_deep_free(&rrset_copy->rrsigs, 1, 1, 1);
+ knot_rrset_deep_free(&rrset_copy->rrsigs, 1, 1);
}
assert(knot_rrset_rrsigs(rrset_copy) == NULL);
-
+
ret = knot_changeset_add_new_rr(changeset, rrset_copy,
KNOT_CHANGESET_ADD);
if (ret != KNOT_EOK) {
/* We have to free the copy now! */
- knot_rrset_deep_free(&rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
dbg_zonediff("zone_diff: add_rrset: Could not add RRSet. "
"Reason: %s.\n", knot_strerror(ret));
return ret;
@@ -187,21 +190,21 @@ static int knot_zone_diff_changeset_remove_rrset(knot_changeset_t *changeset,
dbg_zonediff("zone_diff: remove_rrset: NULL parameters.\n");
return KNOT_EINVAL;
}
-
+
if (rrset == NULL) {
return KNOT_EOK;
}
-
+
if (knot_rrset_rdata_rr_count(rrset) == 0) {
/* RDATA are the same, however*/
dbg_zonediff_detail("zone_diff: Nothing to remove.\n");
return KNOT_EOK;
}
-
+
dbg_zonediff_detail("zone_diff: remove_rrset: Removing RRSet (%d RRs):\n",
knot_rrset_rdata_rr_count(rrset));
- knot_rrset_dump(rrset, 1);
-
+ knot_rrset_dump(rrset);
+
knot_rrset_t *rrset_copy = NULL;
int ret = knot_rrset_deep_copy(rrset, &rrset_copy, 1);
if (ret != KNOT_EOK) {
@@ -209,16 +212,15 @@ static int knot_zone_diff_changeset_remove_rrset(knot_changeset_t *changeset,
return ret;
}
if (rrset_copy->rrsigs != NULL) {
- knot_rrset_deep_free(&rrset_copy->rrsigs, 1, 1, 1);
+ knot_rrset_deep_free(&rrset_copy->rrsigs, 1, 1);
}
-
assert(knot_rrset_rrsigs(rrset_copy) == NULL);
-
+
ret = knot_changeset_add_new_rr(changeset, rrset_copy,
KNOT_CHANGESET_REMOVE);
if (ret != KNOT_EOK) {
/* We have to free the copy now. */
- knot_rrset_deep_free(&rrset_copy, 1, 1, 1);
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
dbg_zonediff("zone_diff: remove_rrset: Could not remove RRSet. "
"Reason: %s.\n", knot_strerror(ret));
return ret;
@@ -234,7 +236,7 @@ static int knot_zone_diff_add_node(const knot_node_t *node,
dbg_zonediff("zone_diff: add_node: NULL arguments.\n");
return KNOT_EINVAL;
}
-
+
/* Add all rrsets from node. */
const knot_rrset_t **rrsets = knot_node_rrsets(node);
if (rrsets == NULL) {
@@ -253,7 +255,7 @@ static int knot_zone_diff_add_node(const knot_node_t *node,
free(rrsets);
return ret;
}
-
+
if (knot_rrset_rrsigs(rrsets[i])) {
/* Add RRSIGs of the new node. */
ret = knot_zone_diff_changeset_add_rrset(changeset,
@@ -267,9 +269,9 @@ static int knot_zone_diff_add_node(const knot_node_t *node,
}
}
}
-
+
free(rrsets);
-
+
return KNOT_EOK;
}
@@ -280,10 +282,10 @@ static int knot_zone_diff_remove_node(knot_changeset_t *changeset,
dbg_zonediff("zone_diff: remove_node: NULL parameters.\n");
return KNOT_EINVAL;
}
-
+
dbg_zonediff("zone_diff: remove_node: Removing node:\n");
dbg_zonediff_exec_detail(
- knot_node_dump((knot_node_t *)node, 1);
+ knot_node_dump((knot_node_t *)node);
);
const knot_rrset_t **rrsets = knot_node_rrsets(node);
@@ -292,7 +294,7 @@ dbg_zonediff_exec_detail(
"Nothing to remove.\n");
return KNOT_EOK;
}
-
+
dbg_zonediff_detail("zone_diff: remove_node: Will be removing %d RRSets.\n",
knot_node_rrset_count(node));
@@ -320,7 +322,7 @@ dbg_zonediff_exec_detail(
}
}
}
-
+
free(rrsets);
return KNOT_EOK;
@@ -335,7 +337,7 @@ static int knot_zone_diff_rdata_return_changes(const knot_rrset_t *rrset1,
rrset1, rrset2);
return KNOT_EINVAL;
}
-
+
/*
* Take one rdata from first list and search through the second list
* looking for an exact match. If no match occurs, it means that this
@@ -343,10 +345,9 @@ static int knot_zone_diff_rdata_return_changes(const knot_rrset_t *rrset1,
* After the list has been traversed, we have a list of
* changed/removed rdatas. This has awful computation time.
*/
- dbg_zonediff_detail("zone_diff: diff_rdata: Diff of %s, type=%s. "
+ dbg_zonediff_detail("zone_diff: diff_rdata: Diff of %s, type=%u. "
"RR count 1=%d RR count 2=%d.\n",
- knot_dname_to_str(rrset1->owner),
- knot_rrtype_to_string(rrset1->type),
+ knot_dname_to_str(rrset1->owner), rrset1->type,
knot_rrset_rdata_rr_count(rrset1),
knot_rrset_rdata_rr_count(rrset2));
@@ -361,52 +362,41 @@ static int knot_zone_diff_rdata_return_changes(const knot_rrset_t *rrset1,
return KNOT_ENOMEM;
}
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(knot_rrset_type(rrset1));
+ const rdata_descriptor_t *desc =
+ get_rdata_descriptor(knot_rrset_type(rrset1));
assert(desc);
- const knot_rdata_t *tmp_rdata = knot_rrset_rdata(rrset1);
- while(tmp_rdata != NULL) {
- const knot_rdata_t *tmp_rdata_second_rrset =
- knot_rrset_rdata(rrset2);
- while ((tmp_rdata_second_rrset != NULL) &&
- (knot_rdata_compare(tmp_rdata,
- tmp_rdata_second_rrset,
- desc->wireformat) != 0)) {
- tmp_rdata_second_rrset =
- knot_rrset_rdata_next(rrset2,
- tmp_rdata_second_rrset);
- }
- if (tmp_rdata_second_rrset == NULL) {
- /*
- * This means that the while cycle above has finished
- * because the list was traversed - there's no match.
- */
+ for (uint16_t i = 0; i < knot_rrset_rdata_rr_count(rrset1); ++i) {
+ size_t rr_pos = 0;
+ int ret = knot_rrset_find_rr_pos(rrset2, rrset1, i, &rr_pos);
+ if (ret == KNOT_ENOENT) {
+ /* No such RR is present in 'rrset2'. */
dbg_zonediff("zone_diff: diff_rdata: "
"No match for RR (type=%u owner=%s).\n",
knot_rrset_type(rrset1),
knot_dname_to_str(rrset1->owner));
- /* Make a copy of tmp_rdata. */
- knot_rdata_t *tmp_rdata_copy =
- knot_rdata_deep_copy(tmp_rdata,
- knot_rrset_type(rrset1),
- 1);
- int ret = knot_rrset_add_rdata(*changes,
- tmp_rdata_copy);
- /*!< \todo dispose of the copy. */
+ /* We'll copy index 'i' into 'changes' RRSet. */
+ ret = knot_rrset_add_rr_from_rrset(*changes, rrset1, i);
if (ret != KNOT_EOK) {
- dbg_zonediff("zone_diff: diff_rdata: "
- "Could not add rdata to rrset.");
- knot_rrset_deep_free(changes, 1, 1, 0);
+ dbg_zonediff("zone_diff: diff_rdata: Could not"
+ " add RR to RRSet (%s).\n",
+ knot_strerror(ret));
+ knot_rrset_free(changes);
return ret;
}
- } else {
+ } else if (ret == KNOT_EOK) {
+ /* RR in both RRSets. no-op*/
dbg_zonediff_detail("zone_diff: diff_rdata: "
- "Found matching RR for type %s.\n",
- knot_rrtype_to_string(rrset1->type));
+ "Found matching RR for type %d.\n",
+ rrset1->type);
+ } else {
+ dbg_zonediff("zone_diff: diff_rdata: Could not search "
+ "for RR (%s).\n", knot_strerror(ret));
+ knot_rrset_free(changes);
+ return ret;
}
- tmp_rdata = knot_rrset_rdata_next(rrset1, tmp_rdata);
}
+
return KNOT_EOK;
}
@@ -446,56 +436,47 @@ static int knot_zone_diff_rdata(const knot_rrset_t *rrset1,
dbg_zonediff("zone_diff: diff_rdata: These are not the diffs you "
"are looking for.\n");
}
-
+
dbg_zonediff_detail("zone_diff: diff_rdata: To remove:\n");
- knot_rrset_dump(to_remove, 1);
-
+ knot_rrset_dump(to_remove);
+
/*
* to_remove RRSet might be empty, meaning that
* there are no differences in RDATA, but TTLs can differ.
*/
- if (rrset1 && rrset2 &&
+ if (rrset1 && rrset2 &&
(knot_rrset_ttl(rrset1) != knot_rrset_ttl(rrset2)) &&
knot_rrset_rdata_rr_count(to_remove) == 0) {
+ dbg_zonediff_detail("zone_diff: diff_rdata: Remove RR: Old TTL=%"PRIu32", New=%"PRIu32"\n",
+ rrset1->ttl, rrset2->ttl);
/* We have to remove old TTL. */
assert(knot_rrset_ttl(to_remove) == knot_rrset_ttl(rrset1));
/*
* Fill the RDATA so that the change gets saved. All RRs can
* be copied because TTLs are the same for all of them.
*/
- knot_rdata_t *tmp_rdata_copy =
- knot_rdata_deep_copy(knot_rrset_rdata(rrset1),
- knot_rrset_type(rrset1),
- 1);
- if (tmp_rdata_copy == NULL) {
- dbg_zonediff("zone diff: diff_rdata: Cannot copy "
- "RDATA (Different TTLs).\n");
- /* TODO cleanup. */
- return KNOT_ENOMEM;
- }
- int ret = knot_rrset_add_rdata(to_remove, tmp_rdata_copy);
+ knot_rrset_free(&to_remove);
+ int ret = knot_rrset_deep_copy(rrset1, &to_remove, 1);
if (ret != KNOT_EOK) {
- dbg_zonediff("zone diff: diff_rdata: Cannot add "
- "RDATA to RRSet. Reason: %s\n",
- knot_strerror(ret));
- /* TODO cleanup. */
+ dbg_zonediff("zone_diff: diff_rdata: Cannot copy RRSet "
+ "(%s).\n", knot_strerror(ret));
return ret;
}
}
-
+
int ret = knot_zone_diff_changeset_remove_rrset(changeset,
- to_remove);
+ to_remove);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&to_remove, 1, 1, 1);
+ knot_rrset_deep_free(&to_remove, 1, 1);
dbg_zonediff("zone_diff: diff_rdata: Could not remove RRs. "
"Error: %s.\n", knot_strerror(ret));
return ret;
}
-
+
/* Copy was made in add_rrset function, we can free now. */
- knot_rrset_deep_free(&to_remove, 1, 1, 1);
+ knot_rrset_deep_free(&to_remove, 1, 1);
- /* Get RRs to add to zone. */
+ /* Get RRs to add to zone. */ // TODO move to extra function, same for remove
knot_rrset_t *to_add = NULL;
if (rrset2 != NULL && rrset1 == NULL) {
assert(rrset2->type == KNOT_RRTYPE_RRSIG);
@@ -519,10 +500,10 @@ static int knot_zone_diff_rdata(const knot_rrset_t *rrset1,
dbg_zonediff("zone_diff: diff_rdata: These are not the diffs you "
"are looking for.\n");
}
-
+
dbg_zonediff_detail("zone_diff: diff_rdata: To add:\n");
- knot_rrset_dump(to_add, 1);
-
+ knot_rrset_dump(to_add);
+
/*
* to_remove RRSet might be empty, meaning that
* there are no differences in RDATA, but TTLs can differ.
@@ -530,45 +511,36 @@ static int knot_zone_diff_rdata(const knot_rrset_t *rrset1,
if (rrset1 && rrset2 &&
knot_rrset_ttl(rrset1) != knot_rrset_ttl(rrset2)) {
/* We have to add newer TTL. */
- knot_rrset_set_ttl(to_add, knot_rrset_ttl(rrset2));
+ dbg_zonediff_detail("zone_diff: diff_rdata: Add RR: Old TTL=%"PRIu32", New=%"PRIu32"\n",
+ rrset1->ttl, rrset2->ttl);
if (knot_rrset_rdata_rr_count(to_add) == 0) {
/*
* Fill the RDATA so that the change gets saved. All RRs can
* be copied because TTLs are the same for all of them.
*/
- knot_rdata_t *tmp_rdata_copy =
- knot_rdata_deep_copy(knot_rrset_rdata(rrset1),
- knot_rrset_type(rrset1),
- 1);
- if (tmp_rdata_copy == NULL) {
- dbg_zonediff("zone diff: diff_rdata: Cannot copy "
- "RDATA (Different TTLs).\n");
- /* TODO cleanup. */
- return KNOT_ENOMEM;
- }
- int ret = knot_rrset_add_rdata(to_add, tmp_rdata_copy);
+ knot_rrset_free(&to_add);
+ int ret = knot_rrset_deep_copy(rrset1, &to_add, 1);
if (ret != KNOT_EOK) {
- dbg_zonediff("zone diff: diff_rdata: Cannot add "
- "RDATA to RRSet. Reason: %s\n",
- knot_strerror(ret));
- /* TODO cleanup. */
+ dbg_zonediff("zone_diff: diff_rdata: Cannot copy RRSet "
+ "(%s).\n", knot_strerror(ret));
return ret;
}
}
+ knot_rrset_set_ttl(to_add, knot_rrset_ttl(rrset2));
}
ret = knot_zone_diff_changeset_add_rrset(changeset,
to_add);
if (ret != KNOT_EOK) {
- knot_rrset_deep_free(&to_add, 1, 1, 1);
+ knot_rrset_deep_free(&to_add, 1, 1);
dbg_zonediff("zone_diff: diff_rdata: Could not remove RRs. "
- "Error: %s.\n", knot_strerror(ret));
+ "Error: %s.\n", knot_strerror(ret));
return ret;
}
-
+
/* Copy was made in add_rrset function, we can free now. */
- knot_rrset_deep_free(&to_add, 1, 1, 1);
-
+ knot_rrset_deep_free(&to_add, 1, 1);
+
return KNOT_EOK;
}
@@ -610,17 +582,16 @@ static int knot_zone_diff_rrsets(const knot_rrset_t *rrset1,
assert(knot_dname_compare(knot_rrset_owner(rrset1),
knot_rrset_owner(rrset2)) == 0);
assert(knot_rrset_type(rrset1) == knot_rrset_type(rrset2));
-
+
int ret = knot_zone_diff_rdata(knot_rrset_rrsigs(rrset1),
knot_rrset_rrsigs(rrset2), changeset);
if (ret != KNOT_EOK) {
- dbg_zonediff("zone_diff: diff_rrsets (%s:%s): "
- "Failed to diff RRSIGs. "
- "They were: %p %p. (%s).\n",
- knot_dname_to_str(rrset1->owner),
- knot_rrtype_to_string(rrset1->type),
- rrset1->rrsigs,
- rrset2->rrsigs, knot_strerror(ret));
+ dbg_zonediff("zone_diff: diff_rrsets (%s:%u): Failed to diff RRSIGs. "
+ "They were: %p %p. (%s).\n",
+ knot_dname_to_str(rrset1->owner),
+ rrset1->type,
+ rrset1->rrsigs,
+ rrset2->rrsigs, knot_strerror(ret));
}
/* RRs (=rdata) have to be cross-compared, unfortunalely. */
@@ -681,7 +652,7 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
param->ret = KNOT_EOK;
return;
}
-
+
assert(node_in_second_tree != node);
dbg_zonediff_detail("zone_diff: diff_node: Node %s is present in "
@@ -691,7 +662,7 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
if (rrsets == NULL) {
dbg_zonediff("zone_diff: Node in first tree has no RRSets.\n");
/*
- * If there are no RRs in the first tree, all of the RRs
+ * If there are no RRs in the first tree, all of the RRs
* in the second tree will have to be inserted to ADD section.
*/
int ret = knot_zone_diff_add_node(node_in_second_tree,
@@ -709,19 +680,19 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
/* Search for the RRSet in the node from the second tree. */
const knot_rrset_t *rrset = rrsets[i];
assert(rrset);
-
+
/* SOAs are handled explicitly. */
if (knot_rrset_type(rrset) == KNOT_RRTYPE_SOA) {
continue;
}
-
+
const knot_rrset_t *rrset_from_second_node =
knot_node_rrset(node_in_second_tree,
knot_rrset_type(rrset));
if (rrset_from_second_node == NULL) {
dbg_zonediff("zone_diff: diff_node: There is no counterpart "
- "for RRSet of type %s in second tree.\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ "for RRSet of type %u in second tree.\n",
+ knot_rrset_type(rrset));
/* RRSet has been removed. Make a copy and remove. */
assert(rrset);
int ret = knot_zone_diff_changeset_remove_rrset(
@@ -734,7 +705,7 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
free(rrsets);
return;
}
-
+
/* Remove RRSet's RRSIGs as well. */
if (knot_rrset_rrsigs(rrset)) {
ret = knot_zone_diff_changeset_remove_rrset(
@@ -750,8 +721,8 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
}
} else {
dbg_zonediff("zone_diff: diff_node: There is a counterpart "
- "for RRSet of type %s in second tree.\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ "for RRSet of type %u in second tree.\n",
+ knot_rrset_type(rrset));
/* Diff RRSets. */
int ret = knot_zone_diff_rrsets(rrset,
rrset_from_second_node,
@@ -763,7 +734,7 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
free(rrsets);
return;
}
-
+
// dbg_zonediff_verb("zone_diff: diff_node: Changes in "
// "RRSIGs.\n");
// /*! \todo There is ad-hoc solution in the function, maybe handle here. */
@@ -778,15 +749,15 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
// }
}
}
-
+
free(rrsets);
-
+
/*! \todo move to one function with the code above. */
rrsets = knot_node_rrsets(node_in_second_tree);
if (rrsets == NULL) {
dbg_zonediff("zone_diff: Node in second tree has no RRSets.\n");
/*
- * This can happen when node in second
+ * This can happen when node in second
* tree is empty non-terminal and as such has no RRs.
* Whole node from the first tree has to be removed.
*/
@@ -807,19 +778,19 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
/* Search for the RRSet in the node from the second tree. */
const knot_rrset_t *rrset = rrsets[i];
assert(rrset);
-
+
/* SOAs are handled explicitly. */
if (knot_rrset_type(rrset) == KNOT_RRTYPE_SOA) {
continue;
}
-
+
const knot_rrset_t *rrset_from_first_node =
knot_node_rrset(node,
knot_rrset_type(rrset));
if (rrset_from_first_node == NULL) {
dbg_zonediff("zone_diff: diff_node: There is no counterpart "
- "for RRSet of type %s in first tree.\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ "for RRSet of type %u in first tree.\n",
+ knot_rrset_type(rrset));
/* RRSet has been added. Make a copy and add. */
assert(rrset);
int ret = knot_zone_diff_changeset_add_rrset(
@@ -841,7 +812,7 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
"Failed to add RRSIGs.\n");
param->ret = ret;
free(rrsets);
- return;
+ return;
}
}
} else {
@@ -849,7 +820,7 @@ static void knot_zone_diff_node(knot_node_t *node, void *data)
;
}
}
-
+
free(rrsets);
assert(param->ret == KNOT_EOK);
@@ -877,7 +848,7 @@ static void knot_zone_diff_add_new_nodes(knot_node_t *node, void *data)
knot_strerror(param->ret));
return;
}
-
+
/*
* If a node is not present in the second zone, it is a new node
* and has to be added to changeset. Differencies on the RRSet level are
@@ -885,14 +856,14 @@ static void knot_zone_diff_add_new_nodes(knot_node_t *node, void *data)
*/
const knot_zone_contents_t *other_zone = param->contents;
assert(other_zone);
-
+
const knot_dname_t *node_owner = knot_node_owner(node);
/*
* Node should definitely have an owner, otherwise it would not be in
* the tree.
*/
assert(node_owner);
-
+
knot_node_t *new_node = NULL;
if (!param->nsec3) {
new_node = knot_zone_contents_get_node(other_zone, node_owner);
@@ -900,7 +871,7 @@ static void knot_zone_diff_add_new_nodes(knot_node_t *node, void *data)
new_node = knot_zone_contents_get_nsec3_node(other_zone,
node_owner);
}
-
+
if (!new_node) {
assert(node);
int ret = knot_zone_diff_add_node(node, param->changeset);
@@ -911,7 +882,7 @@ static void knot_zone_diff_add_new_nodes(knot_node_t *node, void *data)
knot_strerror(ret));
}
}
-
+
assert(param->ret == KNOT_EOK);
}
@@ -939,9 +910,9 @@ int knot_zone_contents_diff(const knot_zone_contents_t *zone1,
knot_strerror(ret));
return ret;
}
-
+
dbg_zonediff("zone_diff: SOAs loaded.\n");
-
+
/* Traverse one tree, compare every node, each RRSet with its rdata. */
struct zone_diff_param param;
param.contents = zone2;
@@ -1010,24 +981,24 @@ int knot_zone_contents_diff(const knot_zone_contents_t *zone1,
static void knot_zone_diff_dump_changeset(knot_changeset_t *ch)
{
dbg_zonediff_detail("Changeset FROM: %d\n", ch->serial_from);
- rrset_dump_text(ch->soa_from, stderr);
+ knot_rrset_dump(ch->soa_from);
dbg_zonediff_detail("\n");
dbg_zonediff_detail("Changeset TO: %d\n", ch->serial_to);
- rrset_dump_text(ch->soa_to, stderr);
+ knot_rrset_dump(ch->soa_to);
dbg_zonediff_detail("\n");
- dbg_zonediff_detail("Adding %d RRs.\n", ch->add_count);
- dbg_zonediff_detail("Removing %d RRs.\n", ch->remove_count);
-
+ dbg_zonediff_detail("Adding %zu RRs.\n", ch->add_count);
+ dbg_zonediff_detail("Removing %zu RRs.\n", ch->remove_count);
+
dbg_zonediff_detail("ADD section:\n");
dbg_zonediff_detail("**********************************************\n");
for (int i = 0; i < ch->add_count; i++) {
- rrset_dump_text(ch->add[i], stderr);
+ knot_rrset_dump(ch->add[i]);
dbg_zonediff_detail("\n");
}
dbg_zonediff_detail("REMOVE section:\n");
dbg_zonediff_detail("**********************************************\n");
for (int i = 0; i < ch->remove_count; i++) {
- rrset_dump_text(ch->remove[i], stderr);
+ knot_rrset_dump(ch->remove[i]);
dbg_zonediff_detail("\n");
}
}
@@ -1053,9 +1024,9 @@ int knot_zone_diff_create_changesets(const knot_zone_contents_t *z1,
"Reason: %s.\n", knot_strerror(ret));
return ret;
}
-
+
memset((*changesets)->sets, 0, sizeof(knot_changeset_t));
-
+
ret = knot_zone_contents_diff(z1, z2, (*changesets)->sets);
if (ret != KNOT_EOK) {
dbg_zonediff("zone_diff: create_changesets: "
@@ -1063,64 +1034,14 @@ int knot_zone_diff_create_changesets(const knot_zone_contents_t *z1,
"Reason: %s.\n", knot_strerror(ret));
return ret;
}
-
+
(*changesets)->count = 1;
-
+
dbg_zonediff("Changesets created successfully!\n");
dbg_zonediff_detail("Changeset dump:\n");
dbg_zonediff_exec_detail(
knot_zone_diff_dump_changeset((*changesets)->sets);
);
+
return KNOT_EOK;
}
-
-///* Mostly just for testing. We only shall diff zones in memory later. */
-//int knot_zone_diff_zones(const char *zonefile1, const char *zonefile2)
-//{
-// /* Compile test zones. */
-// int ret = zone_read("example.com.", "/home/jan/test/testzone1", "tmpzone1.db", 0);
-// assert(ret == KNOT_EOK);
-// ret = zone_read("example.com.", "/home/jan/test/testzone2", "tmpzone2.db", 0);
-// assert(ret == KNOT_EOK);
-// /* Load test zones. */
-// zloader_t *loader = NULL;
-// int ret = knot_zload_open(&loader, "tmpzone1.db");
-// assert(ret == KNOT_EOK);
-// knot_zone_t *z1 = knot_zload_load(loader);
-// ret = knot_zload_open(&loader, "tmpzone2.db");
-// assert(ret == KNOT_EOK);
-// knot_zone_t *z2 = knot_zload_load(loader);
-// assert(z1 && z2);
-// knot_changeset_t *changeset = malloc(sizeof(knot_changeset_t));
-// memset(changeset, 0, sizeof(knot_changeset_t));
-// assert(knot_zone_contents_diff(z1->contents, z2->contents,
-// changeset) == KNOT_EOK);
-// dbg_zonediff("Changeset created: From=%d to=%d.\n", changeset.serial_from,
-// changeset.serial_to);
-// // knot_changesets_t chngsets;
-// // chngsets->sets = malloc(sizeof(knot_changeset_t));
-// // chngsets->sets[0] = changeset;
-// // chngsets->count = 1;
-// // chngsets->allocated = 1;
-// // knot_zone_contents_t *new_zone = NULL;
-// // ret = xfrin_apply_changesets(z1, chngsets, &new_zone);
-// // if (ret != KNOT_EOK) {
-// // dbg_zonediff("Application of changesets failed. (%s)\n",
-// // knot_strerror(ret));
-// // }
-
-// // assert(new_zone);
-
-// /* Dump creted zone. */
-// // FILE *f = fopen("testovani", "w");
-// // zone_dump_text(new_zone, f);
-
-// knot_zone_deep_free(&z2, 0);
-// knot_zone_deep_free(&z1, 0);
-// // knot_zone_contents_deep_free(&new_zone, 1);
-// // knot_zone_free(&z1);
-
-// knot_free_changeset(&changeset);
-// exit(0);
-//}
-
diff --git a/src/libknot/zone/zone-tree.c b/src/libknot/zone/zone-tree.c
index 1d7991e..27cdf5f 100644
--- a/src/libknot/zone/zone-tree.c
+++ b/src/libknot/zone/zone-tree.c
@@ -14,192 +14,104 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
-#include "zone-tree.h"
#include "zone/node.h"
#include "util/debug.h"
+#include "common/hattrie/hat-trie.h"
/*----------------------------------------------------------------------------*/
/* Non-API functions */
/*----------------------------------------------------------------------------*/
-// AVL tree functions
-TREE_DEFINE(knot_zone_tree_node, avl);
-
-/*----------------------------------------------------------------------------*/
-
-static int knot_zone_tree_node_compare(knot_zone_tree_node_t *node1,
- knot_zone_tree_node_t *node2)
-{
- assert(node1 != NULL);
- assert(node2 != NULL);
- assert(node1->node != NULL);
- assert(node2->node != NULL);
- assert(knot_node_owner(node1->node) != NULL);
- assert(knot_node_owner(node2->node) != NULL);
-
- return knot_node_compare(node1->node, node2->node);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void knot_zone_tree_delete_subtree(knot_zone_tree_node_t *root)
-{
- if (root == NULL) {
- return;
+#define DNAME_LFT_MAXLEN 255 /* maximum lookup format length */
+
+/*!
+ * \brief Convert domain name from wire to lookup format.
+ *
+ * Formats names from rightmost label to the leftmost, separated by the lowest
+ * possible character (\x00). Sorting such formatted names also gives
+ * correct canonical order (for NSEC/NSEC3).
+ *
+ * Example:
+ * Name: lake.example.com. Wire: \x04lake\x07example\x03com\x00
+ * Lookup format com\x00example\x00lake\x00
+ *
+ * Maximum length of such a domain name is DNAME_LFT_MAXLEN characters.
+ *
+ * \param dst Memory to store converted name into.
+ * \param maxlen Maximum memory length.
+ * \param src Source domain name.
+ *
+ * \retval KNOT_EOK if successful
+ * \retval KNOT_ESPACE when not enough memory.
+ * \retval KNOT_EINVAL on invalid parameters
+ */
+static int dname_lf(uint8_t *dst, const knot_dname_t *src, size_t maxlen) {
+ if (src->size > maxlen)
+ return KNOT_ESPACE;
+ *dst = (uint8_t)src->size;
+ /* need to save last \x00 for root dname */
+ if (*dst > 1)
+ *dst -= 1;
+ *++dst = '\0';
+ uint8_t* l = src->name;
+ uint8_t lstack[DNAME_LFT_MAXLEN];
+ uint8_t *sp = lstack;
+ while(*l != 0) { /* build label stack */
+ *sp++ = (l - src->name);
+ l += 1 + *l;
+ }
+ while(sp != lstack) { /* consume stack */
+ l = src->name + *--sp; /* fetch rightmost label */
+ memcpy(dst, l+1, *l); /* write label */
+ dst += *l;
+ *dst++ = '\0'; /* label separator */
}
-
- knot_zone_tree_delete_subtree(root->avl.avl_left);
- knot_zone_tree_delete_subtree(root->avl.avl_right);
- free(root);
+ return KNOT_EOK;
}
-/*----------------------------------------------------------------------------*/
-
-static int knot_zone_tree_copy_node(knot_zone_tree_node_t *from,
- knot_zone_tree_node_t **to)
+static value_t knot_zone_node_copy(value_t v)
{
- if (from == NULL) {
- *to = NULL;
- return KNOT_EOK;
- }
-
- *to = (knot_zone_tree_node_t *)
- malloc(sizeof(knot_zone_tree_node_t));
- if (*to == NULL) {
- return KNOT_ENOMEM;
- }
-
- (*to)->node = from->node;
- (*to)->avl.avl_height = from->avl.avl_height;
-
- int ret = knot_zone_tree_copy_node(from->avl.avl_left,
- &(*to)->avl.avl_left);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- ret = knot_zone_tree_copy_node(from->avl.avl_right,
- &(*to)->avl.avl_right);
- if (ret != KNOT_EOK) {
- knot_zone_tree_delete_subtree((*to)->avl.avl_left);
- (*to)->avl.avl_left = NULL;
- free(*to);
- *to = NULL;
- return ret;
- }
-
- return KNOT_EOK;
+ return v;
}
-/*----------------------------------------------------------------------------*/
-
-static void knot_zone_tree_free_node(knot_zone_tree_node_t *node,
- int free_data)
+static value_t knot_zone_node_deep_copy(value_t v)
{
- if (node == NULL) {
- return;
- }
-
- knot_zone_tree_free_node(node->avl.avl_left, free_data);
-
- knot_zone_tree_free_node(node->avl.avl_right, free_data);
-
- if (free_data) {
- knot_node_free(&node->node);
- }
-
- free(node);
+ knot_node_t *n = NULL;
+ knot_node_shallow_copy((knot_node_t *)v, &n);
+ knot_node_set_new_node((knot_node_t *)v, n);
+ return (value_t)n;
}
/*----------------------------------------------------------------------------*/
+/* API functions */
+/*----------------------------------------------------------------------------*/
-static int knot_zone_tree_deep_copy_node(knot_zone_tree_node_t *from,
- knot_zone_tree_node_t **to)
+knot_zone_tree_t* knot_zone_tree_create()
{
- if (from == NULL) {
- *to = NULL;
- return KNOT_EOK;
- }
-
- *to = (knot_zone_tree_node_t *)malloc(sizeof(knot_zone_tree_node_t));
- if (*to == NULL) {
- return KNOT_ENOMEM;
- }
-
- int ret = knot_node_shallow_copy(from->node, &(*to)->node);
-
- if (ret != KNOT_EOK) {
- dbg_zone_verb("Failed to do shallow copy of node.\n");
- free(*to);
- return ret;
- }
-
- (*to)->avl.avl_height = from->avl.avl_height;
-
- ret = knot_zone_tree_deep_copy_node(from->avl.avl_left,
- &(*to)->avl.avl_left);
- if (ret != KNOT_EOK) {
- dbg_zone_verb("Failed to do shallow copy of left subtree.\n");
- return ret;
- }
-
- ret = knot_zone_tree_deep_copy_node(from->avl.avl_right,
- &(*to)->avl.avl_right);
- if (ret != KNOT_EOK) {
- dbg_zone_verb("Failed to do shallow copy of right subtree.\n");
- knot_zone_tree_free_node((*to)->avl.avl_left, 1);
- (*to)->avl.avl_left = NULL;
- knot_node_free(&(*to)->node);
- free(*to);
- *to = NULL;
- return ret;
- }
-
- knot_node_set_new_node(from->node, (*to)->node);
-
- return KNOT_EOK;
+ return hattrie_create();
}
/*----------------------------------------------------------------------------*/
-/* API functions */
-/*----------------------------------------------------------------------------*/
-int knot_zone_tree_init(knot_zone_tree_t *tree)
+size_t knot_zone_tree_weight(knot_zone_tree_t* tree)
{
- if (tree == NULL) {
- return KNOT_EINVAL;
- }
-
- TREE_INIT(tree, knot_zone_tree_node_compare);
- return KNOT_EOK;
+ return hattrie_weight(tree);
}
/*----------------------------------------------------------------------------*/
int knot_zone_tree_insert(knot_zone_tree_t *tree, knot_node_t *node)
{
- if (tree == NULL || node == NULL) {
- return KNOT_EINVAL;
- }
-
- knot_zone_tree_node_t *znode = (knot_zone_tree_node_t *)malloc(
- sizeof(knot_zone_tree_node_t));
- if (znode == NULL) {
- return KNOT_ENOMEM;
- }
-
- znode->node = node;
- znode->avl.avl_left = NULL;
- znode->avl.avl_right = NULL;
- znode->avl.avl_height = 0;
-
- /*! \todo How to know if this was successful? */
- TREE_INSERT(tree, knot_zone_tree_node, avl, znode);
+ assert(tree && node && node->owner);
+ uint8_t lf[DNAME_LFT_MAXLEN];
+ dname_lf(lf, node->owner, sizeof(lf));
+ *hattrie_get(tree, (char*)lf+1, *lf) = node;
return KNOT_EOK;
}
@@ -211,11 +123,8 @@ int knot_zone_tree_find(knot_zone_tree_t *tree, const knot_dname_t *owner,
if (tree == NULL || owner == NULL || found == NULL) {
return KNOT_EINVAL;
}
-
- knot_node_t *f = NULL;
- int ret = knot_zone_tree_get(tree, owner, &f);
- *found = f;
- return ret;
+
+ return knot_zone_tree_get(tree, owner, (knot_node_t **)found);
}
/*----------------------------------------------------------------------------*/
@@ -227,32 +136,14 @@ int knot_zone_tree_get(knot_zone_tree_t *tree, const knot_dname_t *owner,
return KNOT_EINVAL;
}
- *found = NULL;
-
- // create dummy node to use for lookup
- knot_zone_tree_node_t *tmp = (knot_zone_tree_node_t *)malloc(
- sizeof(knot_zone_tree_node_t));
- if (tmp == NULL) {
- return KNOT_ENOMEM;
- }
-
- // create dummy data node to use for lookup
- knot_node_t *tmp_data = knot_node_new(
- (knot_dname_t *)owner, NULL, 0);
- if (tmp_data == NULL) {
- free(tmp);
- return KNOT_ENOMEM;
- }
- tmp->node = tmp_data;
-
- knot_zone_tree_node_t *n = TREE_FIND(tree, knot_zone_tree_node, avl,
- tmp);
-
- knot_node_free(&tmp_data);
- free(tmp);
+ uint8_t lf[DNAME_LFT_MAXLEN];
+ dname_lf(lf, owner, sizeof(lf));
- if (n != NULL) {
- *found = n->node;
+ value_t *val = hattrie_tryget(tree, (char*)lf+1, *lf);
+ if (val == NULL) {
+ *found = NULL;
+ } else {
+ *found = (knot_node_t*)(*val);
}
return KNOT_EOK;
@@ -268,7 +159,7 @@ int knot_zone_tree_find_less_or_equal(knot_zone_tree_t *tree,
if (tree == NULL || owner == NULL || found == NULL || previous == NULL) {
return KNOT_EINVAL;
}
-
+
knot_node_t *f = NULL, *p = NULL;
int ret = knot_zone_tree_get_less_or_equal(tree, owner, &f, &p);
@@ -290,85 +181,55 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
return KNOT_EINVAL;
}
- knot_zone_tree_node_t *f = NULL, *prev = NULL;
-
- // create dummy node to use for lookup
- knot_zone_tree_node_t *tmp = (knot_zone_tree_node_t *)malloc(
- sizeof(knot_zone_tree_node_t));
- if (tmp == NULL) {
- return KNOT_ENOMEM;
+ uint8_t lf[DNAME_LFT_MAXLEN];
+ dname_lf(lf, owner, sizeof(lf));
+
+ value_t *fval = NULL;
+ int ret = hattrie_find_leq(tree, (char*)lf+1, *lf, &fval);
+ if (fval) *found = (knot_node_t *)(*fval);
+ int exact_match = 0;
+ if (ret == 0) {
+ *previous = knot_node_get_previous(*found);
+ exact_match = 1;
+ } else if (ret < 0) {
+ *previous = *found;
+ *found = NULL;
+ } else if (ret > 0) {
+ /* Previous should be the rightmost node.
+ * For regular zone it is the node left of apex, but for some
+ * cases like NSEC3, there is no such sort of thing (name wise).
+ */
+ /*! \todo We could store rightmost node in zonetree probably. */
+ hattrie_iter_t *i = hattrie_iter_begin(tree, 1);
+ *previous = *(knot_node_t **)hattrie_iter_val(i); /* leftmost */
+ *previous = knot_node_get_previous(*previous); /* rightmost */
+ *found = NULL;
+ hattrie_iter_free(i);
}
- // create dummy data node to use for lookup
- knot_node_t *tmp_data = knot_node_new(
- (knot_dname_t *)owner, NULL, 0);
- if (tmp_data == NULL) {
- free(tmp);
- return KNOT_ENOMEM;
+ /* Check if previous node is not an empty non-terminal. */
+ if (knot_node_rrset_count(*previous) == 0) {
+ *previous = knot_node_get_previous(*previous);
}
- tmp->node = tmp_data;
-
- int exact_match = TREE_FIND_LESS_EQUAL(
- tree, knot_zone_tree_node, avl, tmp, &f, &prev);
-
- knot_node_free(&tmp_data);
- free(tmp);
-
- *found = (exact_match > 0) ? f->node : NULL;
dbg_zone_exec_detail(
char *name = knot_dname_to_str(owner);
- char *name_f = (f != NULL)
- ? knot_dname_to_str(knot_node_owner(f->node))
+ char *name_f = (*found != NULL)
+ ? knot_dname_to_str(knot_node_owner(*found))
: "none";
dbg_zone_detail("Searched for owner %s in zone tree.\n",
name);
dbg_zone_detail("Exact match: %d\n", exact_match);
- dbg_zone_detail("Found node: %p: %s.\n", f, name_f);
- dbg_zone_detail("Previous node: %p.\n", prev);
+ dbg_zone_detail("Found node: %p: %s.\n", *found, name_f);
+ dbg_zone_detail("Previous node: %p.\n", *previous);
free(name);
- if (f != NULL) {
+ if (*found != NULL) {
free(name_f);
}
);
- if (exact_match < 0) {
- // previous is not really previous but should be the leftmost
- // node in the tree; take it's previous
- assert(prev != NULL);
- *previous = knot_node_get_previous(prev->node);
- exact_match = 0;
- } else if (prev == NULL) {
- // either the returned node is the root of the tree, or
- // it is the leftmost node in the tree; in both cases
- // node was found set the previous node of the found
- // node
- assert(exact_match > 0);
- assert(f != NULL);
- *previous = knot_node_get_previous(f->node);
- } else {
- // otherwise check if the previous node is not an empty
- // non-terminal
- /*! \todo Here we assume that the 'prev' pointer always points
- * to an empty non-terminal.
- */
- /*! \todo What did I mean by the previous TODO??
- * Nevertheless, it seems to me that node->prev can be
- * an empty non-terminal too, cannot it?
- */
- dbg_zone_detail("Previous: %p\n", prev->node);
- *previous = (knot_node_rrset_count(prev->node) == 0)
- ? knot_node_get_previous(prev->node)
- : prev->node;
- dbg_zone_detail("Previous: %p, is empty: %d\n", *previous,
- (*previous) ? knot_node_is_empty(*previous)
- : -1);
- }
-
- assert(exact_match >= 0);
-
return exact_match;
}
@@ -376,84 +237,53 @@ dbg_zone_exec_detail(
int knot_zone_tree_remove(knot_zone_tree_t *tree,
const knot_dname_t *owner,
- knot_zone_tree_node_t **removed)
+ knot_node_t **removed)
{
- if (tree == NULL || owner == NULL || removed == NULL) {
+ if (tree == NULL || owner == NULL) {
return KNOT_EINVAL;
}
- // create dummy node to use for lookup
- knot_zone_tree_node_t *tmp = (knot_zone_tree_node_t *)malloc(
- sizeof(knot_zone_tree_node_t));
- if (tmp == NULL) {
- return KNOT_ENOMEM;
- }
+ uint8_t lf[DNAME_LFT_MAXLEN];
+ dname_lf(lf, owner, sizeof(lf));
- // create dummy data node to use for lookup
- knot_node_t *tmp_data = knot_node_new(
- (knot_dname_t *)owner, NULL, 0);
- if (tmp_data == NULL) {
- free(tmp);
- return KNOT_ENOMEM;
+ value_t *rval = hattrie_tryget(tree, (char*)lf+1, *lf);
+ if (rval == NULL) {
+ return KNOT_ENOENT;
+ } else {
+ *removed = (knot_node_t *)(*rval);
}
- tmp->node = tmp_data;
- // we must first find the node, so that it may be destroyed
- knot_zone_tree_node_t *n = TREE_FIND(tree, knot_zone_tree_node, avl,
- tmp);
- /*! \todo How to know if this was successful? */
- TREE_REMOVE(tree, knot_zone_tree_node, avl, tmp);
-
- knot_node_free(&tmp_data);
- free(tmp);
-
- *removed = n;
-
+ hattrie_del(tree, (char*)lf+1, *lf);
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-int knot_zone_tree_forward_apply_inorder(knot_zone_tree_t *tree,
- void (*function)(
- knot_zone_tree_node_t *node,
- void *data),
- void *data)
+int knot_zone_tree_apply_inorder(knot_zone_tree_t *tree,
+ void (*function)(knot_node_t **node,
+ void *data),
+ void *data)
{
if (tree == NULL || function == NULL) {
return KNOT_EINVAL;
}
- TREE_FORWARD_APPLY(tree, knot_zone_tree_node, avl,
- function, data);
-
- return KNOT_EOK;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int knot_zone_tree_forward_apply_postorder(knot_zone_tree_t *tree,
- void (*function)(
- knot_zone_tree_node_t *node,
- void *data),
- void *data)
-{
- if (tree == NULL || function == NULL) {
- return KNOT_EINVAL;
+ hattrie_iter_t *i = hattrie_iter_begin(tree, 1);
+ while(!hattrie_iter_finished(i)) {
+ function((knot_node_t **)hattrie_iter_val(i), data);
+ hattrie_iter_next(i);
}
-
- TREE_POST_ORDER_APPLY(tree, knot_zone_tree_node, avl,
- function, data);
+ hattrie_iter_free(i);
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-int knot_zone_tree_reverse_apply_inorder(knot_zone_tree_t *tree,
+int knot_zone_tree_apply_recursive(knot_zone_tree_t *tree,
void (*function)(
- knot_zone_tree_node_t *node,
+ knot_node_t **node,
void *data),
void *data)
{
@@ -461,26 +291,23 @@ int knot_zone_tree_reverse_apply_inorder(knot_zone_tree_t *tree,
return KNOT_EINVAL;
}
- TREE_REVERSE_APPLY(tree, knot_zone_tree_node, avl,
- function, data);
+ hattrie_apply_rev(tree, (void (*)(value_t*,void*))function, data);
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-int knot_zone_tree_reverse_apply_postorder(knot_zone_tree_t *tree,
- void (*function)(
- knot_zone_tree_node_t *node,
- void *data),
- void *data)
+int knot_zone_tree_apply(knot_zone_tree_t *tree,
+ void (*function)(knot_node_t **node, void *data),
+ void *data)
{
- if (tree == NULL || function == NULL) {
- return KNOT_EINVAL;
+ hattrie_iter_t *i = hattrie_iter_begin(tree, 0);
+ while(!hattrie_iter_finished(i)) {
+ function((knot_node_t **)hattrie_iter_val(i), data);
+ hattrie_iter_next(i);
}
-
- TREE_REVERSE_APPLY_POST(tree, knot_zone_tree_node, avl,
- function, data);
+ hattrie_iter_free(i);
return KNOT_EOK;
}
@@ -488,39 +315,29 @@ int knot_zone_tree_reverse_apply_postorder(knot_zone_tree_t *tree,
/*----------------------------------------------------------------------------*/
int knot_zone_tree_shallow_copy(knot_zone_tree_t *from,
- knot_zone_tree_t *to)
+ knot_zone_tree_t **to)
{
if (to == NULL || from == NULL) {
return KNOT_EINVAL;
}
- /*
- * This function will copy the tree by hand, so that the nodes
- * do not have to be inserted the normal way. It should be substantially
- * faster.
- */
- to->th_cmp = from->th_cmp;
+ *to = hattrie_dup(from, knot_zone_node_copy);
- return knot_zone_tree_copy_node(from->th_root, &to->th_root);
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
int knot_zone_tree_deep_copy(knot_zone_tree_t *from,
- knot_zone_tree_t *to)
+ knot_zone_tree_t **to)
{
if (to == NULL || from == NULL) {
return KNOT_EINVAL;
}
- /*
- * This function will copy the tree by hand, so that the nodes
- * do not have to be inserted the normal way. It should be substantially
- * faster.
- */
- to->th_cmp = from->th_cmp;
+ *to = hattrie_dup(from, knot_zone_node_deep_copy);
- return knot_zone_tree_deep_copy_node(from->th_root, &to->th_root);
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -530,21 +347,49 @@ void knot_zone_tree_free(knot_zone_tree_t **tree)
if (tree == NULL || *tree == NULL) {
return;
}
- knot_zone_tree_free_node((*tree)->th_root, 0);
- free(*tree);
+ hattrie_free(*tree);
*tree = NULL;
}
/*----------------------------------------------------------------------------*/
+static void knot_zone_tree_free_node(knot_node_t **node, void *data)
+{
+ UNUSED(data);
+ if (node) {
+ knot_node_free(node);
+ }
+}
+
void knot_zone_tree_deep_free(knot_zone_tree_t **tree)
{
if (tree == NULL || *tree == NULL) {
return;
}
- knot_zone_tree_free_node((*tree)->th_root, 1);
- free(*tree);
- *tree = NULL;
+
+ knot_zone_tree_apply_recursive(*tree, knot_zone_tree_free_node, NULL);
+ knot_zone_tree_free(tree);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void hattrie_insert_dname(hattrie_t *tr, knot_dname_t *dname)
+{
+ *hattrie_get(tr, (char *)dname->name, dname->size) = dname;
}
/*----------------------------------------------------------------------------*/
+
+knot_dname_t *hattrie_get_dname(hattrie_t *tr, knot_dname_t *dname)
+{
+ if (tr == NULL || dname == NULL) {
+ return NULL;
+ }
+
+ value_t *val = hattrie_tryget(tr, (char *)dname->name, dname->size);
+ if (val == NULL) {
+ return NULL;
+ } else {
+ return (knot_dname_t *)(*val);
+ }
+}
diff --git a/src/libknot/zone/zone-tree.h b/src/libknot/zone/zone-tree.h
index 6c38310..d9172ce 100644
--- a/src/libknot/zone/zone-tree.h
+++ b/src/libknot/zone/zone-tree.h
@@ -29,34 +29,27 @@
#ifndef _KNOT_ZONE_TREE_H_
#define _KNOT_ZONE_TREE_H_
-#include "common/tree.h"
+#include "common/hattrie/hat-trie.h"
#include "zone/node.h"
/*----------------------------------------------------------------------------*/
-typedef struct knot_zone_tree_node {
- /*! \brief Structure for connecting this node to an AVL tree. */
- TREE_ENTRY(knot_zone_tree_node) avl;
- /*! \brief Zone tree data. */
- knot_node_t *node;
-} knot_zone_tree_node_t;
-
-/*----------------------------------------------------------------------------*/
-
-typedef TREE_HEAD(knot_zone_tree, knot_zone_tree_node) knot_zone_tree_t;
+typedef hattrie_t knot_zone_tree_t;
/*----------------------------------------------------------------------------*/
/*!
- * \brief Initializes the zone tree.
- *
- * Does not allocate the structure. Must be called before any use of the tree.
- *
- * \param tree Zone tree structure to initialize.
+ * \brief Creates the zone tree.
*
- * \retval KNOT_EOK
- * \retval KNOT_EINVAL
+ * \return created zone tree structure.
+ */
+knot_zone_tree_t* knot_zone_tree_create();
+
+/*!
+ * \brief Return weight of the zone tree (number of nodes).
+ * \param tree Zone tree.
+ * \return number of nodes in tree.
*/
-int knot_zone_tree_init(knot_zone_tree_t *tree);
+size_t knot_zone_tree_weight(knot_zone_tree_t* tree);
/*!
* \brief Inserts the given node into the zone tree.
@@ -163,7 +156,7 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
*/
int knot_zone_tree_remove(knot_zone_tree_t *tree,
const knot_dname_t *owner,
- knot_zone_tree_node_t **removed);
+ knot_node_t **removed);
/*!
* \brief Applies the given function to each node in the zone.
@@ -182,43 +175,16 @@ int knot_zone_tree_remove(knot_zone_tree_t *tree,
* \retval KNOT_EOK
* \retval KNOT_EINVAL
*/
-int knot_zone_tree_forward_apply_inorder(knot_zone_tree_t *tree,
- void (*function)(
- knot_zone_tree_node_t *node,
- void *data),
- void *data);
-
-/*!
- * \brief Applies the given function to each node in the zone.
- *
- * This function uses post-order depth-first forward traversal, i.e. the
- * function is first recursively applied to subtrees and then to the root.
- *
- * \note This implies that the zone is stored in a binary tree. Is there a way
- * to make this traversal independent on the underlying structure?
- *
- * \param tree Zone tree to apply the function to.
- * \param function Function to be applied to each node of the zone.
- * \param data Arbitrary data to be passed to the function.
- *
- * \retval KNOT_EOK
- * \retval KNOT_EINVAL
- */
-int knot_zone_tree_forward_apply_postorder(knot_zone_tree_t *tree,
- void (*function)(
- knot_zone_tree_node_t *node,
+int knot_zone_tree_apply_inorder(knot_zone_tree_t *tree,
+ void (*function)(knot_node_t **node,
void *data),
- void *data);
+ void *data);
/*!
* \brief Applies the given function to each node in the zone.
*
- * This function uses in-order depth-first reverse traversal, i.e. the function
- * is first recursively applied to right subtree, then to the root and then to
- * the left subtree.
- *
- * \note This implies that the zone is stored in a binary tree. Is there a way
- * to make this traversal independent on the underlying structure?
+ * This function visits leafe nodes before their parents.
+ * But doesn't maintain any specific ordering.
*
* \param tree Zone tree to apply the function to.
* \param function Function to be applied to each node of the zone.
@@ -227,22 +193,15 @@ int knot_zone_tree_forward_apply_postorder(knot_zone_tree_t *tree,
* \retval KNOT_EOK
* \retval KNOT_EINVAL
*/
-int knot_zone_tree_reverse_apply_inorder(knot_zone_tree_t *tree,
+int knot_zone_tree_apply_recursive(knot_zone_tree_t *tree,
void (*function)(
- knot_zone_tree_node_t *node,
+ knot_node_t **node,
void *data),
void *data);
/*!
* \brief Applies the given function to each node in the zone.
*
- * This function uses post-order depth-first reverse traversal, i.e. the
- * function is first recursively applied to right subtree, then to the
- * left subtree and then to the root.
- *
- * \note This implies that the zone is stored in a binary tree. Is there a way
- * to make this traversal independent on the underlying structure?
- *
* \param tree Zone tree to apply the function to.
* \param function Function to be applied to each node of the zone.
* \param data Arbitrary data to be passed to the function.
@@ -250,11 +209,9 @@ int knot_zone_tree_reverse_apply_inorder(knot_zone_tree_t *tree,
* \retval KNOT_EOK
* \retval KNOT_EINVAL
*/
-int knot_zone_tree_reverse_apply_postorder(knot_zone_tree_t *tree,
- void (*function)(
- knot_zone_tree_node_t *node,
- void *data),
- void *data);
+int knot_zone_tree_apply(knot_zone_tree_t *tree,
+ void (*function)(knot_node_t **node, void *data),
+ void *data);
/*!
* \brief Copies the whole zone tree structure (but not the data contained
@@ -269,11 +226,11 @@ int knot_zone_tree_reverse_apply_postorder(knot_zone_tree_t *tree,
* \retval KNOT_EOK
* \retval KNOT_ENOMEM
*/
-int knot_zone_tree_shallow_copy(knot_zone_tree_t *from,
- knot_zone_tree_t *to);
+int knot_zone_tree_shallow_copy(knot_zone_tree_t *from,
+ knot_zone_tree_t **to);
int knot_zone_tree_deep_copy(knot_zone_tree_t *from,
- knot_zone_tree_t *to);
+ knot_zone_tree_t **to);
/*!
* \brief Destroys the zone tree, not touching the saved data.
@@ -291,9 +248,11 @@ void knot_zone_tree_free(knot_zone_tree_t **tree);
*/
void knot_zone_tree_deep_free(knot_zone_tree_t **tree);
+void hattrie_insert_dname(hattrie_t *tr, knot_dname_t *dname);
+knot_dname_t *hattrie_get_dname(hattrie_t *tr, knot_dname_t *dname);
+
/*----------------------------------------------------------------------------*/
#endif // _KNOT_ZONE_TREE_H_
/*! @} */
-
diff --git a/src/libknot/zone/zone.c b/src/libknot/zone/zone.c
index 3ab508e..fe59777 100644
--- a/src/libknot/zone/zone.c
+++ b/src/libknot/zone/zone.c
@@ -25,17 +25,14 @@
#include "zone/zone.h"
#include "zone/node.h"
#include "dname.h"
-#include "util/descriptor.h"
-#include "nsec3.h"
#include "util/debug.h"
#include "util/utils.h"
-#include "hash/cuckoo-hash-table.h"
#include "zone/zone-contents.h"
/*! \brief Adaptor for knot_zone_deep_free() */
static void knot_zone_dtor(struct ref_t *p) {
knot_zone_t *z = (knot_zone_t *)p;
- knot_zone_deep_free(&z, 0);
+ knot_zone_deep_free(&z);
}
/*----------------------------------------------------------------------------*/
@@ -60,20 +57,19 @@ knot_zone_t *knot_zone_new_empty(knot_dname_t *name)
// save the zone name
dbg_zone("Setting zone name.\n");
zone->name = name;
-
+
/* Initialize reference counting. */
ref_init(&zone->ref, knot_zone_dtor);
-
+
/* Set reference counter to 1, caller should release it after use. */
knot_zone_retain(zone);
-
+
return zone;
}
/*----------------------------------------------------------------------------*/
-knot_zone_t *knot_zone_new(knot_node_t *apex, uint node_count,
- int use_domain_table)
+knot_zone_t *knot_zone_new(knot_node_t *apex)
{
knot_zone_t *zone = knot_zone_new_empty(
knot_dname_deep_copy(knot_node_owner(apex)));
@@ -82,8 +78,7 @@ knot_zone_t *knot_zone_new(knot_node_t *apex, uint node_count,
}
dbg_zone("Creating zone contents.\n");
- zone->contents = knot_zone_contents_new(apex, node_count,
- use_domain_table, zone);
+ zone->contents = knot_zone_contents_new(apex, zone);
if (zone->contents == NULL) {
knot_dname_release(zone->name);
free(zone);
@@ -205,7 +200,7 @@ void knot_zone_free(knot_zone_t **zone)
dbg_zone("zone_free().\n");
- if ((*zone)->contents
+ if ((*zone)->contents
&& !knot_zone_contents_gen_is_old((*zone)->contents)) {
// zone is in the middle of an update, report
dbg_zone("Destroying zone that is in the middle of an "
@@ -228,12 +223,12 @@ void knot_zone_free(knot_zone_t **zone)
/*----------------------------------------------------------------------------*/
-void knot_zone_deep_free(knot_zone_t **zone, int destroy_dname_table)
+void knot_zone_deep_free(knot_zone_t **zone)
{
if (zone == NULL || *zone == NULL) {
return;
}
-
+
if ((*zone)->contents
&& !knot_zone_contents_gen_is_old((*zone)->contents)) {
// zone is in the middle of an update, report
@@ -254,7 +249,7 @@ dbg_zone_exec(
(*zone)->dtor(*zone);
}
- knot_zone_contents_deep_free(&(*zone)->contents, destroy_dname_table);
+ knot_zone_contents_deep_free(&(*zone)->contents);
free(*zone);
*zone = NULL;
}
diff --git a/src/libknot/zone/zone.h b/src/libknot/zone/zone.h
index 26a5e2a..5db24a5 100644
--- a/src/libknot/zone/zone.h
+++ b/src/libknot/zone/zone.h
@@ -32,10 +32,7 @@
#include "zone/node.h"
#include "dname.h"
#include "nsec3.h"
-#include "zone/dname-table.h"
-#include "common/tree.h"
#include "common/ref.h"
-#include "hash/cuckoo-hash-table.h"
#include "zone-tree.h"
@@ -105,12 +102,10 @@ knot_zone_t *knot_zone_new_empty(knot_dname_t *name);
* \brief Creates new DNS zone.
*
* \param apex Node representing the zone apex.
- * \param node_count Number of authorative nodes in the zone.
*
* \return The initialized zone structure or NULL if an error occured.
*/
-knot_zone_t *knot_zone_new(knot_node_t *apex, uint node_count,
- int use_domain_table);
+knot_zone_t *knot_zone_new(knot_node_t *apex);
knot_zone_contents_t *knot_zone_get_contents(
const knot_zone_t *zone);
@@ -151,11 +146,8 @@ void knot_zone_free(knot_zone_t **zone);
* Also sets the given pointer to NULL.
*
* \param zone Zone to be freed.
- * \param free_rdata_dnames Set to <> 0 if you want to delete ALL domain names
- * present in RDATA. Set to 0 otherwise. (See
- * knot_rdata_deep_free().)
*/
-void knot_zone_deep_free(knot_zone_t **zone, int destroy_dname_table);
+void knot_zone_deep_free(knot_zone_t **zone);
/*!
* \brief Set destructor and initialize reference counter to 1.
diff --git a/src/libknot/zone/zonedb.c b/src/libknot/zone/zonedb.c
index 5e5c516..3650b24 100644
--- a/src/libknot/zone/zonedb.c
+++ b/src/libknot/zone/zonedb.c
@@ -26,41 +26,10 @@
#include "dname.h"
#include "zone/node.h"
#include "util/debug.h"
-#include "common/general-tree.h"
/*----------------------------------------------------------------------------*/
/* Non-API functions */
/*----------------------------------------------------------------------------*/
-/*!
- * \brief Compares the two arguments interpreted as zone names (domain names).
- *
- * Use this function with generic data structures (such as the skip list).
- *
- * \param d1 First zone name.
- * \param d2 Second zone name.
- *
- * \retval 0 if the two zone names are equal.
- * \retval < 0 if \a d1 is before \a d2 in canonical order.
- * \retval > 0 if \a d1 is after \a d2 in canonical order.
- */
-static int knot_zonedb_compare_zone_names(void *p1, void *p2)
-{
- const knot_zone_t *zone1 = (const knot_zone_t *)p1;
- const knot_zone_t *zone2 = (const knot_zone_t *)p2;
-
- int ret = knot_dname_compare(zone1->name, zone2->name);
-
-dbg_zonedb_exec_detail(
- char *name1 = knot_dname_to_str(zone1->name);
- char *name2 = knot_dname_to_str(zone2->name);
- dbg_zonedb_detail("Compared names %s and %s, result: %d.\n",
- name1, name2, ret);
- free(name1);
- free(name2);
-);
-
- return (ret);
-}
/*----------------------------------------------------------------------------*/
/* API functions */
@@ -72,12 +41,12 @@ knot_zonedb_t *knot_zonedb_new()
(knot_zonedb_t *)malloc(sizeof(knot_zonedb_t));
CHECK_ALLOC_LOG(db, NULL);
- db->zone_tree = gen_tree_new(knot_zonedb_compare_zone_names);
+ db->zone_tree = hattrie_create();
if (db->zone_tree == NULL) {
free(db);
return NULL;
}
-
+
db->zone_count = 0;
return db;
@@ -101,17 +70,19 @@ dbg_zonedb_exec(
ret = knot_zone_contents_load_nsec3param(
knot_zone_get_contents(zone));
if (ret != KNOT_EOK) {
+ log_zone_error("NSEC3 signed zone has invalid or no "
+ "NSEC3PARAM record.\n");
return ret;
}
}
- ret = gen_tree_add(db->zone_tree, zone, NULL);
+ /* Ordered lookup is not required, no dname conversion. */
+ const char *key = (const char*)knot_dname_name(zone->name);
+ size_t klen = knot_dname_size(zone->name);
+ *hattrie_get(db->zone_tree, key, klen) = zone;
+ db->zone_count++;
- if (ret == 0) {
- db->zone_count++;
- }
-
- return (ret != 0) ? KNOT_ERROR : KNOT_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -119,24 +90,20 @@ dbg_zonedb_exec(
knot_zone_t *knot_zonedb_remove_zone(knot_zonedb_t *db,
const knot_dname_t *zone_name)
{
- knot_zone_t dummy_zone;
- memset(&dummy_zone, 0, sizeof(knot_zone_t));
- dummy_zone.name = (knot_dname_t *)zone_name;
-
- // add some lock to avoid multiple removals
- knot_zone_t *z = (knot_zone_t *)gen_tree_find(db->zone_tree,
- &dummy_zone);
-
- if (z == NULL) {
+ /* Fetch if exists. */
+ knot_zone_t *oldzone = knot_zonedb_find_zone(db, zone_name);
+ if (oldzone == NULL) return NULL;
+
+ /* Remove from db. */
+ const char *key = (const char*)knot_dname_name(zone_name);
+ size_t klen = knot_dname_size(zone_name);
+ int ret = hattrie_del(db->zone_tree, key, klen);
+ if (ret < 0) {
return NULL;
}
- // remove the zone from the skip list, but do not destroy it
- gen_tree_remove(db->zone_tree, &dummy_zone);
-
- db->zone_count--;
-
- return z;
+ --db->zone_count;
+ return oldzone;
}
/*----------------------------------------------------------------------------*/
@@ -144,9 +111,11 @@ knot_zone_t *knot_zonedb_remove_zone(knot_zonedb_t *db,
knot_zone_t *knot_zonedb_find_zone(const knot_zonedb_t *db,
const knot_dname_t *zone_name)
{
- knot_zone_t dummy_zone;
- dummy_zone.name = (knot_dname_t *)zone_name;
- return (knot_zone_t *)gen_tree_find(db->zone_tree, &dummy_zone);
+ const char *key = (const char*)knot_dname_name(zone_name);
+ size_t klen = knot_dname_size(zone_name);
+ value_t *val = hattrie_tryget(db->zone_tree, key, klen);
+ if (!val) return NULL;
+ return (knot_zone_t *)*val;
}
/*----------------------------------------------------------------------------*/
@@ -158,31 +127,31 @@ const knot_zone_t *knot_zonedb_find_zone_for_name(knot_zonedb_t *db,
return NULL;
}
- knot_zone_t dummy_zone;
- dummy_zone.name = knot_dname_deep_copy(dname);
- void *found = NULL;
-
- found = gen_tree_find(db->zone_tree, &dummy_zone);
- while (found == NULL && knot_dname_label_count(dummy_zone.name) > 0) {
- knot_dname_left_chop_no_copy(dummy_zone.name);
- found = gen_tree_find(db->zone_tree, &dummy_zone);
+ knot_zone_t *zone = NULL;
+ const char *name = (const char*)dname->name;
+ size_t len = dname->size;
+
+ while (len > 0) {
+ value_t *found = hattrie_tryget(db->zone_tree, name, len);
+ if (found) {
+ zone = (knot_zone_t *)*found;
+ break;
+ } else {
+ /* Take label len + 1 and skip it.
+ * ..from \x04lake\x03com\x00
+ * ..to \x03com\x00
+ */
+ uint8_t to_chop = name[0] + 1;
+ len -= to_chop;
+ name += to_chop;
+ }
}
- knot_zone_t *zone = (found) ? (knot_zone_t *)found : NULL;
-
dbg_zonedb_exec(
- char *name = knot_dname_to_str(dname);
- dbg_zonedb("Found zone for name %s: %p\n", name, zone);
- free(name);
+ char *zname = knot_dname_to_str(dname);
+ dbg_zonedb("Found zone for name %s: %p\n", zname, zone);
+ free(zname);
);
- if (zone != NULL && zone->contents != NULL
- && knot_dname_compare(zone->contents->apex->owner, dname) != 0
- && !knot_dname_is_subdomain(dname, zone->contents->apex->owner)) {
- zone = NULL;
- }
-
- knot_dname_free(&dummy_zone.name);
-
return zone;
}
@@ -213,7 +182,7 @@ knot_zonedb_t *knot_zonedb_copy(const knot_zonedb_t *db)
(knot_zonedb_t *)malloc(sizeof(knot_zonedb_t));
CHECK_ALLOC_LOG(db_new, NULL);
- db_new->zone_tree = gen_tree_shallow_copy(db->zone_tree);
+ db_new->zone_tree = hattrie_dup(db->zone_tree, NULL);
if (db_new->zone_tree == NULL) {
free(db_new);
return NULL;
@@ -256,7 +225,13 @@ const knot_zone_t **knot_zonedb_zones(const knot_zonedb_t *db)
args.count = 0;
CHECK_ALLOC_LOG(args.zones, NULL);
- gen_tree_apply_inorder(db->zone_tree, save_zone_to_array, &args);
+ hattrie_iter_t *i = hattrie_iter_begin(db->zone_tree, 1);
+ while(!hattrie_iter_finished(i)) {
+ save_zone_to_array(*hattrie_iter_val(i), &args);
+ hattrie_iter_next(i);
+ }
+ hattrie_iter_free(i);
+
assert(db->zone_count == args.count);
return args.zones;
@@ -266,29 +241,31 @@ const knot_zone_t **knot_zonedb_zones(const knot_zonedb_t *db)
void knot_zonedb_free(knot_zonedb_t **db)
{
- gen_tree_destroy(&((*db)->zone_tree), NULL ,NULL);
+ hattrie_free((*db)->zone_tree);
free(*db);
*db = NULL;
}
/*----------------------------------------------------------------------------*/
-static void delete_zone_from_db(void *node, void *data)
+static void delete_zone_from_db(value_t *node, void *data)
{
UNUSED(data);
- knot_zone_t *zone = (knot_zone_t *)node;
- assert(zone);
+ assert(node);
+ if (*node == NULL) return;
+
+ knot_zone_t *zone = (knot_zone_t *)(*node);
synchronize_rcu();
knot_zone_set_flag(zone, KNOT_ZONE_DISCARDED, 1);
knot_zone_release(zone);
- zone = NULL;
+ *node = NULL;
}
void knot_zonedb_deep_free(knot_zonedb_t **db)
{
dbg_zonedb("Deleting zone db (%p).\n", *db);
- gen_tree_destroy(&((*db)->zone_tree), delete_zone_from_db, NULL);
- assert((*db)->zone_tree == NULL);
+ hattrie_apply_rev((*db)->zone_tree, delete_zone_from_db, NULL);
+ hattrie_free((*db)->zone_tree);
free(*db);
*db = NULL;
}
diff --git a/src/libknot/zone/zonedb.h b/src/libknot/zone/zonedb.h
index 81326bf..186c718 100644
--- a/src/libknot/zone/zonedb.h
+++ b/src/libknot/zone/zonedb.h
@@ -30,7 +30,7 @@
#ifndef _KNOT_ZONEDB_H_
#define _KNOT_ZONEDB_H_
-#include "common/general-tree.h"
+#include "common/hattrie/hat-trie.h"
#include "zone/zone.h"
#include "zone/node.h"
#include "dname.h"
@@ -39,7 +39,7 @@
* \brief Zone database structure. Contains all zones managed by the server.
*/
struct knot_zonedb {
- general_tree_t *zone_tree; /*!< AVL tree of zones. */
+ hattrie_t *zone_tree; /*!< AVL tree of zones. */
size_t zone_count;
};
@@ -82,7 +82,7 @@ int knot_zonedb_add_zone(knot_zonedb_t *db, knot_zone_t *zone);
* \retval KNOT_EOK
* \retval KNOT_ENOZONE
*/
-knot_zone_t * knot_zonedb_remove_zone(knot_zonedb_t *db,
+knot_zone_t * knot_zonedb_remove_zone(knot_zonedb_t *db,
const knot_dname_t *zone_name);
/*!
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
new file mode 100644
index 0000000..29733b7
--- /dev/null
+++ b/src/tests/Makefile.am
@@ -0,0 +1,74 @@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+
+AM_CPPFLAGS = -I$(top_srcdir)/src/libknot -I$(top_srcdir)/src -DSYSCONFDIR='"$(sysconfdir)"' -DSBINDIR='"$(sbindir)"'
+
+check_PROGRAMS = \
+ unittests \
+ unittests_xfr
+
+TESTS = unittests
+
+EXTRA_DIST = \
+ files/sample_conf
+
+BUILT_SOURCES = \
+ sample_conf.rc
+
+CLEANFILES = \
+ sample_conf.rc
+
+nodist_unittests_SOURCES = \
+ sample_conf.rc
+
+unittests_SOURCES = \
+ common/acl_tests.c \
+ common/acl_tests.h \
+ common/base32hex_tests.c \
+ common/base32hex_tests.h \
+ common/base64_tests.c \
+ common/base64_tests.h \
+ common/descriptor_tests.h \
+ common/descriptor_tests.c \
+ common/events_tests.c \
+ common/events_tests.h \
+ common/fdset_tests.c \
+ common/fdset_tests.h \
+ common/skiplist_tests.c \
+ common/skiplist_tests.h \
+ common/hattrie_tests.c \
+ common/hattrie_tests.h \
+ common/slab_tests.c \
+ common/slab_tests.h \
+ knot/conf_tests.c \
+ knot/conf_tests.h \
+ knot/dthreads_tests.c \
+ knot/dthreads_tests.h \
+ knot/journal_tests.c \
+ knot/journal_tests.h \
+ knot/server_tests.c \
+ knot/server_tests.h \
+ knot/rrl_tests.h \
+ knot/rrl_tests.c \
+ zscanner/zscanner_tests.h \
+ zscanner/zscanner_tests.c \
+ libknot/dname_tests.h \
+ libknot/dname_tests.c \
+ libknot/ztree_tests.h \
+ libknot/ztree_tests.c \
+ libknot/wire_tests.h \
+ libknot/wire_tests.c \
+ libknot/rrset_tests.c \
+ libknot/rrset_tests.h \
+ libknot/sign_tests.c \
+ libknot/sign_tests.h \
+ unittests_main.c
+
+unittests_xfr_SOURCES = \
+ xfr_tests.c \
+ xfr_tests.h
+
+unittests_LDADD = ../libknotd.la ../libknots.la @LIBOBJS@
+unittests_xfr_LDADD = ../libknotd.la ../libknot.la ../libknots.la @LIBOBJS@
+
+sample_conf.rc: files/sample_conf
+ $(top_srcdir)/resource.sh $(srcdir)/files/sample_conf >$@
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
new file mode 100644
index 0000000..df605b8
--- /dev/null
+++ b/src/tests/Makefile.in
@@ -0,0 +1,840 @@
+# Makefile.in generated by automake 1.11.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+check_PROGRAMS = unittests$(EXEEXT) unittests_xfr$(EXEEXT)
+TESTS = unittests$(EXEEXT)
+subdir = src/tests
+DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_compile_flag.m4 \
+ $(top_srcdir)/m4/ax_ext.m4 \
+ $(top_srcdir)/m4/ax_gcc_x86_cpuid.m4 \
+ $(top_srcdir)/m4/ax_recvmmsg.m4 $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/m4/visibility.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/src/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__dirstamp = $(am__leading_dot)dirstamp
+am_unittests_OBJECTS = common/acl_tests.$(OBJEXT) \
+ common/base32hex_tests.$(OBJEXT) common/base64_tests.$(OBJEXT) \
+ common/descriptor_tests.$(OBJEXT) \
+ common/events_tests.$(OBJEXT) common/fdset_tests.$(OBJEXT) \
+ common/skiplist_tests.$(OBJEXT) common/hattrie_tests.$(OBJEXT) \
+ common/slab_tests.$(OBJEXT) knot/conf_tests.$(OBJEXT) \
+ knot/dthreads_tests.$(OBJEXT) knot/journal_tests.$(OBJEXT) \
+ knot/server_tests.$(OBJEXT) knot/rrl_tests.$(OBJEXT) \
+ zscanner/zscanner_tests.$(OBJEXT) \
+ libknot/dname_tests.$(OBJEXT) libknot/ztree_tests.$(OBJEXT) \
+ libknot/wire_tests.$(OBJEXT) libknot/rrset_tests.$(OBJEXT) \
+ libknot/sign_tests.$(OBJEXT) unittests_main.$(OBJEXT)
+nodist_unittests_OBJECTS =
+unittests_OBJECTS = $(am_unittests_OBJECTS) \
+ $(nodist_unittests_OBJECTS)
+unittests_DEPENDENCIES = ../libknotd.la ../libknots.la @LIBOBJS@
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am_unittests_xfr_OBJECTS = xfr_tests.$(OBJEXT)
+unittests_xfr_OBJECTS = $(am_unittests_xfr_OBJECTS)
+unittests_xfr_DEPENDENCIES = ../libknotd.la ../libknot.la \
+ ../libknots.la @LIBOBJS@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(unittests_SOURCES) $(nodist_unittests_SOURCES) \
+ $(unittests_xfr_SOURCES)
+DIST_SOURCES = $(unittests_SOURCES) $(unittests_xfr_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CFLAG_VISIBILITY = @CFLAG_VISIBILITY@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+FSM_TYPE = @FSM_TYPE@
+GREP = @GREP@
+HAVE_VISIBILITY = @HAVE_VISIBILITY@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RAGEL = @RAGEL@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SIMD_FLAGS = @SIMD_FLAGS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libcrypto_CFLAGS = @libcrypto_CFLAGS@
+libcrypto_LIBS = @libcrypto_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+liburcu_CFLAGS = @liburcu_CFLAGS@
+liburcu_LIBS = @liburcu_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+run_dir = @run_dir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+storage_dir = @storage_dir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+ACLOCAL_AMFLAGS = -I $(top_srcdir)/m4
+AM_CPPFLAGS = -I$(top_srcdir)/src/libknot -I$(top_srcdir)/src -DSYSCONFDIR='"$(sysconfdir)"' -DSBINDIR='"$(sbindir)"'
+EXTRA_DIST = \
+ files/sample_conf
+
+BUILT_SOURCES = \
+ sample_conf.rc
+
+CLEANFILES = \
+ sample_conf.rc
+
+nodist_unittests_SOURCES = \
+ sample_conf.rc
+
+unittests_SOURCES = \
+ common/acl_tests.c \
+ common/acl_tests.h \
+ common/base32hex_tests.c \
+ common/base32hex_tests.h \
+ common/base64_tests.c \
+ common/base64_tests.h \
+ common/descriptor_tests.h \
+ common/descriptor_tests.c \
+ common/events_tests.c \
+ common/events_tests.h \
+ common/fdset_tests.c \
+ common/fdset_tests.h \
+ common/skiplist_tests.c \
+ common/skiplist_tests.h \
+ common/hattrie_tests.c \
+ common/hattrie_tests.h \
+ common/slab_tests.c \
+ common/slab_tests.h \
+ knot/conf_tests.c \
+ knot/conf_tests.h \
+ knot/dthreads_tests.c \
+ knot/dthreads_tests.h \
+ knot/journal_tests.c \
+ knot/journal_tests.h \
+ knot/server_tests.c \
+ knot/server_tests.h \
+ knot/rrl_tests.h \
+ knot/rrl_tests.c \
+ zscanner/zscanner_tests.h \
+ zscanner/zscanner_tests.c \
+ libknot/dname_tests.h \
+ libknot/dname_tests.c \
+ libknot/ztree_tests.h \
+ libknot/ztree_tests.c \
+ libknot/wire_tests.h \
+ libknot/wire_tests.c \
+ libknot/rrset_tests.c \
+ libknot/rrset_tests.h \
+ libknot/sign_tests.c \
+ libknot/sign_tests.h \
+ unittests_main.c
+
+unittests_xfr_SOURCES = \
+ xfr_tests.c \
+ xfr_tests.h
+
+unittests_LDADD = ../libknotd.la ../libknots.la @LIBOBJS@
+unittests_xfr_LDADD = ../libknotd.la ../libknot.la ../libknots.la @LIBOBJS@
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnits src/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnits src/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+common/$(am__dirstamp):
+ @$(MKDIR_P) common
+ @: > common/$(am__dirstamp)
+common/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) common/$(DEPDIR)
+ @: > common/$(DEPDIR)/$(am__dirstamp)
+common/acl_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/base32hex_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/base64_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/descriptor_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/events_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/fdset_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/skiplist_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/hattrie_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+common/slab_tests.$(OBJEXT): common/$(am__dirstamp) \
+ common/$(DEPDIR)/$(am__dirstamp)
+knot/$(am__dirstamp):
+ @$(MKDIR_P) knot
+ @: > knot/$(am__dirstamp)
+knot/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) knot/$(DEPDIR)
+ @: > knot/$(DEPDIR)/$(am__dirstamp)
+knot/conf_tests.$(OBJEXT): knot/$(am__dirstamp) \
+ knot/$(DEPDIR)/$(am__dirstamp)
+knot/dthreads_tests.$(OBJEXT): knot/$(am__dirstamp) \
+ knot/$(DEPDIR)/$(am__dirstamp)
+knot/journal_tests.$(OBJEXT): knot/$(am__dirstamp) \
+ knot/$(DEPDIR)/$(am__dirstamp)
+knot/server_tests.$(OBJEXT): knot/$(am__dirstamp) \
+ knot/$(DEPDIR)/$(am__dirstamp)
+knot/rrl_tests.$(OBJEXT): knot/$(am__dirstamp) \
+ knot/$(DEPDIR)/$(am__dirstamp)
+zscanner/$(am__dirstamp):
+ @$(MKDIR_P) zscanner
+ @: > zscanner/$(am__dirstamp)
+zscanner/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) zscanner/$(DEPDIR)
+ @: > zscanner/$(DEPDIR)/$(am__dirstamp)
+zscanner/zscanner_tests.$(OBJEXT): zscanner/$(am__dirstamp) \
+ zscanner/$(DEPDIR)/$(am__dirstamp)
+libknot/$(am__dirstamp):
+ @$(MKDIR_P) libknot
+ @: > libknot/$(am__dirstamp)
+libknot/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) libknot/$(DEPDIR)
+ @: > libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/dname_tests.$(OBJEXT): libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/ztree_tests.$(OBJEXT): libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/wire_tests.$(OBJEXT): libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/rrset_tests.$(OBJEXT): libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+libknot/sign_tests.$(OBJEXT): libknot/$(am__dirstamp) \
+ libknot/$(DEPDIR)/$(am__dirstamp)
+unittests$(EXEEXT): $(unittests_OBJECTS) $(unittests_DEPENDENCIES) $(EXTRA_unittests_DEPENDENCIES)
+ @rm -f unittests$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(unittests_OBJECTS) $(unittests_LDADD) $(LIBS)
+unittests_xfr$(EXEEXT): $(unittests_xfr_OBJECTS) $(unittests_xfr_DEPENDENCIES) $(EXTRA_unittests_xfr_DEPENDENCIES)
+ @rm -f unittests_xfr$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(unittests_xfr_OBJECTS) $(unittests_xfr_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f common/acl_tests.$(OBJEXT)
+ -rm -f common/base32hex_tests.$(OBJEXT)
+ -rm -f common/base64_tests.$(OBJEXT)
+ -rm -f common/descriptor_tests.$(OBJEXT)
+ -rm -f common/events_tests.$(OBJEXT)
+ -rm -f common/fdset_tests.$(OBJEXT)
+ -rm -f common/hattrie_tests.$(OBJEXT)
+ -rm -f common/skiplist_tests.$(OBJEXT)
+ -rm -f common/slab_tests.$(OBJEXT)
+ -rm -f knot/conf_tests.$(OBJEXT)
+ -rm -f knot/dthreads_tests.$(OBJEXT)
+ -rm -f knot/journal_tests.$(OBJEXT)
+ -rm -f knot/rrl_tests.$(OBJEXT)
+ -rm -f knot/server_tests.$(OBJEXT)
+ -rm -f libknot/dname_tests.$(OBJEXT)
+ -rm -f libknot/rrset_tests.$(OBJEXT)
+ -rm -f libknot/sign_tests.$(OBJEXT)
+ -rm -f libknot/wire_tests.$(OBJEXT)
+ -rm -f libknot/ztree_tests.$(OBJEXT)
+ -rm -f zscanner/zscanner_tests.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unittests_main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xfr_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/acl_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/base32hex_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/base64_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/descriptor_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/events_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/fdset_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/hattrie_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/skiplist_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/slab_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/$(DEPDIR)/conf_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/$(DEPDIR)/dthreads_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/$(DEPDIR)/journal_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/$(DEPDIR)/rrl_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@knot/$(DEPDIR)/server_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/dname_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/rrset_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/sign_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/wire_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@libknot/$(DEPDIR)/ztree_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@zscanner/$(DEPDIR)/zscanner_tests.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile
+installdirs:
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f common/$(DEPDIR)/$(am__dirstamp)
+ -rm -f common/$(am__dirstamp)
+ -rm -f knot/$(DEPDIR)/$(am__dirstamp)
+ -rm -f knot/$(am__dirstamp)
+ -rm -f libknot/$(DEPDIR)/$(am__dirstamp)
+ -rm -f libknot/$(am__dirstamp)
+ -rm -f zscanner/$(DEPDIR)/$(am__dirstamp)
+ -rm -f zscanner/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR) common/$(DEPDIR) knot/$(DEPDIR) libknot/$(DEPDIR) zscanner/$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR) common/$(DEPDIR) knot/$(DEPDIR) libknot/$(DEPDIR) zscanner/$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all check check-am install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am
+
+
+sample_conf.rc: files/sample_conf
+ $(top_srcdir)/resource.sh $(srcdir)/files/sample_conf >$@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/tests/README b/src/tests/README
index 2f299ad..1d9748b 100644
--- a/src/tests/README
+++ b/src/tests/README
@@ -2,9 +2,3 @@ Unit testing
------------
Make assembles "unittest" binary with all of the planned tests included.
-So far it is accepting the same parameters as the "cutedns",
-but an own parameter format is being developed.
-
-Example:
-bin/unittest samples/example.com.zone
-
diff --git a/src/tests/common/acl_tests.c b/src/tests/common/acl_tests.c
index c1884cd..f8ab106 100644
--- a/src/tests/common/acl_tests.c
+++ b/src/tests/common/acl_tests.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -117,12 +118,12 @@ static int acl_tests_run(int argc, char *argv[])
sockaddr_set(&test_pf4, AF_INET, "192.168.1.20", 0);
ret = acl_match(acl, &test_pf4, 0);
ok(ret == ACL_ACCEPT, "acl: searching address in matching prefix /24");
-
+
// 15. Attempt to search non-matching subnet
sockaddr_set(&test_pf4, AF_INET, "192.168.2.20", 0);
ret = acl_match(acl, &test_pf4, 0);
ok(ret == ACL_DENY, "acl: searching address in non-matching prefix /24");
-
+
// 16. Attempt to match v6 subnet
sockaddr_t match_pf6, test_pf6;
sockaddr_set(&match_pf6, AF_INET6, "2001:0DB8:0400:000e:0:0:0:AB00", 0);
@@ -131,12 +132,12 @@ static int acl_tests_run(int argc, char *argv[])
sockaddr_set(&test_pf6, AF_INET6, "2001:0DB8:0400:000e:0:0:0:AB03", 0);
ret = acl_match(acl, &test_pf6, 0);
ok(ret == ACL_ACCEPT, "acl: searching v6 address in matching prefix /120");
-
+
// 17. Attempt to search non-matching subnet
sockaddr_set(&test_pf6, AF_INET6, "2001:0DB8:0400:000e:0:0:0:CCCC", 0);
ret = acl_match(acl, &test_pf6, 0);
ok(ret == ACL_DENY, "acl: searching v6 address in non-matching prefix /120");
-
+
// 18. Add preferred node
sockaddr_set(&test_pf4, AF_INET, "192.168.1.20", 0);
void *sval = (void*)0x1234;
@@ -158,7 +159,7 @@ static int acl_tests_run(int argc, char *argv[])
ret = acl_match(acl, &match_pf4, 0);
ok(ret == ACL_ACCEPT, "acl: scenario after truncating");
acl_delete(&acl);
-
+
// Return
return 0;
}
diff --git a/src/tests/common/base32hex_tests.c b/src/tests/common/base32hex_tests.c
index cdfec69..1303e44 100644
--- a/src/tests/common/base32hex_tests.c
+++ b/src/tests/common/base32hex_tests.c
@@ -14,12 +14,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "tests/common/base32hex_tests.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include "common/errcode.h"
#include "common/base32hex.h"
#define BUF_LEN 256
@@ -51,10 +53,14 @@ static int base32hex_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base32hex_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "1. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "1. test vector - ENC output content");
+ endskip;
ret = base32hex_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "1. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "1. test vector - DEC output content");
+ endskip;
// 2. test vector -> ENC -> DEC
strcpy((char *)in, "f");
@@ -63,10 +69,14 @@ static int base32hex_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base32hex_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "2. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "2. test vector - ENC output content");
+ endskip;
ret = base32hex_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "2. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "2. test vector - DEC output content");
+ endskip;
// 3. test vector -> ENC -> DEC
strcpy((char *)in, "fo");
@@ -75,10 +85,14 @@ static int base32hex_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base32hex_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "3. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "3. test vector - ENC output content");
+ endskip;
ret = base32hex_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "3. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "3. test vector - DEC output content");
+ endskip;
// 4. test vector -> ENC -> DEC
strcpy((char *)in, "foo");
@@ -87,10 +101,14 @@ static int base32hex_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base32hex_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "4. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "4. test vector - ENC output content");
+ endskip;
ret = base32hex_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "4. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "4. test vector - DEC output content");
+ endskip;
// 5. test vector -> ENC -> DEC
strcpy((char *)in, "foob");
@@ -99,10 +117,14 @@ static int base32hex_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base32hex_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "5. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "5. test vector - ENC output content");
+ endskip;
ret = base32hex_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "5. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "5. test vector - DEC output content");
+ endskip;
// 6. test vector -> ENC -> DEC
strcpy((char *)in, "fooba");
@@ -111,10 +133,14 @@ static int base32hex_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base32hex_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "6. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "6. test vector - ENC output content");
+ endskip;
ret = base32hex_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "6. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "6. test vector - DEC output content");
+ endskip;
// 7. test vector -> ENC -> DEC
strcpy((char *)in, "foobar");
@@ -123,44 +149,48 @@ static int base32hex_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base32hex_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "7. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "7. test vector - ENC output content");
+ endskip;
ret = base32hex_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "7. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "7. test vector - DEC output content");
+ endskip;
// Bad paddings
ret = base32hex_decode((uint8_t *)"AAAAAA==", 8, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad padding length 2");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ECHAR, "Bad padding length 2");
ret = base32hex_decode((uint8_t *)"AAA=====", 8, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad padding length 5");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ECHAR, "Bad padding length 5");
ret = base32hex_decode((uint8_t *)"A======", 8, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad padding length 7");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ECHAR, "Bad padding length 7");
ret = base32hex_decode((uint8_t *)"=======", 8, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad padding length 8");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ECHAR, "Bad padding length 8");
// Bad data length
ret = base32hex_decode((uint8_t *)"A", 1, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 1");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 1");
ret = base32hex_decode((uint8_t *)"AA", 2, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 2");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 2");
ret = base32hex_decode((uint8_t *)"AAA", 3, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 3");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 3");
ret = base32hex_decode((uint8_t *)"AAAA", 4, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 4");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 4");
ret = base32hex_decode((uint8_t *)"AAAAA", 5, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 5");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 5");
ret = base32hex_decode((uint8_t *)"AAAAAA", 6, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 6");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 6");
ret = base32hex_decode((uint8_t *)"AAAAAAA", 7, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 7");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 7");
ret = base32hex_decode((uint8_t *)"AAAAAAAAA", 9, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 9");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ESIZE, "Bad data length 9");
// Bad data character
ret = base32hex_decode((uint8_t *)"AAAAAAA$", 8, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad data character dollar");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ECHAR, "Bad data character dollar");
ret = base32hex_decode((uint8_t *)"AAAAAAA ", 8, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad data character space");
+ cmp_ok(ret, "==", KNOT_BASE32HEX_ECHAR, "Bad data character space");
return 0;
}
diff --git a/src/tests/common/base64_tests.c b/src/tests/common/base64_tests.c
index 9453c98..0893c09 100644
--- a/src/tests/common/base64_tests.c
+++ b/src/tests/common/base64_tests.c
@@ -14,12 +14,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include "tests/common/base64_tests.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include "common/errcode.h"
#include "common/base64.h"
#define BUF_LEN 256
@@ -51,10 +53,14 @@ static int base64_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base64_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "1. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "1. test vector - ENC output content");
+ endskip;
ret = base64_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "1. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "1. test vector - DEC output content");
+ endskip;
// 2. test vector -> ENC -> DEC
strcpy((char *)in, "f");
@@ -63,10 +69,14 @@ static int base64_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base64_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "2. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "2. test vector - ENC output content");
+ endskip;
ret = base64_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "2. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "2. test vector - DEC output content");
+ endskip;
// 3. test vector -> ENC -> DEC
strcpy((char *)in, "fo");
@@ -75,10 +85,14 @@ static int base64_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base64_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "3. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "3. test vector - ENC output content");
+ endskip;
ret = base64_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "3. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "3. test vector - DEC output content");
+ endskip;
// 4. test vector -> ENC -> DEC
strcpy((char *)in, "foo");
@@ -87,10 +101,14 @@ static int base64_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base64_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "4. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "4. test vector - ENC output content");
+ endskip;
ret = base64_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "4. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "4. test vector - DEC output content");
+ endskip;
// 5. test vector -> ENC -> DEC
strcpy((char *)in, "foob");
@@ -99,10 +117,14 @@ static int base64_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base64_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "5. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "5. test vector - ENC output content");
+ endskip;
ret = base64_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "5. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "5. test vector - DEC output content");
+ endskip;
// 6. test vector -> ENC -> DEC
strcpy((char *)in, "fooba");
@@ -111,10 +133,14 @@ static int base64_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base64_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "6. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "6. test vector - ENC output content");
+ endskip;
ret = base64_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "6. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "6. test vector - DEC output content");
+ endskip;
// 7. test vector -> ENC -> DEC
strcpy((char *)in, "foobar");
@@ -123,32 +149,36 @@ static int base64_tests_run(int argc, char *argv[])
ref_len = strlen((char *)ref);
ret = base64_encode(in, in_len, out, BUF_LEN);
cmp_ok(ret, "==", ref_len, "7. test vector - ENC output length");
+ skip(ret < 0, 1);
ok(memcmp(out, ref, ret) == 0, "7. test vector - ENC output content");
+ endskip;
ret = base64_decode(out, ret, out2, BUF_LEN);
cmp_ok(ret, "==", in_len, "7. test vector - DEC output length");
+ skip(ret < 0, 1);
ok(memcmp(out2, in, ret) == 0, "7. test vector - DEC output content");
+ endskip;
// Bad paddings
ret = base64_decode((uint8_t *)"A===", 4, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad padding length 3");
+ cmp_ok(ret, "==", KNOT_BASE64_ECHAR, "Bad padding length 3");
ret = base64_decode((uint8_t *)"====", 4, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad padding length 4");
+ cmp_ok(ret, "==", KNOT_BASE64_ECHAR, "Bad padding length 4");
// Bad data length
ret = base64_decode((uint8_t *)"A", 1, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 1");
+ cmp_ok(ret, "==", KNOT_BASE64_ESIZE, "Bad data length 1");
ret = base64_decode((uint8_t *)"AA", 2, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 2");
+ cmp_ok(ret, "==", KNOT_BASE64_ESIZE, "Bad data length 2");
ret = base64_decode((uint8_t *)"AAA", 3, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 3");
+ cmp_ok(ret, "==", KNOT_BASE64_ESIZE, "Bad data length 3");
ret = base64_decode((uint8_t *)"AAAAA", 5, out, BUF_LEN);
- cmp_ok(ret, "==", -1, "Bad data length 5");
+ cmp_ok(ret, "==", KNOT_BASE64_ESIZE, "Bad data length 5");
// Bad data character
ret = base64_decode((uint8_t *)"AAA$", 4, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad data character dollar");
+ cmp_ok(ret, "==", KNOT_BASE64_ECHAR, "Bad data character dollar");
ret = base64_decode((uint8_t *)"AAA ", 4, out, BUF_LEN);
- cmp_ok(ret, "==", -2, "Bad data character space");
+ cmp_ok(ret, "==", KNOT_BASE64_ECHAR, "Bad data character space");
return 0;
}
diff --git a/src/tests/common/descriptor_tests.c b/src/tests/common/descriptor_tests.c
new file mode 100644
index 0000000..9d752f5
--- /dev/null
+++ b/src/tests/common/descriptor_tests.c
@@ -0,0 +1,234 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "tests/common/descriptor_tests.h"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "common/descriptor.h"
+
+#define BUF_LEN 256
+
+static int descriptor_tests_count(int argc, char *argv[]);
+static int descriptor_tests_run(int argc, char *argv[]);
+
+unit_api descriptor_tests_api = {
+ "RR descriptors",
+ &descriptor_tests_count,
+ &descriptor_tests_run
+};
+
+static int descriptor_tests_count(int argc, char *argv[])
+{
+ return 68;
+}
+
+static int descriptor_tests_run(int argc, char *argv[])
+{
+ const rdata_descriptor_t *descr;
+ char name[BUF_LEN];
+ int ret;
+ uint16_t num;
+
+ // Get descriptor, type num to string:
+ // 1. TYPE0
+ descr = get_rdata_descriptor(0);
+ ok(descr->type_name == 0, "get TYPE0 descriptor name");
+ cmp_ok(descr->block_types[0], "==", KNOT_RDATA_WF_REMAINDER,
+ "get TYPE0 descriptor 1. item type");
+ cmp_ok(descr->block_types[1], "==", KNOT_RDATA_WF_END,
+ "get TYPE0 descriptor 2. item type");
+
+ ret = knot_rrtype_to_string(0, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get TYPE0 ret");
+ ok(strcmp(name, "TYPE0") == 0, "get TYPE0 name");
+
+ // 2. A
+ descr = get_rdata_descriptor(1);
+ ok(strcmp(descr->type_name, "A") == 0, "get A descriptor name");
+ cmp_ok(descr->block_types[0], "==", 4,
+ "get A descriptor 1. item type");
+ cmp_ok(descr->block_types[1], "==", KNOT_RDATA_WF_END,
+ "get A descriptor 2. item type");
+
+ ret = knot_rrtype_to_string(1, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get A ret");
+ ok(strcmp(name, "A") == 0, "get A name");
+
+ // 3. CNAME
+ descr = get_rdata_descriptor(5);
+ ok(strcmp(descr->type_name, "CNAME") == 0, "get CNAME descriptor name");
+ cmp_ok(descr->block_types[0], "==", KNOT_RDATA_WF_COMPRESSED_DNAME,
+ "get CNAME descriptor 1. item type");
+ cmp_ok(descr->block_types[1], "==", KNOT_RDATA_WF_END,
+ "get CNAME descriptor 2. item type");
+
+ ret = knot_rrtype_to_string(5, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get CNAME ret");
+ ok(strcmp(name, "CNAME") == 0, "get CNAME name");
+
+ // 4. TYPE38 (A6)
+ descr = get_rdata_descriptor(38);
+ ok(descr->type_name == 0, "get TYPE38 descriptor name");
+ cmp_ok(descr->block_types[0], "==", KNOT_RDATA_WF_REMAINDER,
+ "get TYPE38 descriptor 1. item type");
+ cmp_ok(descr->block_types[1], "==", KNOT_RDATA_WF_END,
+ "get TYPE38 descriptor 2. item type");
+
+ ret = knot_rrtype_to_string(38, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get TYPE38 ret");
+ ok(strcmp(name, "TYPE38") == 0, "get TYPE38 name");
+
+ // 5. ANY
+ descr = get_rdata_descriptor(255);
+ ok(strcmp(descr->type_name, "ANY") == 0, "get ANY descriptor name");
+ cmp_ok(descr->block_types[0], "==", KNOT_RDATA_WF_REMAINDER,
+ "get ANY descriptor 1. item type");
+ cmp_ok(descr->block_types[1], "==", KNOT_RDATA_WF_END,
+ "get ANY descriptor 2. item type");
+
+ ret = knot_rrtype_to_string(255, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get ANY ret");
+ ok(strcmp(name, "ANY") == 0, "get ANY name");
+
+ // 6. TYPE256
+ descr = get_rdata_descriptor(256);
+ ok(descr->type_name == 0, "get TYPE256 descriptor name");
+ cmp_ok(descr->block_types[0], "==", KNOT_RDATA_WF_REMAINDER,
+ "get TYPE256 descriptor 1. item type");
+ cmp_ok(descr->block_types[1], "==", KNOT_RDATA_WF_END,
+ "get TYPE256 descriptor 2. item type");
+
+ ret = knot_rrtype_to_string(256, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get TYPE256 ret");
+ ok(strcmp(name, "TYPE256") == 0, "get TYPE256 name");
+
+
+ // Class num to string:
+ // 7. CLASS0
+ ret = knot_rrclass_to_string(0, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get CLASS0 ret");
+ ok(strcmp(name, "CLASS0") == 0, "get CLASS0 name");
+
+ // 8. IN
+ ret = knot_rrclass_to_string(1, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get IN ret");
+ ok(strcmp(name, "IN") == 0, "get IN name");
+
+ // 9. ANY
+ ret = knot_rrclass_to_string(255, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get ANY ret");
+ ok(strcmp(name, "ANY") == 0, "get ANY name");
+
+ // 10. CLASS65535
+ ret = knot_rrclass_to_string(65535, name, BUF_LEN);
+ cmp_ok(ret, "!=", -1, "get CLASS65535 ret");
+ ok(strcmp(name, "CLASS65535") == 0, "get CLASS65535 name");
+
+ // String to type num:
+ // 11. A
+ ret = knot_rrtype_from_string("A", &num);
+ cmp_ok(ret, "!=", -1, "get A num ret");
+ cmp_ok(num, "==", 1, "get A num");
+
+ // 12. a
+ ret = knot_rrtype_from_string("a", &num);
+ cmp_ok(ret, "!=", -1, "get a num ret");
+ cmp_ok(num, "==", 1, "get a num");
+
+ // 13. AaAa
+ ret = knot_rrtype_from_string("AaAa", &num);
+ cmp_ok(ret, "!=", -1, "get AaAa num ret");
+ cmp_ok(num, "==", 28, "get AaAa num");
+
+ // 14. ""
+ ret = knot_rrtype_from_string("", &num);
+ cmp_ok(ret, "==", -1, "get "" num ret");
+
+ // 15. DUMMY
+ ret = knot_rrtype_from_string("DUMMY", &num);
+ cmp_ok(ret, "==", -1, "get DUMMY num ret");
+
+ // 16. TypE33
+ ret = knot_rrtype_from_string("TypE33", &num);
+ cmp_ok(ret, "!=", -1, "get TypE33 num ret");
+ cmp_ok(num, "==", 33, "get TypE33 num");
+
+ // 17. TYPE
+ ret = knot_rrtype_from_string("TYPE", &num);
+ cmp_ok(ret, "==", -1, "get TYPE num ret");
+
+ // 18. TYPE0
+ ret = knot_rrtype_from_string("TYPE0", &num);
+ cmp_ok(ret, "!=", -1, "get TYPE0 num ret");
+ cmp_ok(num, "==", 0, "get TYPE0 num");
+
+ // 19. TYPE65535
+ ret = knot_rrtype_from_string("TYPE65535", &num);
+ cmp_ok(ret, "!=", -1, "get TYPE65535 num ret");
+ cmp_ok(num, "==", 65535, "get TYPE65535 num");
+
+ // 20. TYPE65536
+ ret = knot_rrtype_from_string("TYPE65536", &num);
+ cmp_ok(ret, "==", -1, "get TYPE65536 num ret");
+
+ // String to class num:
+ // 21. In
+ ret = knot_rrclass_from_string("In", &num);
+ cmp_ok(ret, "!=", -1, "get In num ret");
+ cmp_ok(num, "==", 1, "get In num");
+
+ // 22. ANY
+ ret = knot_rrclass_from_string("ANY", &num);
+ cmp_ok(ret, "!=", -1, "get ANY num ret");
+ cmp_ok(num, "==", 255, "get ANY num");
+
+ // 23. ""
+ ret = knot_rrclass_from_string("", &num);
+ cmp_ok(ret, "==", -1, "get "" num ret");
+
+ // 24. DUMMY
+ ret = knot_rrclass_from_string("DUMMY", &num);
+ cmp_ok(ret, "==", -1, "get DUMMY num ret");
+
+ // 25. CLass33
+ ret = knot_rrclass_from_string("CLass33", &num);
+ cmp_ok(ret, "!=", -1, "get CLass33 num ret");
+ cmp_ok(num, "==", 33, "get CLass33 num");
+
+ // 26. CLASS
+ ret = knot_rrclass_from_string("CLASS", &num);
+ cmp_ok(ret, "==", -1, "get CLASS num ret");
+
+ // 27. CLASS0
+ ret = knot_rrclass_from_string("CLASS0", &num);
+ cmp_ok(ret, "!=", -1, "get CLASS0 num ret");
+ cmp_ok(num, "==", 0, "get CLASS0 num");
+
+ // 28. CLASS65535
+ ret = knot_rrclass_from_string("CLASS65535", &num);
+ cmp_ok(ret, "!=", -1, "get CLASS65535 num ret");
+ cmp_ok(num, "==", 65535, "get CLASS65535 num");
+
+ // 29. CLASS65536
+ ret = knot_rrclass_from_string("CLASS65536", &num);
+ cmp_ok(ret, "==", -1, "get CLASS65536 num ret");
+
+ return 0;
+}
diff --git a/src/tests/libknot/libknot/nsec3_tests.h b/src/tests/common/descriptor_tests.h
index 10e7ed9..7b7f861 100644
--- a/src/tests/libknot/libknot/nsec3_tests.h
+++ b/src/tests/common/descriptor_tests.h
@@ -14,12 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_NSEC3_TESTS_H_
-#define _KNOTD_NSEC3_TESTS_H_
+#ifndef _KNOTD_DESCRIPTOR_TESTS_H_
+#define _KNOTD_DESCRIPTOR_TESTS_H_
#include "common/libtap/tap_unit.h"
/* Unit API. */
-unit_api nsec3_tests_api;
+unit_api descriptor_tests_api;
-#endif /* _KNOTD_NSEC3_TESTS_H_ */
+#endif /* _KNOTD_DESCRIPTOR_TESTS_H_ */
diff --git a/src/tests/common/events_tests.c b/src/tests/common/events_tests.c
index a9b3de6..713bb5a 100644
--- a/src/tests/common/events_tests.c
+++ b/src/tests/common/events_tests.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
diff --git a/src/tests/common/fdset_tests.c b/src/tests/common/fdset_tests.c
index 627829e..d7b29fa 100644
--- a/src/tests/common/fdset_tests.c
+++ b/src/tests/common/fdset_tests.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
@@ -83,7 +84,9 @@ void* thr_action(void *arg)
/* Write pattern. */
char pattern = WRITE_PATTERN;
- (void)write(*fd, &pattern, WRITE_PATTERN_LEN);
+ if (write(*fd, &pattern, WRITE_PATTERN_LEN) == -1) {
+ // Error.
+ }
return NULL;
}
diff --git a/src/tests/common/hattrie_tests.c b/src/tests/common/hattrie_tests.c
new file mode 100644
index 0000000..941f38c
--- /dev/null
+++ b/src/tests/common/hattrie_tests.c
@@ -0,0 +1,161 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <string.h>
+#include <time.h>
+
+#include "tests/common/hattrie_tests.h"
+#include "common/mempattern.h"
+#include "common/hattrie/hat-trie.h"
+
+static const char *alphabet = "abcdefghijklmn";
+static char *randstr() {
+ unsigned len = (1 + rand() % 64) + 1; /* (1-64) + '\0' */
+ char *s = xmalloc(len * sizeof(char));
+ for (unsigned i = 0; i < len - 1; ++i) {
+ s[i] = alphabet[rand() % strlen(alphabet)];
+ }
+ s[len - 1] = '\0';
+ return s;
+}
+
+static int hattrie_tests_count(int argc, char *argv[]);
+static int hattrie_tests_run(int argc, char *argv[]);
+
+/*
+ * Unit API.
+ */
+unit_api hattrie_tests_api = {
+ "HAT trie",
+ &hattrie_tests_count,
+ &hattrie_tests_run
+};
+
+/*
+ * Unit implementation.
+ */
+
+static const int HAT_TEST_COUNT = 6;
+
+static int hattrie_tests_count(int argc, char *argv[])
+{
+ return HAT_TEST_COUNT;
+}
+
+static int hattrie_tests_run(int argc, char *argv[])
+{
+ /* Interesting intems. */
+ unsigned count = 10;
+ const char *items[] = {
+ "abcd",
+ "abc",
+ "ab",
+ "a",
+ "abcdefghijklmnopqrstuvw",
+ "abAcd",
+ "abcA",
+ "abA",
+ "Aab",
+ "A"
+ };
+
+ /* Dummy items. */
+ srand(time(NULL));
+ unsigned dummy_count = 10000;
+ char **dummy = xmalloc(sizeof(char*) * dummy_count);
+ for (unsigned i = 0; i < dummy_count; ++i) {
+ dummy[i] = randstr();
+ }
+
+ /* Test 1: Create */
+ unsigned passed = 1;
+ value_t *v = NULL;
+ hattrie_t *t = hattrie_create();
+ ok(t != NULL, "hattrie: create");
+
+ /* Test 2: Insert */
+ passed = 1;
+ for (unsigned i = 0; i < count; ++i) {
+ v = hattrie_get(t, items[i], strlen(items[i]));
+ if (!v) {
+ passed = 0;
+ break;
+ }
+ *v = (value_t)items[i];
+ }
+ ok(passed, "hattrie: insert");
+
+ /* Test 3: Insert dummy. */
+ passed = 1;
+ for (unsigned i = 0; i < dummy_count; ++i) {
+ v = hattrie_get(t, dummy[i], strlen(dummy[i]));
+ if (!v) {
+ passed = 0;
+ break;
+ }
+ if (*v == NULL) {
+ *v = dummy[i];
+ }
+ }
+ ok(passed, "hattrie: dummy insert");
+
+ /* Test 4: Lookup */
+ passed = 1;
+ for (unsigned i = 0; i < count; ++i) {
+ v = hattrie_tryget(t, items[i], strlen(items[i]));
+ if (!v || *v != items[i]) {
+ diag("hattrie: mismatch on element '%u'", i);
+ passed = 0;
+ break;
+ }
+ }
+ ok(passed, "hattrie: lookup");
+
+ /* Test 5: LPR lookup */
+ unsigned lpr_count = 5;
+ const char *lpr[] = {
+ "abcdZ",
+ "abcZ",
+ "abZ",
+ "aZ",
+ "abcdefghijklmnopqrstuvw"
+ };
+ passed = 1;
+ for (unsigned i = 0; i < lpr_count; ++i) {
+ int ret = hattrie_find_lpr(t, lpr[i], strlen(lpr[i]), &v);
+ if (!v || ret != 0 || *v != items[i]) {
+ diag("hattrie: lpr='%s' mismatch lpr(%s) != %s",
+ !v ? NULL : *v, lpr[i], items[i]);
+ passed = 0;
+ break;
+ }
+ }
+ ok(passed, "hattrie: longest prefix match");
+
+ /* Test 6: false LPR lookup */
+ const char *false_lpr = "Z";
+ int ret = hattrie_find_lpr(t, false_lpr, strlen(false_lpr), &v);
+ ok(ret != 0 && v == NULL, "hattrie: non-existent prefix lookup");
+
+
+ for (unsigned i = 0; i < dummy_count; ++i) {
+ free(dummy[i]);
+ }
+ free(dummy);
+ hattrie_free(t);
+ return 0;
+}
diff --git a/src/tests/libknot/libknot/packet_tests.h b/src/tests/common/hattrie_tests.h
index 5a8ce03..c1e02e6 100644
--- a/src/tests/libknot/libknot/packet_tests.h
+++ b/src/tests/common/hattrie_tests.h
@@ -14,12 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_PACKET_TESTS_H_
-#define _KNOTD_PACKET_TESTS_H_
+#ifndef _KNOTD_HATTRIE_TESTS_H_
+#define _KNOTD_HATTRIE_TESTS_H_
#include "common/libtap/tap_unit.h"
/* Unit API. */
-unit_api packet_tests_api;
+unit_api hattrie_tests_api;
-#endif /* _KNOTD_PACKET_TESTS_H_ */
+#endif /* _KNOTD_HATTRIE_TESTS_H_ */
diff --git a/src/tests/common/skiplist_tests.c b/src/tests/common/skiplist_tests.c
index 4fe99ec..68ad139 100644
--- a/src/tests/common/skiplist_tests.c
+++ b/src/tests/common/skiplist_tests.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <time.h>
#include "tests/common/skiplist_tests.h"
diff --git a/src/tests/common/slab_tests.c b/src/tests/common/slab_tests.c
index a5de1c2..088370d 100644
--- a/src/tests/common/slab_tests.c
+++ b/src/tests/common/slab_tests.c
@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
@@ -21,7 +22,6 @@
#include "tests/common/slab_tests.h"
#include "common/slab/slab.h"
-#include "knot/common.h"
/*! \brief Type-safe maximum macro. */
#define SLAB_MAX(a, b) \
diff --git a/src/tests/knot/conf_tests.c b/src/tests/knot/conf_tests.c
index 61520ea..0904a4e 100644
--- a/src/tests/knot/conf_tests.c
+++ b/src/tests/knot/conf_tests.c
@@ -14,13 +14,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdio.h>
#include "tests/knot/conf_tests.h"
#include "knot/conf/conf.h"
/* Resources. */
-#include "tests/sample_conf.rc"
+#include "sample_conf.rc"
static int conf_tests_count(int argc, char *argv[]);
static int conf_tests_run(int argc, char *argv[]);
@@ -78,10 +79,15 @@ static int conf_tests_run(int argc, char *argv[])
ok(0, "TSIG key algorithm check - NO KEY FOUND");
ok(0, "TSIG key secret check - NO KEY FOUND");
} else {
- knot_key_t *k = &((conf_key_t *)HEAD(conf->keys))->k;
+ knot_tsig_key_t *k = &((conf_key_t *)HEAD(conf->keys))->k;
+ uint8_t decoded_secret[] = { 0x5a };
+
cmp_ok(k->algorithm, "==", KNOT_TSIG_ALG_HMAC_MD5,
"TSIG key algorithm check");
- is(k->secret, "Wg==", "TSIG key secret check");
+ ok(k->secret.size == sizeof(decoded_secret)
+ && memcmp(k->secret.data, decoded_secret,
+ sizeof(decoded_secret)) == 0,
+ "TSIG key secret check");
}
// Test 11,12,13,14,15,16,17,18: Check logging facilities
@@ -118,20 +124,20 @@ static int conf_tests_run(int argc, char *argv[])
{
is(log->file, "/var/log/knot/server.err", "log file matches");
} endskip;
-
+
// Test 21: Load key dname
const char *sample_str = "key0.example.net";
knot_dname_t *sample = knot_dname_new_from_str(sample_str,
strlen(sample_str), 0);
if (conf->key_count > 0) {
- knot_key_t *k = &((conf_key_t *)HEAD(conf->keys))->k;
+ knot_tsig_key_t *k = &((conf_key_t *)HEAD(conf->keys))->k;
ok(knot_dname_compare(sample, k->name) == 0,
"TSIG key dname check");
} else {
ok(0, "TSIG key dname check - NO KEY FOUND");
}
knot_dname_free(&sample);
-
+
} endskip;
// Deallocating config
diff --git a/src/tests/knot/dthreads_tests.c b/src/tests/knot/dthreads_tests.c
index 0b2cb01..247f66e 100644
--- a/src/tests/knot/dthreads_tests.c
+++ b/src/tests/knot/dthreads_tests.c
@@ -13,6 +13,8 @@
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 <config.h>
#include <pthread.h>
#include <sched.h>
#include <sys/select.h>
@@ -36,7 +38,7 @@ unit_api dthreads_tests_api = {
/*
* Unit implementation.
*/
-static const int DT_TEST_COUNT = 23;
+static const int DT_TEST_COUNT = 18;
/* Unit runnable data. */
static pthread_mutex_t _runnable_mx;
@@ -140,87 +142,6 @@ static inline int dt_test_reanimate(dt_unit_t *unit)
return ret == 0;
}
-/*! \brief Resize unit. */
-static inline int dt_test_resize(dt_unit_t *unit, int size)
-{
- // Resize
- int ret = 0;
- ret = dt_resize(unit, size);
- if (ret < 0) {
- return 0;
- }
-
- // Check outcome
- if (unit->size != size) {
- return 0;
- }
-
- // Repurpose all
- _runnable_i = 0;
- for (int i = 0; i < size; ++i) {
- ret += dt_repurpose(unit->threads[i], &runnable, 0);
- }
- ret += dt_start(unit);
-
- // Wait for finish
- ret += dt_join(unit);
-
- // Verify
- int expected = size * _runnable_cycles;
- note("resize test: %d threads, %d ticks, %d expected",
- size, _runnable_i, expected);
- if (_runnable_i != expected) {
- return 0;
- }
-
- // Check return codes
- return ret == 0;
-}
-
-/*! \brief Resize unit while threads are active. */
-static inline int dt_test_liveresize(dt_unit_t *unit)
-{
- // Size
- int size = unit->size;
- int size_hi = size + 2;
- int size_lo = size - 1;
-
- // Expand
- int ret = 0;
- ret = dt_resize(unit, size_hi);
- if (ret < 0) {
- return 0;
- }
-
- // Repurpose all
- for (int i = 0; i < unit->size; ++i) {
- ret += dt_repurpose(unit->threads[i], &runnable, 0);
- }
-
- // Restart
- _runnable_i = 0;
- ret += dt_start(unit);
-
- // Shrink
- ret += dt_resize(unit, size_lo);
-
- // Wait for finish
- ret += dt_join(unit);
-
- // Verify
- int expected_hi = size_hi * _runnable_cycles;
- int expected_lo = size_lo * _runnable_cycles;
- note("resize test: %d->%d->%d threads, %d ticks, <%d,%d> expected",
- size, size_hi, size_lo, _runnable_i, expected_lo, expected_hi);
-
- if (_runnable_i > expected_hi || _runnable_i < expected_lo) {
- return 0;
- }
-
- // Check return codes
- return ret == 0;
-}
-
/*! \brief Start unit. */
static inline int dt_test_start(dt_unit_t *unit)
{
@@ -324,42 +245,20 @@ static int dt_tests_run(int argc, char *argv[])
/* Test 13: Reanimate dead threads. */
ok(dt_test_reanimate(unit), "dthreads: reanimate dead threads");
- /* Test 14: Expand unit by 100%. */
- int size = unit->size * 2;
- ok(dt_test_resize(unit, size),
- "dthreads: expanding unit to size * 2 (%d threads)", size);
-
- /* Test 15: Shrink unit to half. */
- size = unit->size / 2;
- ok(dt_test_resize(unit, size),
- "dthreads: shrinking unit to size / 2 (%d threads)", size);
-
- /* Test 16: Resize while threads are active. */
- ok(dt_test_liveresize(unit), "dthreads: resizing unit while active");
-
- /* Test 17: Deinitialize */
+ /* Test 14: Deinitialize */
dt_delete(&unit);
ok(unit == 0, "dthreads: delete unit");
endskip;
- /* Test 18: Wrong values. */
+ /* Test 15: Wrong values. */
unit = dt_create(-1);
ok(unit == 0, "dthreads: create with negative count");
unit = dt_create_coherent(dt_optimal_size(), 0, 0);
- /* Test 19: NULL runnable. */
+ /* Test 16: NULL runnable. */
cmp_ok(dt_start(unit), "==", 0, "dthreads: start with NULL runnable");
- /* Test 20: resize to negative value. */
- cmp_ok(dt_resize(unit, -19),
- "<", 0, "dthreads: resize to negative size");
-
- /* Test 21: resize to zero value. */
- cmp_ok(dt_resize(unit, 0), "<", 0, "dthreads: resize to NULL size");
- dt_join(unit);
- dt_delete(&unit);
-
- /* Test 22: NULL operations crashing. */
+ /* Test 17: NULL operations crashing. */
int op_count = 14;
int expected_min = op_count * -1;
// All functions must return -1 at least
@@ -372,7 +271,6 @@ static int dt_tests_run(int argc, char *argv[])
ret += dt_is_cancelled(0); // 0
ret += dt_join(0); // -1
ret += dt_repurpose(0, 0, 0); // -1
- ret += dt_resize(0, 0); // -1
ret += dt_signalize(0, SIGALRM); // -1
ret += dt_start(0); // -1
ret += dt_start_id(0); // -1
@@ -382,7 +280,7 @@ static int dt_tests_run(int argc, char *argv[])
ret += dt_unit_unlock(0); // -1
}, "dthreads: not crashed while executing functions on NULL context");
- /* Test 23: expected results. */
+ /* Test 18: expected results. */
cmp_ok(ret, "<=", expected_min,
"dthreads: correct values when passed NULL context "
"(%d, min: %d)", ret, expected_min);
diff --git a/src/tests/knot/journal_tests.c b/src/tests/knot/journal_tests.c
index 89466ea..d61a149 100644
--- a/src/tests/knot/journal_tests.c
+++ b/src/tests/knot/journal_tests.c
@@ -13,11 +13,13 @@
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 <config.h>
#include <string.h>
#include "tests/knot/journal_tests.h"
#include "knot/server/journal.h"
-#include "knot/common.h"
+#include "knot/knot.h"
static int journal_tests_count(int argc, char *argv[]);
static int journal_tests_run(int argc, char *argv[]);
@@ -58,7 +60,7 @@ static int walkchars(journal_t *j, journal_node_t *n) {
journal_read(j, n->id, walkchars_cmp, _walkbuf + _wbi);
++_wbi;
return 0;
-}
+}
/*! API: return number of tests. */
static int journal_tests_count(int argc, char *argv[])
@@ -86,7 +88,7 @@ static int journal_tests_run(int argc, char *argv[])
/* Test 3: Open journal. */
journal_t *journal = journal_open(jfilename, fsize, JOURNAL_LAZY, 0);
ok(journal != 0, "journal: open");
-
+
/* Retain journal. */
journal_t *j = journal_retain(journal);
@@ -103,7 +105,7 @@ static int journal_tests_run(int argc, char *argv[])
/* Test 6: Compare read data. */
ret = strncmp(sample, tmpbuf, strlen(sample));
ok(ret == 0, "journal: read data integrity check");
-
+
/* Append several characters. */
journal_write(j, 0, "X", 1); /* Dummy */
char word[7] = { 'w', 'o', 'r', 'd', '0', '\0', '\0' };
@@ -118,7 +120,7 @@ static int journal_tests_run(int argc, char *argv[])
ret = strcmp(word, _walkbuf);
ok(ret == 0, "journal: read data integrity check 2 '%s'", _walkbuf);
_wbi = 0;
-
+
/* Test 8: Change single letter and compare. */
word[5] = 'X';
journal_write(j, 5, word+5, 1); /* append 'X', shifts out 'w' */
@@ -127,18 +129,18 @@ static int journal_tests_run(int argc, char *argv[])
ret = strcmp(word + 1, _walkbuf);
ok(ret == 0, "journal: read data integrity check 3 '%s'", _walkbuf);
_wbi = 0;
-
+
/* Test 9: Attempt to retain and release. */
journal_t *tmp = journal_retain(j);
ok(tmp == j, "journal: tested journal retaining");
journal_release(tmp);
-
+
/* Release journal. */
journal_release(j);
-
+
/* Close journal. */
journal_close(journal);
-
+
/* Recreate journal = NORMAL mode. */
if (remove(jfilename) < 0) {
diag("journal: couldn't remove filename");
@@ -147,12 +149,12 @@ static int journal_tests_run(int argc, char *argv[])
jsize = 512;
ret = journal_create(jfilename, jsize);
j = journal_open(jfilename, fsize, 0, 0);
-
+
/* Test 10: Write random data. */
int chk_key = 0;
char chk_buf[64] = {'\0'};
ret = 0;
- const int itcount = 1;//jsize * 5 + 5;
+ const int itcount = jsize * 5 + 5;
for (int i = 0; i < itcount; ++i) {
int key = rand() % 65535;
randstr(tmpbuf, sizeof(tmpbuf));
@@ -182,26 +184,26 @@ static int journal_tests_run(int argc, char *argv[])
journal_read(j, chk_key, 0, tmpbuf);
ret = strncmp(chk_buf, tmpbuf, sizeof(chk_buf));
ok(j && ret == 0, "journal: read data integrity check after close/open");
-
+
/* Test 13: Map journal entry. */
char *mptr = NULL;
memset(chk_buf, 0xde, sizeof(chk_buf));
ret = journal_map(j, 0x12345, &mptr, sizeof(chk_buf));
ok(j && mptr && ret == 0, "journal: mapped journal entry");
skip(ret != 0, 2);
-
+
/* Test 14: Write to mmaped entry and unmap. */
memcpy(mptr, chk_buf, sizeof(chk_buf));
ret = journal_unmap(j, 0x12345, mptr, 1);
ok(j && mptr && ret == 0, "journal: written to mapped entry and finished");
-
+
/* Test 15: Compare mmaped entry. */
memset(tmpbuf, 0, sizeof(tmpbuf));
journal_read(j, 0x12345, NULL, tmpbuf);
ret = strncmp(chk_buf, tmpbuf, sizeof(chk_buf));
ok(j && ret == 0, "journal: mapped entry data integrity check");
endskip;
-
+
/* Test 16: Make a transaction. */
uint64_t tskey = 0x75750000;
ret = journal_trans_begin(j);
@@ -210,16 +212,16 @@ static int journal_tests_run(int argc, char *argv[])
memset(tmpbuf, i, sizeof(tmpbuf));
journal_write(j, tskey + i, tmpbuf, sizeof(tmpbuf));
}
-
+
/* Test 17: Check if uncommited node exists. */
ret = journal_read(j, tskey + rand() % 16, NULL, chk_buf);
ok(j && ret != 0, "journal: check for uncommited node");
-
+
/* Test 18: Commit transaction. */
ret = journal_trans_commit(j);
int read_ret = journal_read(j, tskey + rand() % 16, NULL, chk_buf);
ok(j && ret == 0 && read_ret == 0, "journal: transaction commit");
-
+
/* Test 19: Rollback transaction. */
tskey = 0x6B6B0000;
journal_trans_begin(j);
@@ -268,7 +270,7 @@ static int journal_tests_run(int argc, char *argv[])
remove(jfilename);
j = journal_open(jfilename, fsize, 0, 0);
ok(j != NULL, "journal: open+create from scratch");
-
+
/* Close journal. */
journal_close(j);
diff --git a/src/tests/knot/rrl_tests.c b/src/tests/knot/rrl_tests.c
index ed16530..e7d26dd 100644
--- a/src/tests/knot/rrl_tests.c
+++ b/src/tests/knot/rrl_tests.c
@@ -14,21 +14,23 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "tests/knot/rrl_tests.h"
#include "knot/server/rrl.h"
#include "knot/server/dthreads.h"
-#include "knot/common.h"
+#include "knot/knot.h"
#include "libknot/packet/response.h"
#include "libknot/packet/query.h"
#include "libknot/nameserver/name-server.h"
+#include "common/descriptor.h"
#include "common/prng.h"
/* Enable time-dependent tests. */
//#define ENABLE_TIMED_TESTS
#define RRL_SIZE 196613
-#define RRL_THREADS 8
+#define RRL_THREADS 8
#define RRL_INSERTS (RRL_SIZE/(5*RRL_THREADS)) /* lf = 1/5 */
#define RRL_LOCKS 64
@@ -55,7 +57,6 @@ static void* rrl_runnable(void *arg)
struct runnable_data* d = (struct runnable_data*)arg;
sockaddr_t addr;
memcpy(&addr, d->addr, sizeof(sockaddr_t));
- sockaddr_update(&addr);
int lock = -1;
uint32_t now = time(NULL);
struct bucketmap_t *m = malloc(RRL_INSERTS * sizeof(struct bucketmap_t));
@@ -130,37 +131,42 @@ static int rrl_tests_run(int argc, char *argv[])
knot_packet_free(&query);
return KNOT_ERROR; /* Fatal */
}
- knot_query_set_question(query, &qst);
-
+ int ret = knot_query_set_question(query, &qst);
+ if (ret != KNOT_EOK) {
+ knot_dname_free(&qst.qname);
+ knot_packet_free(&query);
+ return KNOT_ERROR; /* Fatal */
+ }
+
/* Prepare response */
knot_nameserver_t *ns = knot_ns_create();
uint8_t rbuf[65535];
size_t rlen = sizeof(rbuf);
memset(rbuf, 0, sizeof(rbuf));
knot_ns_error_response_from_query(ns, query, KNOT_RCODE_NOERROR, rbuf, &rlen);
-
+
rrl_req_t rq;
rq.w = rbuf;
rq.len = rlen;
rq.qst = &qst;
rq.flags = 0;
-
+
/* 1. create rrl table */
rrl_table_t *rrl = rrl_create(RRL_SIZE);
ok(rrl != NULL, "rrl: create");
-
+
/* 2. set rate limit */
uint32_t rate = 10;
rrl_setrate(rrl, rate);
ok(rate == rrl_rate(rrl), "rrl: setrate");
-
+
/* 3. setlocks */
- int ret = rrl_setlocks(rrl, RRL_LOCKS);
+ ret = rrl_setlocks(rrl, RRL_LOCKS);
ok(ret == KNOT_EOK, "rrl: setlocks");
/* 4. N unlimited requests. */
knot_dname_t *apex = knot_dname_new_from_str("rrl.", 4, NULL);
- knot_zone_t *zone = knot_zone_new(knot_node_new(apex, NULL, 0), 0, 0);
+ knot_zone_t *zone = knot_zone_new(knot_node_new(apex, NULL, 0));
sockaddr_t addr;
sockaddr_t addr6;
sockaddr_set(&addr, AF_INET, "1.2.3.4", 0);
@@ -184,7 +190,7 @@ static int rrl_tests_run(int argc, char *argv[])
ret = rrl_query(rrl, &addr6, &rq, zone);
ok(ret != 0, "rrl: throttled IPv6 request");
#endif
-
+
/* 7. invalid values. */
ret = 0;
lives_ok( {
@@ -197,7 +203,7 @@ static int rrl_tests_run(int argc, char *argv[])
ret += rrl_query(rrl, (void*)0x1, 0, 0); // -1
ret += rrl_destroy(0); // -1
}, "rrl: not crashed while executing functions on NULL context");
-
+
#ifdef ENABLE_TIMED_TESTS
/* 8. hopscotch test */
struct runnable_data rd = {
@@ -205,18 +211,18 @@ static int rrl_tests_run(int argc, char *argv[])
};
rrl_hopscotch(&rd);
ok(rd.passed, "rrl: hashtable is ~ consistent");
-
+
/* 9. reseed */
ok(rrl_reseed(rrl) == 0, "rrl: reseed");
-
+
/* 10. hopscotch after reseed. */
rrl_hopscotch(&rd);
ok(rd.passed, "rrl: hashtable is ~ consistent");
#endif
-
+
knot_dname_release(qst.qname);
knot_dname_release(apex);
- knot_zone_deep_free(&zone, 0);
+ knot_zone_deep_free(&zone);
knot_ns_destroy(&ns);
knot_packet_free(&query);
rrl_destroy(rrl);
diff --git a/src/tests/knot/server_tests.c b/src/tests/knot/server_tests.c
index 5ae04d8..d84d2c9 100644
--- a/src/tests/knot/server_tests.c
+++ b/src/tests/knot/server_tests.c
@@ -13,6 +13,8 @@
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 <config.h>
#include "tests/knot/server_tests.h"
#include "knot/server/server.h"
diff --git a/src/tests/libknot/dname_tests.c b/src/tests/libknot/dname_tests.c
new file mode 100644
index 0000000..73ca67d
--- /dev/null
+++ b/src/tests/libknot/dname_tests.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "tests/libknot/dname_tests.h"
+#include "libknot/dname.h"
+
+/* Test dname_parse_from_wire */
+static int test_fw(size_t l, const char *w) {
+ size_t p = 0;
+ knot_dname_t *d = NULL;
+ d = knot_dname_parse_from_wire((const uint8_t*)w, &p, l, NULL, NULL);
+ int ret = (d != NULL);
+// d = knot_dname_new_from_wire((const uint8_t*)w, l, 0);
+// if (d) {
+// for(unsigned i = 0; i < d->label_count; ++i) {
+// diag("%d", knot_dname_label_size(d, i));
+// }
+// }
+ knot_dname_free(&d);
+ return ret;
+}
+
+static int dname_tests_count(int argc, char *argv[]);
+static int dname_tests_run(int argc, char *argv[]);
+
+unit_api dname_tests_api = {
+ "dname",
+ &dname_tests_count,
+ &dname_tests_run
+};
+
+static int dname_tests_count(int argc, char *argv[])
+{
+ return 8;
+}
+
+static int dname_tests_run(int argc, char *argv[])
+{
+ const char *w = NULL;
+
+ /* 1. NULL wire */
+ ok(!test_fw(0, NULL), "parsing NULL dname");
+
+ /* 2. empty label */
+ ok(test_fw(1, ""), "parsing empty dname");
+
+ /* 3. incomplete dname */
+ ok(!test_fw(5, "\x08""dddd"), "parsing incomplete wire");
+
+ /* 4. non-fqdn */
+ ok(!test_fw(3, "\x02""ab"), "parsing non-fqdn name");
+
+ /* 5. label > 63b */
+ w = "\x40""dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
+ ok(!test_fw(65, w), "parsing label > 63b");
+
+ /* 6. label count > 127 */
+ w = "\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64\x01\x64";
+ ok(!test_fw(257, w), "parsing label count > 127");
+
+ /* 7. dname length > 255 */
+ w = "\xff""ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
+ ok(!test_fw(257, w), "parsing dname len > 255");
+
+ /* 8. special case - invalid label */
+ w = "\x20\x68\x6d\x6e\x63\x62\x67\x61\x61\x61\x61\x65\x72\x6b\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x67\x6e\x69\x64\x68\x62\x61\x61\x61\x61\x65\x6c\x64\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x61\x63\x6f\x63\x64\x62\x61\x61\x61\x61\x65\x6b\x72\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x69\x62\x63\x6d\x6a\x6f\x61\x61\x61\x61\x65\x72\x6a\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x6f\x6c\x6e\x6c\x67\x68\x61\x61\x61\x61\x65\x73\x72\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x6a\x6b\x64\x66\x66\x67\x61\x61\x61\x61\x65\x6c\x68\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x67\x67\x6c\x70\x70\x61\x61\x61\x61\x61\x65\x73\x72\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x61\x61\x61\x62\x65\x6a\x61\x6d\x20\x65\x6b\x6c\x67\x70\x66\x61\x61\x61\x61\x65\x6c\x68\x30\x30\x30\x30\x64\x6c\x61\x61\x61\x61\x61\x0\x21\x42\x63\x84\xa5\xc6\xe7\x8\xa\xd\x11\x73\x3\x6e\x69\x63\x2\x43\x5a";
+ ok(!test_fw(277, w), "parsing invalid label (spec. case 1)");
+
+ return 0;
+}
diff --git a/src/tests/libknot/libknot/dname_tests.h b/src/tests/libknot/dname_tests.h
index a7d75aa..f3edff3 100644
--- a/src/tests/libknot/libknot/dname_tests.h
+++ b/src/tests/libknot/dname_tests.h
@@ -14,12 +14,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_DNAME_TESTS_H_
-#define _KNOTD_DNAME_TESTS_H_
+#ifndef _KNOT_DNAME_TESTS_
+#define _KNOT_DNAME_TESTS_
#include "common/libtap/tap_unit.h"
-/* Unit API. */
unit_api dname_tests_api;
-#endif /* _KNOTD_DNAME_TESTS_H_ */
+#endif
diff --git a/src/tests/libknot/files/parsed_data b/src/tests/libknot/files/parsed_data
deleted file mode 100644
index 4027c92..0000000
--- a/src/tests/libknot/files/parsed_data
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/files/parsed_data_queries b/src/tests/libknot/files/parsed_data_queries
deleted file mode 100644
index 5857c87..0000000
--- a/src/tests/libknot/files/parsed_data_queries
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/files/raw_data b/src/tests/libknot/files/raw_data
deleted file mode 100644
index f94236b..0000000
--- a/src/tests/libknot/files/raw_data
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/files/raw_data_queries b/src/tests/libknot/files/raw_data_queries
deleted file mode 100644
index 9062d5a..0000000
--- a/src/tests/libknot/files/raw_data_queries
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/libknot/cuckoo_tests.c b/src/tests/libknot/libknot/cuckoo_tests.c
deleted file mode 100644
index 8d22e36..0000000
--- a/src/tests/libknot/libknot/cuckoo_tests.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/* Copyright (C) 2011 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 <time.h>
-#include <assert.h>
-#include <string.h>
-
-#include "tests/libknot/libknot/cuckoo_tests.h"
-
-#include "libknot/hash/cuckoo-hash-table.h"
-
-//#define CK_TEST_DEBUG
-//#define CK_TEST_LOOKUP
-//#define CK_TEST_OUTPUT
-//#define CK_TEST_REMOVE
-//#define CK_TEST_COMPARE
-
-#ifdef CK_TEST_DEBUG
-#define CK_TEST_LOOKUP
-#define CK_TEST_OUTPUT
-#define CK_TEST_REMOVE
-#define CK_TEST_COMPARE
-#endif
-
-/*----------------------------------------------------------------------------*/
-
-static int cuckoo_tests_count(int argc, char *argv[]);
-static int cuckoo_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api cuckoo_tests_api = {
- "Cuckoo hashing", //! Unit name
- &cuckoo_tests_count, //! Count scheduled tests
- &cuckoo_tests_run //! Run scheduled tests
-};
-
-/*----------------------------------------------------------------------------*/
-
-/*
- * Unit implementation
- */
-static const int CUCKOO_TESTS_COUNT = 13;
-static const int CUCKOO_MAX_ITEMS = 1000;
-static const int CUCKOO_TEST_MAX_KEY_SIZE = 10;
-
-typedef struct test_cuckoo_items {
- char **keys;
- size_t *key_sizes;
- size_t *values;
- size_t *deleted;
- int count;
- int total_count;
-} test_cuckoo_items;
-
-/*----------------------------------------------------------------------------*/
-
-static inline char rand_char()
-{
- return (char)((rand() % 26) + 97);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static inline void rand_str(char *str, int size)
-{
- for (int i = 0; i < size; ++i) {
- str[i] = rand_char();
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int cuckoo_tests_count(int argc, char *argv[])
-{
- return CUCKOO_TESTS_COUNT;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_create(ck_hash_table_t **table, uint items)
-{
- *table = ck_create_table(items);
- return (*table != NULL);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_insert(ck_hash_table_t *table,
- const test_cuckoo_items *items)
-{
- assert(table != NULL);
- int errors = 0;
- for (int i = 0; i < items->count; ++i) {
- assert(items->values[i] != 0);
- if (ck_insert_item(table, items->keys[i], items->key_sizes[i],
- (void *)items->values[i]) != 0) {
- ++errors;
- }
- }
- return errors == 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_lookup(ck_hash_table_t *table,
- const test_cuckoo_items *items)
-{
- int errors = 0;
- for (int i = 0; i < items->count; ++i) {
- const ck_hash_table_item_t *found = ck_find_item(
- table, items->keys[i], items->key_sizes[i]);
- if (!found) {
- if (items->deleted[i] == 0) {
- diag("Not found item with key %.*s\n",
- items->key_sizes[i], items->keys[i]);
- ++errors;
- }
- } else {
- if (items->deleted[i] != 0
- || found->key != items->keys[i]
- || (size_t)(found->value) != items->values[i]) {
- diag("Found item with key %.*s (size %u) "
- "(should be %.*s (size %u)) and value %zu "
- "(should be %d).\n",
- found->key_length, found->key,
- found->key_length, items->key_sizes[i],
- items->keys[i], items->key_sizes[i],
- (size_t)found->value, items->values[i]);
- ++errors;
- }
- }
- }
-
- if (errors > 0) {
- diag("Not found %d of %d items.\n", errors, items->count);
- } else {
- note("Found %d items.\n", items->count);
- }
-
- return errors == 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_delete(ck_hash_table_t *table, test_cuckoo_items *items)
-{
- int errors = 0;
- // delete approx. 1/10 items from the table
- int count = rand() % (CUCKOO_MAX_ITEMS / 10) + 1;
-
- for (int i = 0; i < count; ++i) {
- int item = rand() % items->count;
- if (items->deleted[item] == 0
- && ck_delete_item(table, items->keys[item],
- items->key_sizes[item], NULL, 0) != 0) {
- ++errors;
- } else {
- items->deleted[item] = 1;
- }
- }
-
- return errors == 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_modify(ck_hash_table_t *table, test_cuckoo_items *items)
-{
- int errors = 0;
- // modify approx. 1/10 items from the table
- int count = rand() % (CUCKOO_MAX_ITEMS / 10) + 1;
-
- for (int i = 0; i < count; ++i) {
- int item = rand() % items->count;
- int old_value = items->values[item];
- items->values[item] = rand() + 1;
- if (ck_update_item(table, items->keys[item],
- items->key_sizes[item],
- (void *)items->values[item], NULL) != 0
- && items->deleted[item] == 1) {
- ++errors;
- items->values[item] = old_value;
- }
- }
-
- return 1;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_rehash(ck_hash_table_t *table)
-{
- return (ck_rehash(table) == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_resize(ck_hash_table_t *table)
-{
- // test the resize explicitly
- return (ck_resize_table(table) == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_cuckoo_full(ck_hash_table_t *table, test_cuckoo_items *items)
-{
- // invoke the resize by inserting so much items that thay cannot
- // fit into the table
- int new_count = table->items;
-
- while (new_count < hashsize(table->table_size_exp) * table->table_count) {
- new_count += table->items;
- }
-
- note("Old item count: %d, new count: %d, capacity of the table: %d\n",
- table->items, new_count,
- hashsize(table->table_size_exp) * table->table_count);
-
- assert(new_count <= items->total_count);
-
- int errors = 0;
-
- for (int i = items->count; i < new_count; ++i) {
- assert(items->values[i] != 0);
- if (ck_insert_item(table, items->keys[i], items->key_sizes[i],
- (void *)items->values[i]) != 0) {
- ++errors;
- }
- }
-
- items->count = new_count;
-
- return (errors == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void create_random_items(test_cuckoo_items *items, int item_count)
-{
- assert(items != NULL);
-
- items->count = item_count;
- items->total_count = item_count * 10;
- items->values = (size_t *)malloc(items->total_count * sizeof(size_t));
- items->key_sizes = (size_t *)malloc(items->total_count * sizeof(size_t));
- items->deleted = (size_t *)malloc(items->total_count * sizeof(size_t));
- items->keys = (char **)malloc(items->total_count * sizeof(char *));
-
- for (int i = 0; i < items->total_count; ++i) {
- int value = rand() + 1;
- int key_size = rand() % CUCKOO_TEST_MAX_KEY_SIZE + 1;
- char *key = malloc(key_size * sizeof(char));
- assert(key != NULL);
- rand_str(key, key_size);
-
- // check if the key is not already in the table
- int found = 0;
- for (int j = 0; j < i; ++j) {
- if (items->key_sizes[j] == key_size
- && strncmp(items->keys[j], key, key_size) == 0) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- assert(value != 0);
- items->values[i] = value;
- items->key_sizes[i] = key_size;
- items->keys[i] = key;
- items->deleted[i] = 0;
- } else {
- free(key);
- --i;
- }
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void delete_items(test_cuckoo_items *items)
-{
- free(items->deleted);
- free(items->key_sizes);
- free(items->values);
- for (int i = 0; i < items->total_count; ++i) {
- free(items->keys[i]);
- }
- free(items->keys);
-}
-
-/*----------------------------------------------------------------------------*/
-
-/*! Run all scheduled tests for given parameters.
- */
-static int cuckoo_tests_run(int argc, char *argv[])
-{
- srand(time(NULL));
- int res;
-
- const int item_count = rand() % CUCKOO_MAX_ITEMS + 1;
- test_cuckoo_items *items = (test_cuckoo_items *)
- malloc(sizeof(test_cuckoo_items));
-
- ck_hash_table_t *table = NULL;
-
- // Test 1: create
- ok(res = test_cuckoo_create(&table, item_count),
- "cuckoo hashing: create");
-
- create_random_items(items, item_count);
-
- skip(!res, 10);
- // Test 2: insert
- ok(test_cuckoo_insert(table, items), "cuckoo hashing: insert");
-
- // Test 3: lookup
- ok(test_cuckoo_lookup(table, items), "cuckoo hashing: lookup");
-
- // Test 4: delete
- ok(test_cuckoo_delete(table, items), "cuckoo hashing: delete");
-
- // Test 5: lookup 2
- ok(test_cuckoo_lookup(table, items),
- "cuckoo hashing: lookup after delete");
-
- // Test 6: modify
- ok(test_cuckoo_modify(table, items), "cuckoo hashing: modify");
-
- // Test 7: lookup 3
- ok(test_cuckoo_lookup(table, items),
- "cuckoo hashing: lookup after modify");
-
- // Test 8: rehash
- ok(test_cuckoo_rehash(table), "cuckoo hashing: rehash");
-
- // Test 9: lookup 4
- ok(test_cuckoo_lookup(table, items),
- "cuckoo hashing: lookup after rehash");
-
- // Test 10: resize
- ok(test_cuckoo_resize(table), "cuckoo hashing: resize");
-
- // Test 11: lookup 5
- ok(test_cuckoo_lookup(table, items),
- "cuckoo hashing: lookup after resize");
-
- // Test 12: owerflow the table
- ok(test_cuckoo_full(table, items), "cuckoo hashing: overflow");
-
- // Test 13: lookup 5
- ok(test_cuckoo_lookup(table, items),
- "cuckoo hashing: lookup after overflow");
-
- endskip;
-
- /**
- * \note These last 2 tests found some major bug in the cuckoo hash
- * table, so running them results in abort upon assertion.
- * Disabled for now.
- */
-
- // Cleanup
- ck_destroy_table(&table, NULL, 0);
- delete_items(items);
- free(items);
-
- return 0;
-}
diff --git a/src/tests/libknot/libknot/dname_table_tests.c b/src/tests/libknot/libknot/dname_table_tests.c
deleted file mode 100644
index 991f1c6..0000000
--- a/src/tests/libknot/libknot/dname_table_tests.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-/* blame: jan.kadlec@nic.cz */
-
-#include <assert.h>
-
-#include "dname_table_tests.h"
-#include "libknot/zone/dname-table.h"
-/* *test_t structures */
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-
-static int knot_dname_table_tests_count(int argc, char *argv[]);
-static int knot_dname_table_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api dname_table_tests_api = {
- "Dname table", //! Unit name
- &knot_dname_table_tests_count, //! Count scheduled tests
- &knot_dname_table_tests_run //! Run scheduled tests
-};
-
-/* Helper functions. */
-static knot_dname_t *dname_from_test_dname_str(const test_dname_t *test_dname)
-{
- assert(test_dname != NULL);
- knot_dname_t *ret = knot_dname_new_from_str (test_dname->str,
- strlen(test_dname->str),
- NULL);
- CHECK_ALLOC(ret, NULL);
-
- return ret;
-}
-
-static int dname_compare_sort_wrapper(const void *ptr1, const void *ptr2)
-{
- const knot_dname_t *dname1 =
- dname_from_test_dname_str((const test_dname_t *)ptr1);
- const knot_dname_t *dname2 =
- dname_from_test_dname_str((const test_dname_t *)ptr2);
- assert(dname1 && dname2);
- return knot_dname_compare(dname1, dname2);
-}
-
-/* Unit implementation. */
-enum {DNAME_TABLE_DNAME_COUNT = 3};
-
-/* Strings are enough, we're not testing dname here ... */
-static test_dname_t DNAME_TABLE_DNAMES[DNAME_TABLE_DNAME_COUNT] = {
- /* list ptr, string, wire, length, labels, label_count */
- {NULL, NULL, ".", NULL, 1, NULL, 0},
- {NULL, NULL, "a.ns.nic.cz.", NULL, 13, NULL, 0},
- {NULL, NULL, "b.ns.nic.cz.", NULL, 13, NULL, 0}
-};
-
-static int test_dname_table_new()
-{
- knot_dname_table_t *table = knot_dname_table_new();
- if (table == NULL) {
- return 0;
- }
-
- knot_dname_table_free(&table);
- return 1;
-}
-
-struct test_dname_table_arg {
- /* Times two - safety measure. */
- knot_dname_t *array[DNAME_TABLE_DNAME_COUNT * 2];
- uint count;
-};
-
-static void save_dname_to_array(knot_dname_t *node, void *data)
-{
- assert(data);
- struct test_dname_table_arg *arg = (struct test_dname_table_arg *)data;
- arg->array[arg->count] = node;
- arg->count++;
-}
-
-static int test_dname_table_adding()
-{
- int errors = 0;
- knot_dname_table_t *table = knot_dname_table_new();
- CHECK_ALLOC(table, 0);
-
- /* Add NULL */
- if (knot_dname_table_add_dname(table, NULL) != KNOT_EINVAL) {
- diag("Adding NULL dname did not result in an error!");
- errors++;
- }
-
- /* Add to NULL table*/
- if (knot_dname_table_add_dname(NULL, NULL) != KNOT_EINVAL) {
- diag("Adding to NULL table did not result in an error!");
- errors++;
- }
-
- /* Add NULL */
- if (knot_dname_table_add_dname_check(table, NULL) != KNOT_EINVAL) {
- diag("Adding NULL dname did not result in an error!");
- errors++;
- }
-
- /* Add to NULL table*/
- if (knot_dname_table_add_dname_check(NULL, NULL) != KNOT_EINVAL) {
- diag("Adding to NULL table did not result in an error!");
- errors++;
- }
-
-
- /* Add valid dnames. */
- for (int i = 0; i < DNAME_TABLE_DNAME_COUNT; i++) {
- knot_dname_t *dname =
- dname_from_test_dname_str(&DNAME_TABLE_DNAMES[i]);
- if (!dname) {
- diag("Could not create dname from test dname!");
- errors++;
- continue;
- }
- if (knot_dname_table_add_dname(table, dname) != KNOT_EOK) {
- diag("Could not add dname! (%s)",
- DNAME_TABLE_DNAMES[i].str);
- errors++;
- }
- }
-
- /*
- * Using inorder traversal of the table,
- * create array containing dnames.
- */
-
- struct test_dname_table_arg arg;
- arg.count = 0;
-
- knot_dname_table_tree_inorder_apply(table, save_dname_to_array, &arg);
-
- if (arg.count != DNAME_TABLE_DNAME_COUNT) {
- diag("Table contains too many dnames!");
- /* No sense in continuing. */
- knot_dname_table_deep_free(&table);
- return 0;
- }
-
- /*
- * Check that inordered array is really sorted
- * and contains valid dnames.
- */
- for (int i = 0; i < DNAME_TABLE_DNAME_COUNT; i++) {
- assert(arg.array[i]);
- const char *str = knot_dname_to_str(arg.array[i]);
- if (str == NULL) {
- diag("Wrong dname in table!");
- errors++;
- continue;
- }
-
- if (arg.array[i]->size !=
- DNAME_TABLE_DNAMES[i].size) {
- diag("Wrong dname size in table!");
- diag("Is: %u should be %u.",
- arg.array[i]->size,
- DNAME_TABLE_DNAMES[i].size);
- errors++;
- continue;
- }
-
- if (strncmp(str, DNAME_TABLE_DNAMES[i].str,
- DNAME_TABLE_DNAMES[i].size) != 0) {
- diag("Wrong dname wire in table!");
- errors++;
- }
- }
-
- /* Now add one dname once again. It has to be the first item! */
-
- if (knot_dname_table_add_dname(table,
- dname_from_test_dname_str(&DNAME_TABLE_DNAMES[0])) !=
- KNOT_EOK) {
- diag("Could not add dname to table once it's already there!");
- /* Next test would not make sense. */
- knot_dname_table_deep_free(&table);
- return 0;
- }
-
- /*
- * After walking the table, there should now be
- * DNAME_TABLE_DNAME_COUNT + 1 items, with 2 identical
- * items at the beginning.
- */
-
- memset(arg.array, 0,
- sizeof(knot_dname_t *) * DNAME_TABLE_DNAME_COUNT * 2);
- arg.count = 0;
- knot_dname_table_tree_inorder_apply(table, save_dname_to_array, &arg);
-
- if (arg.count != DNAME_TABLE_DNAME_COUNT + 1) {
- diag("Identical dname was not added!");
- /* Again, next test would not make any sense. */
- knot_dname_table_deep_free(&table);
- return 0;
- }
-
- if (knot_dname_compare(arg.array[0], arg.array[1]) != 0) {
- diag("First two dnames in table are not identical!");
- errors++;
- }
-
- /* Delete table, wipe out array. */
- knot_dname_table_deep_free(&table);
- memset(arg.array, 0,
- sizeof(knot_dname_t *) * DNAME_TABLE_DNAME_COUNT * 2);
- arg.count = 0;
-
- table = knot_dname_table_new();
- assert(table);
-
- /*
- * Add dname with same content twice using knot_dname_table_add2 -
- * table should now only contain one item.
- */
-
- knot_dname_t *tmp_dname =
- dname_from_test_dname_str(&DNAME_TABLE_DNAMES[0]);
- assert(tmp_dname);
-
- if (knot_dname_table_add_dname_check(table, &tmp_dname) != KNOT_EOK) {
- diag("Could not add dname using dname_table_add_dname2!");
- knot_dname_table_deep_free(&table);
- knot_dname_free(&tmp_dname);
- return 0;
- }
-
- tmp_dname = dname_from_test_dname_str(&DNAME_TABLE_DNAMES[0]);
- assert(tmp_dname);
-
- knot_dname_t *dname_before_add = tmp_dname;
-
- if (knot_dname_table_add_dname_check(table, &tmp_dname) != 1) {
- diag("Could not add dname again using dname_table_add_dname2!");
- knot_dname_table_deep_free(&table);
- return 0;
- }
-
- if (tmp_dname == dname_before_add) {
- diag("Dname was not freed after insertion!");
- errors++;
- }
-
- knot_dname_table_tree_inorder_apply(table, save_dname_to_array, &arg);
-
- if (arg.count != 1) {
- diag("Add_dname2 has added dname when it shouldn't!");
- errors++;
- }
-
- if (knot_dname_compare(tmp_dname, arg.array[0]) != 0) {
- diag("Add_dname2 has added wrong dname!");
- errors++;
- }
-
- knot_dname_table_deep_free(&table);
- return (errors == 0);
-}
-
-static int test_dname_table_find()
-{
- int errors = 0;
- knot_dname_table_t *table = knot_dname_table_new();
- assert(table);
-
- if (knot_dname_table_find_dname(table, NULL) != NULL) {
- diag("Dname table did not return NULL when searching NULL!");
- errors++;
- }
-
- if (knot_dname_table_find_dname(NULL, NULL) != NULL) {
- diag("Passing NULL instead of dname table did not "
- "return NULL!");
- errors++;
- }
-
- /* Add all dnames but the last one. */
- for (int i = 0; i < DNAME_TABLE_DNAME_COUNT - 1; i++) {
- knot_dname_t *dname =
- dname_from_test_dname_str(&DNAME_TABLE_DNAMES[i]);
- if (!dname) {
- diag("Could not create dname from test dname!");
- errors++;
- continue;
- }
- if (knot_dname_table_add_dname(table, dname) != KNOT_EOK) {
- diag("Could not add dname! (%s)",
- DNAME_TABLE_DNAMES[i].str);
- errors++;
- }
- }
-
- /* Search for added dnames. */
- for (int i = 0; i < DNAME_TABLE_DNAME_COUNT - 1; i++) {
- knot_dname_t *dname =
- dname_from_test_dname_str(&DNAME_TABLE_DNAMES[i]);
- if (!dname) {
- diag("Could not create dname from test dname!");
- errors++;
- continue;
- }
-
- knot_dname_t *found_dname =
- knot_dname_table_find_dname(table, dname);
-
- if (found_dname == NULL) {
- diag("Dname table did not return "
- "dname when it should!");
- errors++;
- continue;
- }
-
- if (knot_dname_compare(found_dname, dname) != 0) {
- diag("Returned dname did not match!");
- errors++;
- continue;
- }
- }
-
- /* Search for last dname, it should return NULL. */
- knot_dname_t *dname =
- dname_from_test_dname_str(
- &DNAME_TABLE_DNAMES[DNAME_TABLE_DNAME_COUNT]);
- assert(dname);
-
- if (knot_dname_table_find_dname(table, dname) != NULL) {
- diag("Dname table returned dname when it "
- "should not be there!");
- errors++;
- }
-
- knot_dname_free(&dname);
- knot_dname_table_deep_free(&table);
-
- return (errors == 0);
-}
-
-static const int KNOT_DNAME_TABLE_TEST_COUNT = 3;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_dname_table_tests_count(int argc, char *argv[])
-{
- return KNOT_DNAME_TABLE_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_dname_table_tests_run(int argc, char *argv[])
-{
- int final_res = 1;
- int res = 0;
-
- /* Sort array containing test dnames. */
- qsort(DNAME_TABLE_DNAMES, DNAME_TABLE_DNAME_COUNT,
- sizeof(test_dname_t), dname_compare_sort_wrapper);
-
- ok((res = test_dname_table_new()), "dname table: new");
- final_res *= res;
-
- skip(!res, 2);
-
- ok((res = test_dname_table_adding()), "dname table: adding");
- final_res *= res;
-
- ok((res = test_dname_table_find()), "dname table: searching");
- final_res *= res;
-
- endskip;
-
- return final_res;
-}
diff --git a/src/tests/libknot/libknot/dname_tests.c b/src/tests/libknot/libknot/dname_tests.c
deleted file mode 100644
index 35ac230..0000000
--- a/src/tests/libknot/libknot/dname_tests.c
+++ /dev/null
@@ -1,936 +0,0 @@
-/* Copyright (C) 2011 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 <string.h>
-#include <assert.h>
-
-#include "tests/libknot/libknot/dname_tests.h"
-#include "libknot/dname.h"
-#include "libknot/zone/node.h"
-
-static int knot_dname_tests_count(int argc, char *argv[]);
-static int knot_dname_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api dname_tests_api = {
- "DNS library - dname", //! Unit name
- &knot_dname_tests_count, //! Count scheduled tests
- &knot_dname_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-// C will not accept const int in other const definition
-enum { TEST_DOMAINS_OK = 8 };
-
-enum { TEST_DOMAINS_BAD = 5 };
-
-enum { TEST_DOMAINS_NON_FQDN = 6 };
-
-static knot_node_t *NODE_ADDRESS = (knot_node_t *)0xDEADBEEF;
-
-struct test_domain {
- char *str;
- char *wire;
- uint size;
- char *labels;
- short label_count;
-};
-
-/*! \warning Do not change the order in those, if you want to test some other
- * feature with new dname, add it at the end of these arrays.
- */
-static const struct test_domain
- test_domains_ok[TEST_DOMAINS_OK] = {
- { "abc.test.domain.com.", "\3abc\4test\6domain\3com", 21,
- "\x0\x4\x9\x10", 4 },
- { "some.test.domain.com.", "\4some\4test\6domain\3com", 22,
- "\x0\x5\xA\x11", 4 },
- { "xyz.test.domain.com.", "\3xyz\4test\6domain\3com", 21,
- "\x0\x4\x9\x10", 4 },
- { "some.test.domain.com.", "\4some\4test\6domain\3com", 22,
- "\x0\x5\xA\x11", 4 },
- { "test.domain.com.", "\4test\6domain\3com", 17,
- "\x0\x5\xC", 3 },
- { ".", "\0", 1,
- "", 0 },
- { "foo.bar.net.", "\3foo\3bar\3net", 13,
- "\x0\x4\x8", 3},
- { "bar.net.", "\3bar\3net", 9,
- "\x0\x4", 2}
-};
-
-static const struct test_domain // sizes are strlen()s here
- test_domains_non_fqdn[TEST_DOMAINS_NON_FQDN] = {
- { "www", "\3www", 4, "\x0", 1 },
- { "example", "\7example", 8, "\x0", 1 },
- { "com", "\3com", 4, "\x0", 1 },
- { "www.example.com", "\3www\7example\3com", 16, "\x0\x4\xC",
- 3 },
- { "some", "\4some", 5, "\x0", 1 },
- { "example.com", "\7example\3com", 12, "\x0\x8", 2 }
- };
-
-static const struct test_domain
- test_domains_bad[TEST_DOMAINS_BAD] = {
- { NULL, "\2ex\3com", 0, "", 0 },
- { "ex.com.", NULL, 0, "", 0 },
- { "ex.com.\5", "\3ex\3com\0\5", 10, "", 0 },
- { "example.com", "\3example\3com", 12, "\x0\x8", 2 },
- { "example..", "\7example\0\0", 12, "\x0\x8", 2 }
-};
-
-static int test_dname_create()
-{
- knot_dname_t *dname = knot_dname_new();
- if (dname == NULL
- || knot_dname_name(dname) != NULL
- || knot_dname_size(dname) != 0
- || knot_dname_node(dname) != NULL) {
- diag("New domain name not initialized properly!");
- return 0;
- }
- knot_dname_free(&dname);
- if (dname != NULL) {
- diag("Pointer to the structure not set to"
- "NULL when deallocating!");
- return 0;
- }
- return 1;
-}
-
-static int test_dname_delete()
-{
- // how to test this??
- return 0;
-}
-
-static int check_domain_name(const knot_dname_t *dname,
- const struct test_domain *test_domains, int i,
- int check_node)
-{
- int errors = 0;
-
- if (dname == NULL) {
- diag("Domain name #%d not created!", i);
- return 1;
- }
-
- // check size
- if (knot_dname_size(dname) != test_domains[i].size) {
- diag("Bad size of the created domain name: %u (should be %u).",
- knot_dname_size(dname), test_domains[i].size);
- ++errors;
- }
- // check wire format
- uint size = knot_dname_size(dname);
- if (strncmp((char *)knot_dname_name(dname),
- test_domains[i].wire, size) != 0) {
- diag("The wire format of the created domain name is wrong:"
- " '%.*s' (should be '%.*s').",
- size, knot_dname_name(dname),
- size, test_domains[i].wire);
- ++errors;
- }
- // check labels
- if (test_domains[i].label_count != dname->label_count) {
- diag("Label count of the created domain name is wrong:"
- " %d (should be %d)\n", dname->label_count,
- test_domains[i].label_count);
- ++errors;
- }
- if (strncmp((char *)dname->labels, test_domains[i].labels,
- test_domains[i].label_count) != 0) {
- diag("Label offsets of the created domain name are wrong.\n");
- ++errors;
- }
-
- if (check_node) {
- if (knot_dname_node(dname) != NODE_ADDRESS) {
- diag("Node pointer in the created domain name is wrong:"
- "%p (should be %p)",
- knot_dname_node(dname), NODE_ADDRESS);
- ++errors;
- }
- }
-
- return errors;
-}
-
-static int test_dname_create_from_str()
-{
- int errors = 0;
- knot_dname_t *dname = NULL;
-
- for (int i = 0; i < TEST_DOMAINS_OK && errors == 0; ++i) {
- //note("testing domain: %s", test_domains_ok[i].str);
- dname = knot_dname_new_from_str(test_domains_ok[i].str,
- strlen(test_domains_ok[i].str), NODE_ADDRESS);
- errors += check_domain_name(dname, test_domains_ok, i, 1);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_create_from_str_non_fqdn()
-{
- int errors = 0;
- knot_dname_t *dname = NULL;
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; ++i) {
-// note("testing domain: %s, size: %zu",
-// test_domains_non_fqdn[i].str,
-// strlen(test_domains_non_fqdn[i].str));
- dname = knot_dname_new_from_str(test_domains_non_fqdn[i].str,
- strlen(test_domains_non_fqdn[i].str), NULL);
- errors += check_domain_name(dname, test_domains_non_fqdn, i, 0);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_cat()
-{
- int errors = 0;
-
- /*
- * This uses three particular dnames from test_domains structure
- * where the third dname is a concatenation of the first two dnames.
- */
-
- knot_dname_t *d1, *d2, *d3;
-
- d1 = knot_dname_new_from_str(test_domains_non_fqdn[0].str,
- strlen(test_domains_non_fqdn[0].str), NULL);
- d2 = knot_dname_new_from_str(test_domains_non_fqdn[1].str,
- strlen(test_domains_non_fqdn[1].str), NULL);
- d3 = knot_dname_new_from_str(test_domains_non_fqdn[2].str,
- strlen(test_domains_non_fqdn[2].str), NULL);
-
- knot_dname_cat(d1, d2);
- knot_dname_cat(d1, d3);
-
- errors += check_domain_name(d1, test_domains_non_fqdn, 3, 0);
-
- knot_dname_free(&d1);
- knot_dname_free(&d2);
- knot_dname_free(&d3);
-
- /*
- * Same thing as above, only different case.
- */
-
- d1 = knot_dname_new_from_str(test_domains_non_fqdn[4].str,
- strlen(test_domains_non_fqdn[4].str),
- NODE_ADDRESS);
-
- d2 = knot_dname_new_from_str(test_domains_ok[4].str,
- strlen(test_domains_ok[4].str),
- NODE_ADDRESS);
-
- knot_dname_cat(d1, d2);
-
- errors += check_domain_name(d1, test_domains_ok, 1, 1);
-
- knot_dname_free(&d1);
- knot_dname_free(&d2);
-
- return (errors == 0);
-}
-
-static int test_dname_left_chop()
-{
- int errors = 0;
-
- /* Uses same principle as test_dname_cat(), only reversed */
-
- /* TODO this would maybe deserver separate structure */
-
- knot_dname_t *d1;
-
- d1 = knot_dname_new_from_str(test_domains_ok[1].str,
- strlen(test_domains_ok[1].str),
- NODE_ADDRESS);
-
- knot_dname_t *chopped;
-
- chopped = knot_dname_left_chop(d1);
-
- errors += check_domain_name(chopped, test_domains_ok, 4, 0);
-
- knot_dname_free(&d1);
- knot_dname_free(&chopped);
-
- d1 = knot_dname_new_from_str(test_domains_non_fqdn[3].str,
- strlen(test_domains_non_fqdn[3].str),
- NODE_ADDRESS);
-
- chopped = knot_dname_left_chop(d1);
-
- errors += check_domain_name(chopped, test_domains_non_fqdn, 5, 0);
-
- knot_dname_free(&d1);
- knot_dname_free(&chopped);
-
- return (errors == 0);
-}
-
-static int test_dname_create_from_wire()
-{
- int errors = 0;
- knot_dname_t *dname = NULL;
-
- for (int i = 0; i < TEST_DOMAINS_OK && errors == 0; ++i) {
- assert(strlen(test_domains_ok[i].wire) + 1 ==
- test_domains_ok[i].size);
- dname = knot_dname_new_from_wire(
- (uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size, NODE_ADDRESS);
- errors += check_domain_name(dname, test_domains_ok, i, 1);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_to_str()
-{
- int errors = 0;
-
- /*
- * Converts dname wireformat to string represenation, which is compared
- * with entries in test_domains structure.
- */
-
- knot_dname_t *dname = NULL;
-
- for (int i = 0; i < TEST_DOMAINS_OK && errors == 0; ++i) {
- dname = knot_dname_new_from_wire(
- (uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size, NODE_ADDRESS);
- char *name_str = knot_dname_to_str(dname);
- if (strcmp(name_str, test_domains_ok[i].str) != 0) {
- diag("Presentation format of domain name wrong:"
- " %s (should be %s)",
- name_str, test_domains_ok[i].str);
- ++errors;
- }
- free(name_str);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-/* called by lives_ok */
-static int test_faulty_data()
-{
- knot_dname_t *dname = NULL;
-
- /*
- * This takes dnames from test_domains_bad array, which contains
- * malformed dnames. TODO add something like: 2www3foo - it's gonna fail
- */
-
- for (int i = 0; i < TEST_DOMAINS_BAD; i++) {
-
- if (test_domains_bad[i].str != NULL) {
- dname = knot_dname_new_from_str(
- test_domains_bad[i].str,
- strlen(test_domains_bad[i].str),
- NODE_ADDRESS);
- } else {
- dname = knot_dname_new_from_str(
- test_domains_bad[i].str, 0, NODE_ADDRESS);
- }
-
- knot_dname_free(&dname);
-
- dname = knot_dname_new_from_wire(
- (uint8_t *)test_domains_bad[i].wire,
- test_domains_bad[i].size, NODE_ADDRESS);
-
- knot_dname_free(&dname);
- }
-
- return 1; //did it get here? success
-}
-
-static int test_dname_compare()
-{
- knot_dname_t *dnames[TEST_DOMAINS_OK];
-
- /* This uses particular dnames from TEST_DOMAINS_OK array */
-
- for (int i = 0; i < TEST_DOMAINS_OK; ++i) {
- dnames[i] = knot_dname_new_from_wire(
- (uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size, NODE_ADDRESS);
- }
-
- int errors = 0;
- /* abc < some */
- if (knot_dname_compare(dnames[0], dnames[1]) >= 0) {
- diag("Dname comparison error");
- errors++;
- }
-
- /* abc.test.domain.com. < foo.bar.net. */
- if (knot_dname_compare(dnames[0], dnames[6]) >= 0) {
- diag("Dname comparison error");
- errors++;
- }
-
- /* foo.bar.net. < . */
- if (knot_dname_compare(dnames[5], dnames[0]) >= 0) {
- diag("Dname comparison error");
- errors++;
- }
-
- /* bar.net. < foo.bar.net. */
- if (knot_dname_compare(dnames[7], dnames[6]) >= 0) {
- diag("Dname comparison error");
- errors++;
- }
-
- /* some == some */
- if (knot_dname_compare(dnames[1], dnames[3]) != 0) {
- diag("Dname comparison error");
- errors++;
- }
-
- /*xyz > some */
- if (knot_dname_compare(dnames[2], dnames[1]) <= 0) {
- diag("Dname comparison error");
- errors++;
- }
-
- /*foo.bar.net. > xyz.test.domain.com. */
- if (knot_dname_compare(dnames[6], dnames[3]) <= 0) {
- diag("Dname comparison error");
- errors++;
- }
-
-// /* xyz.test.domain.com. > . */
-// if (knot_dname_compare(dnames[3], dnames[5]) <= 0) {
-// diag("Dname comparison error");
-// errors++;
-// }
-
- /* bar.net. < foo.bar.net. */
- if (knot_dname_compare(dnames[6], dnames[7]) <= 0) {
- diag("Dname comparison error");
- errors++;
- }
-
- for (int i = 0; i < TEST_DOMAINS_OK; i++) {
- knot_dname_free(&dnames[i]);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_is_fqdn()
-{
- int errors = 0;
-
- knot_dname_t *dname;
-
- /* All dnames in TEST_DOMAINS_OK are fqdn */
-
- for (int i = 0; i < TEST_DOMAINS_OK && !errors; ++i) {
- dname = knot_dname_new_from_wire(
- (uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size, NODE_ADDRESS);
- errors += !knot_dname_is_fqdn(dname);
- knot_dname_free(&dname);
- }
-
- /* None of the following dnames should be fqdn */
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN && !errors; ++i) {
- dname = knot_dname_new_from_str(test_domains_non_fqdn[i].str,
- strlen(test_domains_non_fqdn[i].str), NULL);
- errors += knot_dname_is_fqdn(dname);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_is_subdomain()
-{
- int errors = 0;
-
- knot_dname_t *dnames_fqdn[TEST_DOMAINS_OK];
- knot_dname_t *dnames_non_fqdn[TEST_DOMAINS_NON_FQDN];
-
- for (int i = 0; i < TEST_DOMAINS_OK; ++i) {
- dnames_fqdn[i] = knot_dname_new_from_wire(
- (const uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size, NULL);
- assert(dnames_fqdn[i] != NULL);
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; ++i) {
- dnames_non_fqdn[i] = knot_dname_new_from_str(
- test_domains_non_fqdn[i].str,
- strlen(test_domains_non_fqdn[i].str), NULL);
- assert(dnames_non_fqdn[i] != NULL);
- }
-
- // fqdn names 0 - 3 should be subdomains of name 4
- knot_dname_t *parent = dnames_fqdn[4];
- for (int i = 0; i < 3; ++i) {
- if (!knot_dname_is_subdomain(dnames_fqdn[i], parent)) {
- diag("(fqdn 1-%d) "
- "Name %s was not considered subdomain of %s", i,
- knot_dname_name(dnames_fqdn[i]),
- knot_dname_name(parent));
- ++errors;
- }
- }
-
- // fqdn names 0 - 4 should be subdomains of name 5 (root)
- parent = dnames_fqdn[5];
- for (int i = 0; i < 4; ++i) {
- if (!knot_dname_is_subdomain(dnames_fqdn[i], parent)) {
- diag("(fqdn 2-%d) "
- "Name %s was not considered subdomain of %s", i,
- knot_dname_name(dnames_fqdn[i]),
- knot_dname_name(parent));
- ++errors;
- }
- }
-
- // non-fqdn names 3 and 5 should be subdomains of non-fqdn name 2
- parent = dnames_non_fqdn[2];
- if (!knot_dname_is_subdomain(dnames_non_fqdn[3], parent)) {
- diag("(non-fqdn 1) "
- "Name %.*s was not considered subdomain of %.*s",
- knot_dname_size(dnames_non_fqdn[3]),
- knot_dname_name(dnames_non_fqdn[3]),
- knot_dname_size(parent),
- knot_dname_name(parent));
- ++errors;
- }
- if (!knot_dname_is_subdomain(dnames_non_fqdn[5], parent)) {
- diag("(non-fqdn 2) "
- "Name %.*s was not considered subdomain of %.*s",
- knot_dname_size(dnames_non_fqdn[5]),
- knot_dname_name(dnames_non_fqdn[5]),
- knot_dname_size(parent),
- knot_dname_name(parent));
- ++errors;
- }
-
- // non-fqdn name 3 should be subdomain of non-fqdn name 5
- parent = dnames_non_fqdn[5];
- if (!knot_dname_is_subdomain(dnames_non_fqdn[3], parent)) {
- diag("(non-fqdn 3) "
- "Name %.*s was not considered subdomain of %.*s",
- knot_dname_size(dnames_non_fqdn[3]),
- knot_dname_name(dnames_non_fqdn[3]),
- knot_dname_size(parent),
- knot_dname_name(parent));
- ++errors;
- }
-
- // identical names should not be considered subdomains
- if (knot_dname_is_subdomain(dnames_fqdn[0], dnames_fqdn[0])) {
- diag("(identical names) "
- "Name %s was considered subdomain of itself",
- knot_dname_name(dnames_fqdn[0]));
- ++errors;
- }
- if (knot_dname_is_subdomain(dnames_fqdn[1], dnames_fqdn[3])) {
- diag("(identical names) "
- "Name %s was considered subdomain of %s",
- knot_dname_name(dnames_fqdn[1]),
- knot_dname_name(dnames_fqdn[3]));
- ++errors;
- }
-
- // fqdn name should not be considered subdomain of non-fqdn name
- if (knot_dname_is_subdomain(dnames_fqdn[1], dnames_non_fqdn[2])) {
- diag("(fqdn subdomain of non-fqdn) "
- "Name %s was considered subdomain of %.*s",
- knot_dname_name(dnames_fqdn[1]),
- knot_dname_size(dnames_non_fqdn[2]),
- knot_dname_name(dnames_non_fqdn[2]));
- ++errors;
- }
-
- // non-fqdn name should not be considered subdomain of fqdn name
- if (knot_dname_is_subdomain(dnames_fqdn[1], dnames_non_fqdn[2])) {
- diag("(non-fqdn subdomain of fqdn) "
- "Name %s was considered subdomain of %.*s",
- knot_dname_name(dnames_fqdn[1]),
- knot_dname_size(dnames_non_fqdn[2]),
- knot_dname_name(dnames_non_fqdn[2]));
- ++errors;
- }
-
- // parent name should not be considered subdomain of its subdomain
- if (knot_dname_is_subdomain(dnames_fqdn[4], dnames_fqdn[0])) {
- diag("(ancestor subdomain of name) "
- "Name %s was considered subdomain of %s",
- knot_dname_name(dnames_fqdn[4]),
- knot_dname_name(dnames_fqdn[0]));
- ++errors;
- }
-
- for (int i = 0; i < TEST_DOMAINS_OK; ++i) {
- knot_dname_free(&dnames_fqdn[i]);
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; ++i) {
- knot_dname_free(&dnames_non_fqdn[i]);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_deep_copy() {
- int errors = 0;
-
- knot_dname_t *dnames_fqdn[TEST_DOMAINS_OK];
- knot_dname_t *dnames_non_fqdn[TEST_DOMAINS_NON_FQDN];
- knot_dname_t *dnames_fqdn_copy[TEST_DOMAINS_OK];
- knot_dname_t *dnames_non_fqdn_copy[TEST_DOMAINS_NON_FQDN];
-
- for (int i = 0; i < TEST_DOMAINS_OK; ++i) {
- dnames_fqdn[i] = knot_dname_new_from_wire(
- (const uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size, NODE_ADDRESS);
- assert(dnames_fqdn[i] != NULL);
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; ++i) {
- dnames_non_fqdn[i] = knot_dname_new_from_str(
- test_domains_non_fqdn[i].str,
- strlen(test_domains_non_fqdn[i].str),
- NODE_ADDRESS);
-// note("Created name: %.*s\n", dnames_non_fqdn[i]->size,
-// dnames_non_fqdn[i]->name);
- assert(dnames_non_fqdn[i] != NULL);
- }
-
- /*
- * Create copies of the domain names.
- */
- for (int i = 0; i < TEST_DOMAINS_OK; ++i) {
-// note("Testing %d. FQDN domain.\n", i);
- dnames_fqdn_copy[i] = knot_dname_deep_copy(dnames_fqdn[i]);
- assert(dnames_fqdn_copy[i] != NULL);
- errors += check_domain_name(dnames_fqdn_copy[i],
- test_domains_ok, i, 1);
- knot_dname_free(&dnames_fqdn_copy[i]);
- knot_dname_free(&dnames_fqdn[i]);
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; ++i) {
-// note("Testing %d. non-FQDN domain: ", i);
-// note("%.*s\n", dnames_non_fqdn[i]->size,
-// dnames_non_fqdn[i]->name);
- dnames_non_fqdn_copy[i] =
- knot_dname_deep_copy(dnames_non_fqdn[i]);
- assert(dnames_non_fqdn_copy[i] != NULL);
- errors += check_domain_name(dnames_non_fqdn_copy[i],
- test_domains_non_fqdn, i, 1);
- knot_dname_free(&dnames_non_fqdn_copy[i]);
- knot_dname_free(&dnames_non_fqdn[i]);
- }
-
- return (errors == 0);
-}
-
-static int check_wires(const uint8_t *wire1, uint size1,
- uint8_t *wire2, uint size2)
-{
- if (size1 != size2) {
- return 0;
- }
-
- int i;
-
- for (i = 0; (i < size1); i++) {
- if (wire1[i] != wire2[i]) {
- return 0;
- }
- }
-
- return 1;
-}
-
-/*!< \note not to be run separately */
-static int test_dname_name(knot_dname_t **dnames_fqdn,
- knot_dname_t **dnames_non_fqdn)
-{
- assert(dnames_fqdn);
- assert(dnames_non_fqdn);
-
- int errors = 0;
-
- for (int i = 0; i < TEST_DOMAINS_OK; i++) {
- const uint8_t *tmp_name;
-
- tmp_name = knot_dname_name(dnames_fqdn[i]);
- if (!check_wires(tmp_name, dnames_fqdn[i]->size,
- (uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size)) {
- diag("Got bad name value from structure: "
- "%s, should be: %s. Sizes: %d and: %d",
- tmp_name, test_domains_ok[i].wire,
- dnames_fqdn[i]->size,
- test_domains_ok[i].size);
- errors++;
- }
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
- const uint8_t *tmp_name;
- tmp_name = knot_dname_name(dnames_non_fqdn[i]);
- if (!check_wires(tmp_name, dnames_non_fqdn[i]->size,
- (uint8_t *)test_domains_non_fqdn[i].wire,
- test_domains_non_fqdn[i].size)) {
- diag("Got bad name value from structure: "
- "%s, should be: %s. Sizes: %d and %d\n",
- tmp_name, test_domains_non_fqdn[i].wire,
- dnames_non_fqdn[i]->size,
- test_domains_non_fqdn[i].size);
-// hex_print(dnames_non_fqdn[i]->name,
-// dnames_non_fqdn[i]->size);
-// hex_print(test_domains_non_fqdn[i].wire,
-// test_domains_non_fqdn[i].size);
-// diag("%s and %s\n",
-// knot_dname_to_str(dnames_non_fqdn[i]),
-// test_domains_non_fqdn[i]);
- errors++;
- }
- }
-
- return errors;
-}
-
-/* \note not to be run separately */
-static int test_dname_size(knot_dname_t **dnames_fqdn,
- knot_dname_t **dnames_non_fqdn)
-{
- assert(dnames_fqdn);
- assert(dnames_non_fqdn);
-
- int errors = 0;
-
- for (int i = 0; i < TEST_DOMAINS_OK; i++) {
- uint8_t tmp_size;
- if ((tmp_size = knot_dname_size(dnames_fqdn[i])) !=
- test_domains_ok[i].size) {
- diag("Got bad size value from structure: "
- "%u, should be: %u",
- tmp_size, test_domains_ok[i].size);
- errors++;
- }
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
- uint8_t tmp_size;
- if ((tmp_size = knot_dname_size(dnames_non_fqdn[i])) !=
- test_domains_non_fqdn[i].size) {
- diag("Got bad size value from structure: "
- "%u, should be: %u",
- tmp_size, test_domains_non_fqdn[i].size);
- errors++;
- }
- }
-
- return errors;
-}
-
-/* \note not to be run separately */
-static int test_dname_node(knot_dname_t **dnames_fqdn,
- knot_dname_t **dnames_non_fqdn)
-{
- assert(dnames_fqdn);
- assert(dnames_non_fqdn);
-
- int errors = 0;
-
- for (int i = 0; i < TEST_DOMAINS_OK; i++) {
- const knot_node_t *tmp_node;
- if ((tmp_node = knot_dname_node(dnames_fqdn[i])) !=
- NODE_ADDRESS) {
- diag("Got bad node value from structure: "
- "%p, should be: %p",
- tmp_node, NODE_ADDRESS);
- errors++;
- }
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
- const knot_node_t *tmp_node;
- if ((tmp_node = knot_dname_node(dnames_non_fqdn[i])) !=
- NODE_ADDRESS) {
- diag("Got bad node value from structure: "
- "%s, should be: %s",
- tmp_node, NODE_ADDRESS);
- errors++;
- }
- }
-
- return errors;
-}
-
-static int test_dname_getters(uint type)
-{
- int errors = 0;
-
- knot_dname_t *dnames_fqdn[TEST_DOMAINS_OK];
- knot_dname_t *dnames_non_fqdn[TEST_DOMAINS_NON_FQDN];
-
- for (int i = 0; i < TEST_DOMAINS_OK; i++) {
- dnames_fqdn[i] = knot_dname_new_from_wire(
- (uint8_t *)test_domains_ok[i].wire,
- test_domains_ok[i].size, NODE_ADDRESS);
- assert(dnames_fqdn[i] != NULL);
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
-// note("Creating dname: %s size: %d\n",
-// test_domains_non_fqdn[i].wire,
-// test_domains_non_fqdn[i].size);
- dnames_non_fqdn[i] = knot_dname_new_from_str(
- test_domains_non_fqdn[i].str,
- strlen(test_domains_non_fqdn[i].str),
- NODE_ADDRESS);
- assert(dnames_non_fqdn[i] != NULL);
- }
-
- switch (type) {
- case 0: {
- errors += test_dname_name(dnames_fqdn, dnames_non_fqdn);
- break;
- }
-
- case 1: {
- errors += test_dname_size(dnames_fqdn, dnames_non_fqdn);
- break;
- }
-
- case 2: {
- errors += test_dname_node(dnames_fqdn, dnames_non_fqdn);
- break;
- }
- } /* switch */
-
- for (int i = 0; i < TEST_DOMAINS_OK; i++) {
- knot_dname_free(&dnames_fqdn[i]);
- }
-
- for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
- knot_dname_free(&dnames_non_fqdn[i]);
- }
-
- return (errors == 0);
-}
-
-static const int KNOT_DNAME_TEST_COUNT = 16;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_dname_tests_count(int argc, char *argv[])
-{
- return KNOT_DNAME_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_dname_tests_run(int argc, char *argv[])
-{
- int res = 0,
- res_str = 0,
- res_wire = 0,
- res_str_non_fqdn = 0,
- res_final = 1;
-
- res = test_dname_create();
- ok(res, "dname: create empty");
- res_final *= res;
-
- skip(!res, 12);
-
- todo();
-
- ok((res = test_dname_delete()), "dname: delete");
- //res_final *= res;
-
- endtodo;
-
- ok((res_str = test_dname_create_from_str()), "dname: create from str");
- ok((res_wire = test_dname_create_from_wire()),
- "dname: create from wire");
- ok((res_str_non_fqdn = test_dname_create_from_str_non_fqdn()),
- "dname: create from str non fqdn");
- res_final *= res_str;
- res_final *= res_wire;
- res_final *= res_str_non_fqdn;
-
- res = test_dname_getters(0);
- ok(res, "dname: name");
-
- res = test_dname_getters(1);
- ok(res, "dname: size");
-
- res = test_dname_getters(2);
- ok(res, "dname: node");
-
- skip(!res_str || !res_wire || !res_str_non_fqdn, 2);
-
- ok((res = test_dname_to_str()), "dname: convert to str");
- res_final *= res;
-
- lives_ok(test_faulty_data(); , "dname: faulty data test");
-
- endskip; /* !res_str || !res_wire */
-
- ok((res = test_dname_compare()), "dname: compare");
- res_final *= res;
-
- ok((res = test_dname_cat()), "dname: cat");
- res_final *= res;
-
- ok((res = test_dname_is_fqdn()), "dname: fqdn");
- res_final *= res;
-
- ok((res = test_dname_left_chop()), "dname: left chop");
- res_final *= res;
-
- ok((res = test_dname_is_subdomain()), "dname: is subdomain");
- res_final *= res;
-
- ok((res = test_dname_deep_copy()), "dname: deep copy");
- res_final *= res;
-
- endskip; /* create failed */
-
- return res_final;
-}
diff --git a/src/tests/libknot/libknot/edns_tests.c b/src/tests/libknot/libknot/edns_tests.c
deleted file mode 100644
index 4d1a37a..0000000
--- a/src/tests/libknot/libknot/edns_tests.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "tests/libknot/libknot/edns_tests.h"
-#include "libknot/common.h"
-#include "libknot/edns.h"
-
-static int knot_edns_tests_count(int argc, char *argv[]);
-static int knot_edns_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api edns_tests_api = {
- "DNS library - EDNS", //! Unit name
- &knot_edns_tests_count, //! Count scheduled tests
- &knot_edns_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-enum { TEST_EDNS = 1, OPTION_COUNT = 3 };
-
-struct test_edns_options {
- uint16_t code;
- uint16_t length;
- uint8_t *data;
-};
-
-struct test_edns {
- struct test_edns_options *options;
- uint16_t payload;
- uint8_t ext_rcode;
- uint8_t version;
- uint16_t flags;
- short option_count;
- short options_max;
- short size;
-};
-
-typedef struct test_edns test_edns_t;
-
-struct test_edns_options test_options_data[OPTION_COUNT] = {
- {5, 7, (uint8_t *)"123456"},
- {4, 3, (uint8_t *)"12"},
- {1, 5, (uint8_t *)"13333"}
-};
-
-test_edns_t test_edns_data[TEST_EDNS] = {
-{ NULL, 4096, 2, 0, 0, 0, 10, 11}
-};
-
-enum edns_mask {
- KNOT_EDNS_DO_MASK = (uint16_t)0x8000
-};
-
-/* Creates actual knot_opt_rr_t variable from test_edns_t variable */
-static knot_opt_rr_t *opt_rr_from_test_edns(test_edns_t *test_edns)
-{
- knot_opt_rr_t *ret = knot_edns_new();
-
- CHECK_ALLOC_LOG(ret, NULL);
-
- ret->flags = test_edns->flags;
- ret->ext_rcode = test_edns->ext_rcode;
- ret->payload = test_edns->payload;
- ret->version = test_edns->version;
-
- for (int i = 0; i < test_edns->option_count; i++) {
- if (knot_edns_add_option(ret, test_edns->options[i].code,
- test_edns->options[i].length,
- test_edns->options[i].data) != 0) {
- knot_edns_free(&ret);
- return NULL;
- }
- }
-
- return ret;
-}
-
-/* simple wire compare - 0 if same, 1 otherwise */
-static int edns_compare_wires(uint8_t *wire1,
- uint8_t *wire2,
- uint16_t length)
-{
- for (uint i = 0; i < length; i++) {
- if (wire1[i] != wire2[i]) {
- return 1;
- }
- }
-
- return 0;
-}
-
-static int check_edns(const knot_opt_rr_t *edns,
- const test_edns_t *test_edns)
-{
- if (edns->option_count != test_edns->option_count) {
- diag("Option count is wrong");
- return -1;
- }
-
- for (int i = 0; i < edns->option_count; i++) {
- /* check options */
- if (edns->options[i].code != test_edns->options[i].code) {
- diag("Code in options is wrong");
- return -1;
- }
-
- if (edns->options[i].length != test_edns->options[i].length) {
- diag("Length in options is wrong");
- return -1;
- }
-
- if (edns_compare_wires(edns->options[i].data,
- test_edns->options[i].data,
- edns->options[i].length) != 0) {
- diag("Data in options are wrong");
- return -1;
- }
- }
-
- if (edns->version != test_edns->version) {
- diag("Version is wrong");
- return -1;
- }
-
- if (edns->flags != test_edns->flags) {
- diag("Flags are wrong");
- return -1;
- }
-
- if (edns->size != test_edns->size) {
- diag("Size is wrong");
- return -1;
- }
-
- return 0;
-}
-
-static int test_edns_get_payload(const knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- if (knot_edns_get_payload(edns) !=
- test_edns->payload) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_get_ext_rcode(const knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- if (knot_edns_get_ext_rcode(edns) !=
- test_edns->ext_rcode) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_get_flags(const knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- if (knot_edns_get_flags(edns) !=
- test_edns->flags) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_get_version(const knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- if (knot_edns_get_version(edns) !=
- test_edns->version) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_do(const knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- if (knot_edns_do(edns) !=
- (test_edns->flags & KNOT_EDNS_DO_MASK)) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_size(knot_opt_rr_t *edns, test_edns_t *test_edns)
-{
- if (knot_edns_size(edns) !=
- test_edns->size) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_set_payload(knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- knot_edns_set_payload(edns, test_edns->payload);
-
- if (edns->payload !=
- test_edns->payload) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_set_ext_rcode(knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- knot_edns_set_ext_rcode(edns, test_edns->ext_rcode);
- if (edns->ext_rcode !=
- test_edns->ext_rcode) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_set_version(knot_opt_rr_t *edns,
- test_edns_t *test_edns)
-{
- knot_edns_set_version(edns,
- test_edns->version);
-
- if (edns->version !=
- test_edns->version) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_set_do(knot_opt_rr_t *edns)
-{
- knot_edns_set_do(edns);
-
- if (!knot_edns_do(edns)) {
- return 0;
- } else {
- return 1;
- }
-}
-
-static int test_edns_getters(uint type)
-{
- int errors = 0;
- for (int i = 0; i < TEST_EDNS; i++) {
- knot_opt_rr_t *edns =
- opt_rr_from_test_edns(&(test_edns_data[i]));
- if (edns == NULL) {
- ERR_ALLOC_FAILED;
- return -1;
- }
-
- switch(type) {
- case 0:
- if (test_edns_get_payload(edns,
- &test_edns_data[i]) != 1) {
- diag("Got wrong payload!");
- errors++;
- }
- break;
- case 1:
- if (test_edns_get_ext_rcode(edns,
- &test_edns_data[i]) != 1) {
- diag("Got wrong extended RCODE!");
- errors++;
- }
- break;
- case 2:
- if (test_edns_get_flags(edns,
- &test_edns_data[i]) != 1) {
- diag("Got wrong flags!");
-
- errors++;
- }
- break;
- case 3:
- if (test_edns_get_version(edns,
- &test_edns_data[i]) != 1) {
- diag("Got wrong version!");
- errors++;
- }
- break;
- case 4:
- if (test_edns_do(edns,
- &test_edns_data[i]) != 1) {
- diag("Got wrong DO bit!");
- errors++;
- }
- break;
- case 5:
- if (test_edns_size(edns,
- &test_edns_data[i]) != 1) {
- diag("Got wrong size!");
- errors++;
- }
- break;
- default:
- diag("Unknown option");
- errors++;
- } /* switch */
-
- knot_edns_free(&edns);
- }
-
- return (errors == 0);
-}
-
-static int test_edns_setters(uint type)
-{
- int errors = 0;
- for (int i = 0; i < TEST_EDNS; i++) {
- knot_opt_rr_t *edns =
- opt_rr_from_test_edns(&(test_edns_data[i]));
- if (edns == NULL) {
- ERR_ALLOC_FAILED;
- return -1;
- }
-
- switch(type) {
- case 0:
- if (test_edns_set_payload(edns,
- &test_edns_data[i]) != 1) {
- diag("Set wrong payload!");
- errors++;
- }
- break;
- case 1:
- if (test_edns_set_ext_rcode(edns,
- &test_edns_data[i]) != 1) {
- diag("Set wrong ext_rcode");
- errors++;
- }
- break;
- case 2:
- if (test_edns_set_version(edns,
- &test_edns_data[i]) != 1) {
- diag("Set wrong version!");
- errors++;
- }
- break;
- case 3:
- if (test_edns_set_do(edns) != 1) {
- diag("Set wrong DO bit!");
- errors++;
- }
- break;
- default:
- diag("Unknown option");
- errors++;
- } /* switch */
-
- knot_edns_free(&edns);
- }
-
- return (errors == 0);
-}
-
-static int test_edns_wire()
-{
- /*
- * Tests to_wire and from_wire in one test.
- */
- for (int i = 0; i < TEST_EDNS; i++) {
- /* Creates instance from test_edns_t. */
- knot_opt_rr_t *edns =
- opt_rr_from_test_edns(&(test_edns_data[i]));
- if (edns == NULL) {
- ERR_ALLOC_FAILED;
- return -1;
- }
-
- uint8_t *wire = NULL;
- wire = malloc(sizeof(uint8_t) * edns->size);
- CHECK_ALLOC_LOG(wire, 0);
-
- /* Converts EDNS to wire. */
- short wire_size = knot_edns_to_wire(edns, wire, 100);
-
- if (wire_size == -1) {
- diag("Could not create EDNS wire");
- return 0;
- }
-
- knot_opt_rr_t *edns_from_wire = knot_edns_new();
- if (edns == NULL) {
- return 0;
- }
-
- /* TODO use some constant */
- /* Creates new EDNS from wire */
- if (knot_edns_new_from_wire(edns_from_wire,
- wire,
- 100) <= 0) {
- diag("Could not create from wire");
- return 0;
- }
-
- /* Checks whether EDNS created from wire is the same */
- if (check_edns(edns_from_wire,
- &(test_edns_data[i])) != 0) {
- diag("EDNS created from wire is different from the "
- "original one");
- }
-
- free(wire);
- knot_edns_free(&edns_from_wire);
- knot_edns_free(&edns);
- }
- return 1;
-}
-
-static int test_edns_add_option()
-{
- /*
- * Create empty EDNS and add options one by one, testing their presence.
- */
- for (int i = 0; i < TEST_EDNS; i++) {
- knot_opt_rr_t *edns = knot_edns_new();
- assert(edns->option_count == 0);
-
- if (edns == NULL) {
- ERR_ALLOC_FAILED;
- return 0;
- }
-
- for (int j = 0; j < test_edns_data[i].option_count; j++) {
- if (knot_edns_add_option(edns,
- test_edns_data[i].options[j].code,
- test_edns_data[i].options[j].length,
- test_edns_data[i].options[j].
- data) != 0) {
- diag("Could not add option");
- return 0;
- }
-
- if (edns->options[j].code !=
- test_edns_data[i].options[j].code) {
- diag("Option code wrongly added!");
- return 0;
- }
-
- if (edns->options[j].length !=
- test_edns_data[i].options[j].length) {
- diag("Option length wrongly added!");
- return 0;
- }
-
- if (edns_compare_wires(edns->options[j].data,
- test_edns_data[i].
- options[j].data,
- edns->options[j].length) != 0) {
- diag("Option wire wrongly added!");
- return 0;
- }
- }
- knot_edns_free(&edns);
- }
- return 1;
-}
-
-static int test_edns_has_option()
-{
- /*
- * Create empty EDNS and add options one by one, testing their presence
- */
- for (int i = 0; i < TEST_EDNS; i++) {
- knot_opt_rr_t *edns = knot_edns_new();
-
- if (edns == NULL) {
- ERR_ALLOC_FAILED;
- return 0;
- }
-
- assert(edns->option_count == 0);
-
- for (int j = 0; j < test_edns_data[i].option_count; j++) {
- if (knot_edns_add_option(edns,
- test_edns_data[i].options[j].code,
- test_edns_data[i].options[j].length,
- test_edns_data[i].options[j].
- data) != 0) {
- diag("Could not add option");
- return 0;
- }
-
- if (knot_edns_has_option(edns,
- test_edns_data[i].options[j].code) != 1) {
- diag("Option not found!");
- return 0;
- }
- }
- knot_edns_free(&edns);
- }
- return 1;
-}
-
-static const int KNOT_EDNS_TESTS_COUNT = 12;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_edns_tests_count(int argc, char *argv[])
-{
- return KNOT_EDNS_TESTS_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_edns_tests_run(int argc, char *argv[])
-{
- int res = 0;
- int res_final = 1;
-
- res = test_edns_getters(0);
- ok(res, "ends: get payload");
- res_final *= res;
-
- res = test_edns_getters(1);
- ok(res, "ends: get extenden RCODE");
- res_final *= res;
-
- res = test_edns_getters(2);
- ok(res, "ends: get flags");
- res_final *= res;
-
- res = test_edns_getters(3);
- ok(res, "ends: get version");
- res_final *= res;
-
- res = test_edns_getters(4);
- ok(res, "ends: do");
- res_final *= res;
-
- res = test_edns_getters(5);
- ok(res, "ends: size");
- res_final *= res;
-
- res = test_edns_setters(0);
- ok(res, "ends: set payload");
- res_final *= res;
-
- res = test_edns_setters(1);
- ok(res, "ends: set extended RCODE");
- res_final *= res;
-
- res = test_edns_setters(2);
- ok(res, "ends: set version");
- res_final *= res;
-
- res = test_edns_setters(3);
- ok(res, "ends: set DO");
- res_final *= res;
-
- res = test_edns_add_option();
- ok(res, "ends: add option");
- res_final *= res;
-
- res = test_edns_has_option();
- ok(res, "ends: has option");
- res_final *= res;
-
- res = test_edns_wire();
- ok(res, "ends: to_wire and from_wire");
- res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/libknot/node_tests.c b/src/tests/libknot/libknot/node_tests.c
deleted file mode 100644
index b252982..0000000
--- a/src/tests/libknot/libknot/node_tests.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/* Copyright (C) 2011 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 "tests/libknot/libknot/node_tests.h"
-#include "libknot/dname.h"
-#include "libknot/zone/node.h"
-#include "libknot/util/descriptor.h"
-
-static int knot_node_tests_count(int argc, char *argv[]);
-static int knot_node_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api node_tests_api = {
- "DNS library - node", //! Unit name
- &knot_node_tests_count, //! Count scheduled tests
- &knot_node_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-// C will not accept const int in other const definition
-enum { TEST_NODES = 2, RRSETS = 5};
-
-struct test_node {
- knot_dname_t owner;
- knot_node_t *parent;
- uint size;
-};
-
-static knot_dname_t test_dnames[TEST_NODES] = {
- {{}, (uint8_t *)"\3www\7example\3com", NULL, NULL, 0, 17},
- {{}, (uint8_t *)"\3www\7example\3com", NULL, NULL, 0, 17}
-};
-
-static struct test_node test_nodes[TEST_NODES] = {
- {{{}, (uint8_t *)"\3com", NULL, NULL, 0, 4}, (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\3www\7example\3com", NULL, NULL, 0, 17}, (knot_node_t *)NULL}
-};
-
-static knot_rrset_t rrsets[RRSETS] = {
- {&test_dnames[0], 1, 1, 3600, NULL, NULL},
- {&test_dnames[1], 2, 1, 3600, NULL, NULL},
- {&test_dnames[1], 7, 1, 3600, NULL, NULL},
- {&test_dnames[1], 3, 1, 3600, NULL, NULL},
- {&test_dnames[1], 9, 1, 3600, NULL, NULL}
-};
-
-static int test_node_create()
-{
- /* Tests creation of node by comparing with test_node struct */
- knot_node_t *tmp;
- int errors = 0;
- for (int i = 0; i < TEST_NODES && !errors; i++) {
- tmp = knot_node_new(&test_nodes[i].owner,
- test_nodes[i].parent, 0);
- if (tmp == NULL ||
- tmp->owner != &test_nodes[i].owner ||
- tmp->parent != test_nodes[i].parent ||
- tmp->rrset_tree == NULL) {
- errors++;
- diag("Failed to create node structure");
- }
- knot_node_free(&tmp);
- }
- return (errors == 0);
-}
-
-static int test_node_add_rrset()
-{
- knot_node_t *tmp;
- knot_rrset_t *rrset;
- int errors = 0;
- for (int i = 0; i < TEST_NODES && !errors; i++) {
- /* create node from test_node structure */
- tmp = knot_node_new(&test_nodes[i].owner,
- test_nodes[i].parent, 0);
- rrset = &rrsets[i];
- if (knot_node_add_rrset(tmp, rrset, 0) < 0) {
- errors++;
- diag("Failed to insert rrset into node");
- }
-
- /* check if rrset is really there */
-
- const knot_rrset_t *rrset_from_node = NULL;
- if ((rrset_from_node =
- knot_node_rrset(tmp, rrset->type)) == NULL) {
- errors++;
- diag("Inserted rrset could not be found");
- continue;
- }
-
- /* compare rrset from node with original rrset */
-
- const knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
-
- int cmp = 0;
-
- if ((rrset_from_node->rdata == NULL) &&
- (rrset->rdata == NULL)) {
- cmp = 0;
- } else if ((rrset_from_node->rdata != NULL) &&
- (rrset->rdata != NULL)) {
- cmp = knot_rdata_compare(rrset_from_node->rdata,
- rrset->rdata,
- desc->wireformat);
- } else { /* one is not NULL and other is -> error */
- cmp = 1;
- }
-
- if (!((rrset_from_node->type == rrset->type) &&
- (rrset_from_node->rclass == rrset->rclass) &&
- (rrset_from_node->ttl == rrset->ttl) &&
- (rrset_from_node->rrsigs == rrset->rrsigs) &&
- (cmp == 0))) {
- errors++;
- diag("Values in found rrset are wrong");
- }
-
- knot_node_free(&tmp);
- }
-
- return (errors == 0);
-}
-
-static int test_node_get_rrset()
-{
- knot_node_t *tmp;
- knot_rrset_t *rrset;
- int errors = 0;
-
- knot_node_t *nodes[TEST_NODES];
-
- for (int i = 0; i < TEST_NODES && !errors; i++) {
- tmp = knot_node_new(&test_nodes[i].owner,
- test_nodes[i].parent, 0);
- nodes[i] = tmp;
- for (int j = 0; j < RRSETS; j++) {
- knot_node_add_rrset(tmp, &rrsets[j], 0);
- }
- }
-
- for (int i = 0; i < TEST_NODES && !errors; i++) {
- for (int j = 0; j < RRSETS; j++) {
- rrset = &rrsets[j];
- if (knot_node_rrset(nodes[i], rrset->type)
- != rrset) {
- errors++;
- diag("Failed to get proper rrset from node");
- }
- }
- knot_node_free(&nodes[i]);
- }
-
- return (errors == 0);
-}
-
-static int test_node_get_parent()
-{
- knot_node_t *tmp;
- knot_rrset_t *rrset;
- int errors = 0;
-
- knot_node_t *nodes[TEST_NODES];
-
- for (int i = 0; i < TEST_NODES && !errors; i++) {
- tmp = knot_node_new(&test_nodes[i].owner,
- test_nodes[i].parent, 0);
- nodes[i] = tmp;
- rrset = &rrsets[i];
- knot_node_add_rrset(tmp, rrset, 0);
- }
-
- for (int i = 0; i < TEST_NODES && !errors; i++) {
- rrset = &rrsets[i];
- if (knot_node_parent(nodes[i]) != test_nodes[i].parent) {
- errors++;
- diag("Failed to get proper parent from node");
- }
- knot_node_free(&nodes[i]);
- }
- return (errors == 0);
-}
-
-static int test_node_sorting()
-{
- knot_node_t *tmp;
- knot_rrset_t *rrset;
- int errors = 0;
-
- tmp = knot_node_new(&test_nodes[0].owner, test_nodes[0].parent, 0);
-
- /* Will add rrsets to node. */
-
- for (int i = 0; i < RRSETS && !errors; i++) {
- rrset = &rrsets[i];
- knot_node_add_rrset(tmp, rrset, 0);
- }
-
-// const skip_node_t *node = skip_first(tmp->rrsets);
-
-// int last = *((uint16_t *)node->key);
-
-// /* TODO there is now an API function knot_node_rrsets ... */
-
-// /* Iterates through skip list and checks, whether it is sorted. */
-
-// while ((node = skip_next(node)) != NULL) {
-// if (last > *((uint16_t *)node->key)) {
-// errors++;
-// diag("RRset sorting error");
-// }
-// last = *((uint16_t *)node->key);
-// }
-
- knot_node_free(&tmp);
- return (errors == 0);
-}
-
-static int test_node_delete()
-{
- int errors = 0;
-
- knot_node_t *tmp_node;
-
- for (int i = 0; i < TEST_NODES; i++) {
- tmp_node = knot_node_new(&test_nodes[i].owner,
- test_nodes[i].parent, 0);
-
- knot_node_free(&tmp_node);
-
- errors += (tmp_node != NULL);
- }
-
- return (errors == 0);
-}
-
-static int test_node_set_parent()
-{
- knot_node_t *tmp_parent = knot_node_new(NULL, NULL, 0);
- int errors = 0;
-
- knot_node_t *tmp_node;
-
- for (int i = 0; i < TEST_NODES; i++) {
- tmp_node = knot_node_new(&test_nodes[i].owner,
- test_nodes[i].parent, 0);
-
- knot_node_set_parent(tmp_node, tmp_parent);
-
- if (tmp_node->parent != tmp_node->parent) {
- diag("Parent node is wrongly set.");
- errors++;
- }
- knot_node_free(&tmp_node);
- }
- knot_node_free(&tmp_parent);
- return (errors == 0);
-}
-
-static int test_node_free_rrsets()
-{
- int errors = 0;
-
- knot_node_t *tmp_node;
-
- for (int i = 0; i < TEST_NODES; i++) {
- tmp_node = knot_node_new(&test_nodes[i].owner,
- test_nodes[i].parent, 0);
-
- knot_node_free_rrsets(tmp_node, 0);
-
-// errors += (tmp_node->rrsets != NULL);
-
- knot_node_free(&tmp_node);
- }
- return (errors == 0);
-}
-
-static const int KNOT_NODE_TEST_COUNT = 8;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_node_tests_count(int argc, char *argv[])
-{
- return KNOT_NODE_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_node_tests_run(int argc, char *argv[])
-{
- int res = 0,
- res_final = 1;
-
- res = test_node_create();
- ok(res, "node: create");
- res_final *= res;
-
- skip(!res, 6)
-
- ok((res = test_node_add_rrset()), "node: add");
- res_final *= res;
-
- ok((res = test_node_get_rrset()), "node: get");
- res_final *= res;
-
- ok((res = test_node_get_parent()), "node: get parent");
- res_final *= res;
-
- ok((res = test_node_set_parent()), "node: set parent");
- res_final *= res;
-
- ok((res = test_node_sorting()), "node: sort");
- res_final *= res;
-
- ok((res = test_node_free_rrsets()), "node: free rrsets");
- res_final *= res;
-
- endskip;
-
- ok((res = test_node_delete()), "node: delete");
- //res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/libknot/nsec3_tests.c b/src/tests/libknot/libknot/nsec3_tests.c
deleted file mode 100644
index 5864b05..0000000
--- a/src/tests/libknot/libknot/nsec3_tests.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-/* blame: jan.kadlec@nic.cz */
-
-#include <assert.h>
-
-#include "libknot/common.h"
-#include "libknot/nsec3.h"
-#include "libknot/util/utils.h"
-#include "common/base32hex.h"
-#include "nsec3_tests.h"
-
-#ifdef TEST_WITH_LDNS
-#include "ldns/ldns.h"
-#endif
-
-static int knot_nsec3_tests_count(int argc, char *argv[]);
-static int knot_nsec3_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api nsec3_tests_api = {
- "NSEC3", //! Unit name
- &knot_nsec3_tests_count, //! Count scheduled tests
- &knot_nsec3_tests_run //! Run scheduled tests
-};
-
-extern int compare_wires_simple(uint8_t *w1, uint8_t *w2, uint count);
-
-static int test_nsec3_params_from_wire()
-{
- /* Create sample NSEC3PARAM rdata */
- knot_rdata_item_t items[4];
- knot_rdata_t *rdata = knot_rdata_new();
- rdata->items = items;
- rdata->count = 4;
- knot_rdata_item_set_raw_data(rdata, 0, (uint16_t *)"\x1\x0\x1");
- knot_rdata_item_set_raw_data(rdata, 1, (uint16_t *)"\x1\x0\x0");
- knot_rdata_item_set_raw_data(rdata, 2, (uint16_t *)"\x2\x0\x0\x64");
- knot_rdata_item_set_raw_data(rdata, 3,
- (uint16_t *)"\xF\x0\xE\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF");
-
- knot_rrset_t *rrset =
- knot_rrset_new(knot_dname_new_from_str("cz.",
- strlen("cz."), NULL),
- KNOT_RRTYPE_NSEC3PARAM,
- KNOT_CLASS_IN,
- 3600);
- assert(rrset);
- int ret = knot_rrset_add_rdata(rrset, rdata);
- assert(ret == KNOT_EOK);
-
- knot_nsec3_params_t nsec3_test_params;
-
- int errors = 0;
- int lived = 0;
- lives_ok({
- /* Create special variable for this block. */
- if (knot_nsec3_params_from_wire(NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
-
- lived = 0;
- if (knot_nsec3_params_from_wire(&nsec3_test_params, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
-
- lived = 0;
- if (knot_nsec3_params_from_wire(NULL, rrset) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
-
- }, "nsec3 params from wire NULL tests");
- errors += lived != 1;
-
- if (knot_nsec3_params_from_wire(&nsec3_test_params,
- rrset) != KNOT_EOK) {
- diag("Could not convert nsec3 params to wire!");
- return 0;
- }
-
- if (nsec3_test_params.algorithm != 1) {
- diag("Algorithm error");
- errors++;
- }
-
- if (nsec3_test_params.flags != 0) {
- diag("Flags error %d", nsec3_test_params.flags);
- errors++;
- }
-
- if (nsec3_test_params.iterations != 100) {
- diag("Iterations error %d", nsec3_test_params.iterations);
- errors++;
- }
- printf("salt length: %d\n", nsec3_test_params.salt_length);
-
- if (nsec3_test_params.salt_length != 14) {
- diag("Salt length error %d", nsec3_test_params.salt_length);
- return 0;
- }
-
- if (compare_wires_simple((uint8_t *)nsec3_test_params.salt,
- (uint8_t *)"\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF\xF",
- 14) != 0) {
- diag("Salt wire error");
- errors++;
- }
-
- knot_rrset_free(&rrset);
- return (errors == 0);
-}
-
-static int test_nsec3_sha1()
-{
- int errors = 0;
- int lived = 0;
-
- knot_nsec3_params_t nsec3_test_params;
-
- lives_ok({
- if (knot_nsec3_sha1(NULL, NULL, 1, NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_nsec3_sha1(&nsec3_test_params,
- NULL, 1, NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- uint8_t data[20];
- lived = 1;
- lived = 0;
- if (knot_nsec3_sha1(&nsec3_test_params,
- data, 20, NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- uint8_t *digest = NULL;
- lived = 1;
- lived = 0;
- if (knot_nsec3_sha1(&nsec3_test_params,
- data, 20, &digest, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
-// size_t size = 0;
-// lived = 1;
-// lived = 0;
-// if (knot_nsec3_sha1(&nsec3_test_params,
-// data, 20, &digest, &size) !=
-// KNOT_EINVAL) {
-// errors++;
-// }
- lived = 1;
- }, "NSEC3: nsec3 sha1 NULL tests");
- if (errors) {
- diag("Does not return KNOT_EINVAL after "
- "execution with wrong arguments!");
- }
-
- errors += lived != 1;
-
- uint8_t *digest = NULL;
- size_t digest_size = 0;
- if (knot_nsec3_sha1(&nsec3_test_params,
- (uint8_t *)"\2ns\3nic\2cz",
- strlen("\2ns\3nic\2cz"), &digest,
- &digest_size) != KNOT_EOK) {
- diag("Could not hash name!");
- return 0;
- }
-
-#ifdef TEST_WITH_LDNS
- ldns_rdf *name = ldns_dname_new_frm_str("ns.nic.cz.");
- assert(name);
- ldns_rdf *hashed_name = ldns_nsec3_hash_name(name,
- nsec3_test_params.algorithm,
- nsec3_test_params.iterations,
- nsec3_test_params.salt_length,
- nsec3_test_params.salt);
- assert(hashed_name);
-// knot_dname_t *dname_from_ldns =
-// knot_dname_new_from_wire(ldns_rdf_data(hashed_name),
-// ldns_rdf_size(hashed_name),
-// NULL);
-
- char *name_b32 = NULL;
- size_t size_b32 = base32hex_encode_alloc((char *)digest, digest_size,
- &name_b32);
-
-// hex_print(name_b32, size_b32);
-// hex_print(ldns_rdf_data(hashed_name), ldns_rdf_size(hashed_name));
- if (ldns_rdf_size(hashed_name) != size_b32) {
- diag("Wrong hashed name length! Should be: %d is: %d",
- ldns_rdf_size(hashed_name), size_b32);
- return 0;
- }
-
- if (compare_wires_simple(ldns_rdf_data(hashed_name),
- (uint8_t *)name_b32, size_b32) != 0) {
- diag("Wrong hashed name wire!");
- errors++;
- }
-#endif
-
-#ifndef TEST_WITH_LDNS
- diag("Warning: without ldns this test is only partial!");
-#endif
- return (errors == 0);
-}
-
-static const int KNOT_NSEC3_TESTS_COUNT = 2;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_nsec3_tests_count(int argc, char *argv[])
-{
- return KNOT_NSEC3_TESTS_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_nsec3_tests_run(int argc, char *argv[])
-{
- ok(test_nsec3_params_from_wire(), "nsec3: params from wire");
- ok(test_nsec3_sha1(), "nsec3: sha1");
- return 1;
-}
diff --git a/src/tests/libknot/libknot/packet_tests.c b/src/tests/libknot/libknot/packet_tests.c
deleted file mode 100644
index 8e6597b..0000000
--- a/src/tests/libknot/libknot/packet_tests.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-/* blame: jan.kadlec@nic.cz */
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "packet_tests.h"
-#include "libknot/packet/packet.h"
-#include "libknot/util/wire.h"
-/* *test_t structures */
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-
-static int packet_tests_count(int argc, char *argv[]);
-static int packet_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api packet_tests_api = {
- "packet", //! Unit name
- &packet_tests_count, //! Count scheduled tests
- &packet_tests_run //! Run scheduled tests
-};
-
-static int test_packet_new()
-{
- int errors = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_NONE);
- if (packet == NULL) {
- diag("Could not create packet using prealloc_node constant!");
- errors++;
- }
- knot_packet_free(&packet);
-
- packet = knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
- if (packet == NULL) {
- diag("Could not create packet using prealloc_query constant!");
- errors++;
- }
- knot_packet_free(&packet);
-
- packet = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- if (packet == NULL) {
- diag("Could not create packet using prealloc_resp constant!");
- errors++;
- }
- knot_packet_free(&packet);
-
- /*!< \todo Should it create packet using any size? */
-
- return (errors == 0);
-}
-
-static int test_packet_parse_from_wire()
-{
- int errors = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
-
- int tmp = 0;
- lives_ok({
- if (knot_packet_parse_from_wire(NULL, NULL, 0, 0) !=
- KNOT_EINVAL) {
- diag("Trying to parse NULL packet with NULL wire "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- tmp = 1;
- tmp = 0;
- if (knot_packet_parse_from_wire(packet, NULL, 0, 0) !=
- KNOT_EINVAL) {
- diag("Trying to parse with NULL wire "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- tmp = 1;
- tmp = 0;
- if (knot_packet_parse_from_wire(packet, (uint8_t *)0xbeef,
- 0, 0) !=
- KNOT_EFEWDATA) {
- diag("Trying to parse 0 lengt"
- "did not return KNOT_EOK!");
- errors++;
- }
- tmp = 1;
- }, "packet: parse from wire NULL tests.");
- errors += tmp != 1;
-
- knot_packet_free(&packet);
-
- return (errors == 0);
-}
-
-static int test_packet_parse_next_rr_answer()
-{
- int errors = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
-
- int tmp = 0;
- lives_ok({
- int ret = 0;
- if (knot_packet_parse_next_rr_answer(NULL, NULL) !=
- KNOT_EINVAL) {
- diag("Trying to parse next RR answer with "
- "NULL packet with and NULL RRSet "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- tmp = 1;
- tmp = 0;
- if ((ret = knot_packet_parse_next_rr_answer(packet,
- NULL)) !=
- KNOT_EINVAL) {
- diag("Trying to parse next RR with NULL RRSet pointer "
- "did not return KNOT_EINVAL! Got %d.",
- ret);
- errors++;
- }
- tmp = 1;
-// knot_rrset_t *rrset = (knot_rrset_t *)0xaaaa;
-// tmp = 0;
-// if (knot_packet_parse_next_rr_answer(packet,
-// &rrset) !=
-// KNOT_EINVAL) {
-// diag("Trying to parse next RR answer with rrset pointer"
-// " not pointing to NULL did not "
-// "return KNOT_EINVAL!");
-// errors++;
-// }
-// tmp = 1;
- }, "packet: parse next rr answer NULL tests.");
- errors += tmp != 1;
-
- knot_packet_free(&packet);
-
- return (errors == 0);
-}
-
-static int test_packet_parse_rest()
-{
- int res = 0;
- lives_ok({res = knot_packet_parse_rest(NULL);},
- "packet: parse rest NULL test");
-
- if (res != KNOT_EINVAL) {
- diag("parse rest NULL did not return KNOT_EINVAL.\n");
- return 1;
- }
-
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_NONE);
- assert(packet);
-
- lives_ok({res = knot_packet_parse_rest(packet);},
- "packet: parser rest empty packet");
-
- knot_packet_free(&packet);
-
- return 1;
-}
-
-
-static int test_packet_set_max_size()
-{
- int errors = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_NONE);
- assert(packet);
-
- int lived = 0;
-
- lives_ok({
- lived = 0;
- if (knot_packet_set_max_size(NULL, 1) != KNOT_EINVAL) {
- diag("Calling packet_set_max() with NULL packet "
- "did not return KNOT_EINVAL");
- errors++;
- }
- lived = 1;
- }, "packet: set max size NULL test");
-
- errors += lived != 1;
-
- if (knot_packet_set_max_size(packet, 0) != KNOT_EINVAL) {
- diag("Calling packet_set_max() with size eqeal to 0 did not "
- "return KNOT_EINVAL");
- errors++;
- }
-
- if (knot_packet_set_max_size(packet, 10) != KNOT_EOK) {
- diag("Calling packet_set_max() with valid arguments did not "
- "return KNOT_EOK");
- errors++;
- }
-
- knot_packet_free(&packet);
-
- return (errors == 0);
-}
-
-static int test_packet_add_tmp_rrset()
-{
- int errors = 0;
- int lived = 0;
-
- /* knot_packet_add_tmp_rrset only works with pointers. */
- knot_rrset_t *rrset = (knot_rrset_t *)0xabcdef;
-
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
-
- lives_ok({
- if (knot_packet_add_tmp_rrset(NULL, rrset) !=
- KNOT_EINVAL) {
- diag("Trying to add to NULL packet did not return "
- "KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- if (knot_packet_add_tmp_rrset(packet, NULL) !=
- KNOT_EINVAL) {
- diag("Trying to add NULL rrset did not return "
- "KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- if (knot_packet_add_tmp_rrset(NULL, NULL) !=
- KNOT_EINVAL) {
- diag("Trying to add NULL rrset to NULL packet "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "packet: add tmp rrset NULL test");
- errors += lived != 1;
-
- if (knot_packet_add_tmp_rrset(packet, rrset) != KNOT_EOK) {
- diag("Could not add valid RRSet to packet!");
- errors++;
- }
-
- /* Not freeing because RRSet is fake. */
-// knot_packet_free(&packet);
-
- free(packet->wireformat);
- free(packet);
-
- return (errors == 0);
-}
-
-//static int test_packet_contains()
-//{
-// int errors = 0;
-// int lives = 0;
-
-// knot_packet_t *packet =
-// knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
-// assert(packet);
-
-// lives_ok({
-// if (knot_packet_contains(packet, NULL,
-// KNOT_RRSET_COMPARE_PTR) !=
-// KNOT_EINVAL{
-// diag();
-// }
-// }, "packet: contains NULL tests);
-
-// knot_packet_contains()
-
-//}
-
-static int test_packet_header_to_wire()
-{
- int errors = 0;
- int lived = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
- size_t size;
-
- lives_ok({
- knot_packet_header_to_wire(NULL, NULL, NULL);
- lived = 1;
- lived = 0;
- knot_packet_header_to_wire(&packet->header, NULL, &size);
- lived = 1;
- }, "packet: header to wire NULL tests");
- errors += lived != 1;
-
- knot_packet_free(&packet);
- return (errors == 0);
-}
-
-static int test_packet_question_to_wire()
-{
- int errors = 0 ;
- int lived = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
-
- lives_ok({
- if (knot_packet_question_to_wire(NULL) != KNOT_EINVAL) {
- diag("Calling packet_question_to_wire with "
- "NULL pointer did not result to KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "packet: question to wire NULL tests");
- errors += lived != 1;
-
- packet->size = KNOT_WIRE_HEADER_SIZE + 1;
- if (knot_packet_question_to_wire(packet) != KNOT_ERROR) {
- diag("Calling packet_question_to_wire with oversized packet "
- "did not return KNOT_ERROR!");
- errors++;
- }
-
- knot_packet_free(&packet);
- return (errors == 0);
-}
-
-static int test_packet_edns_to_wire()
-{
- int errors = 0 ;
- int lived = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
-
- lives_ok({
- knot_packet_edns_to_wire(NULL);
- lived = 1;
- }, "packet: question to wire NULL tests");
- errors += lived != 1;
-
- knot_packet_free(&packet);
- return (errors == 0);
-}
-
-static int test_packet_to_wire()
-{
- int errors = 0 ;
- int lived = 0;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
-
- lives_ok({
- if (knot_packet_to_wire(NULL, NULL, NULL) != KNOT_EINVAL) {
- diag("Calling packet_to_wire with "
- "NULL pointers did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- size_t size;
- lived = 0;
- if (knot_packet_to_wire(packet, NULL, &size) !=
- KNOT_EINVAL) {
- diag("Calling packet_to_wire with "
- "NULL wire did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- uint8_t *wire = (uint8_t *)0xabcdef;
- lived = 0;
- if (knot_packet_to_wire(packet, &wire, &size) !=
- KNOT_EINVAL) {
- diag("Calling packet_to_wire with "
- "wire not pointing to NULL did not return"
- " KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "packet: to wire NULL tests");
- errors += lived != 1;
-
- knot_packet_free(&packet);
- return (errors == 0);
-}
-
-static const uint KNOT_PACKET_TEST_COUNT = 21;
-
-static int packet_tests_count(int argc, char *argv[])
-{
- return KNOT_PACKET_TEST_COUNT;
-}
-
-static int packet_tests_run(int argc, char *argv[])
-{
- int res = 0;
- ok(res = test_packet_new(), "packet: new");
- skip(!res, 20);
- ok(test_packet_parse_rest(), "packet: parse rest");
- ok(test_packet_parse_from_wire(), "packet: parse from wire");
- ok(test_packet_parse_next_rr_answer(), "packet: parse next rr answer");
- ok(test_packet_set_max_size(), "packet: set max size");
- ok(test_packet_add_tmp_rrset(), "packet: add tmp rrset");
- ok(test_packet_header_to_wire(), "packet: header to wire");
- ok(test_packet_question_to_wire(), "packet: header to wire");
- ok(test_packet_edns_to_wire(), "packet: header to wire");
- ok(test_packet_to_wire(), "packet: to wire");
-// ok(res = test_packet_contains(), "Packet: contains");
- endskip;
- return 1;
-}
diff --git a/src/tests/libknot/libknot/query_tests.c b/src/tests/libknot/libknot/query_tests.c
deleted file mode 100644
index e056faa..0000000
--- a/src/tests/libknot/libknot/query_tests.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-/* blame: jan.kadlec@nic.cz */
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "packet_tests.h"
-#include "libknot/packet/packet.h"
-#include "libknot/util/wire.h"
-#include "libknot/packet/query.h"
-/* *test_t structures */
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-
-static int query_tests_count(int argc, char *argv[]);
-static int query_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api query_tests_api = {
- "query", //! Unit name
- &query_tests_count, //! Count scheduled tests
- &query_tests_run //! Run scheduled tests
-};
-
-static const uint KNOT_QUERY_TEST_COUNT = 1;
-
-static int query_tests_count(int argc, char *argv[])
-{
- return KNOT_QUERY_TEST_COUNT;
-}
-
-static int test_query_init()
-{
- int errors = 0;
- int lived = 0;
- knot_packet_t *query =
- knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
- assert(query);
- lives_ok({
- if (knot_query_init(NULL) != KNOT_EINVAL) {
- diag("Calling query_init with NULL query did "
- "not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "query: init NULL tests");
- errors += lived != 1;
-
- assert(knot_packet_set_max_size(query, 1024 * 10) == KNOT_EOK);
- if (knot_query_init(query) != KNOT_EOK) {
- diag("Calling query_init with valid query did not return "
- "KNOT_EOK!");
- errors++;
- }
-
- if (!knot_packet_is_query(query)) {
- diag("QR flag was not set!");
- errors++;
- }
-
- return (errors == 0);
-}
-
-static int test_query_set_question()
-{
- int errors = 0;
- int lived = 0;
-
- knot_packet_t *query =
- knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
- assert(query);
- assert(knot_packet_set_max_size(query, 1024 * 10) == KNOT_EOK);
- knot_query_init(query);
-
- knot_rrset_t *rrset =
- knot_rrset_new(knot_dname_new_from_str("a.ns.cz.",
- strlen("a.ns.cz."),
- NULL),
- KNOT_RRTYPE_A, KNOT_CLASS_IN, 3600);
- assert(rrset);
-
- knot_question_t *question = malloc(sizeof(knot_question_t));
- assert(question);
- question->qname = rrset->owner;
- question->qtype = rrset->type;
- question->qclass = rrset->rclass;
-
- lives_ok({
- if (knot_query_set_question(NULL, NULL) != KNOT_EINVAL) {
- diag("Calling query_set_question with NULL");
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_query_set_question(query, NULL) != KNOT_EINVAL) {
- diag("Calling query_set_question with NULL");
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_query_set_question(NULL, question) != KNOT_EINVAL) {
- diag("Calling query_set_question with NULL");
- errors++;
- }
- lived = 1;
- }, "query: set question NULL tests");
- errors += lived != 1;
-
- if (knot_query_set_question(query, question) != KNOT_EOK) {
- diag("Calling query_set_question with valid arguments ");
- errors++;
- }
-
- if (query->question.qname != rrset->owner) {
- diag("Qname was not set right!");
- errors++;
- }
-
- if (query->question.qtype != rrset->type) {
- diag("Qtype was not set right!");
- errors++;
- }
-
- if (query->question.qclass != rrset->rclass) {
- diag("Qclass was not set right!");
- errors++;
- }
-
- if (query->header.qdcount != 1) {
- diag("Qdcount was not set right!");
- errors++;
- }
-
- knot_packet_free(&query);
- knot_rrset_deep_free(&rrset, 1, 0, 0);
-
- return (errors == 0);
-}
-
-static int query_tests_run(int argc, char *argv[])
-{
- ok(test_query_init(), "query: init");
- ok(test_query_set_question(), "query: set question");
- return 1;
-}
diff --git a/src/tests/libknot/libknot/query_tests.h b/src/tests/libknot/libknot/query_tests.h
deleted file mode 100644
index 037ecab..0000000
--- a/src/tests/libknot/libknot/query_tests.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_QUERY_TESTS_H_
-#define _KNOTD_QUERY_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api query_tests_api;
-
-#endif /* _KNOTD_QUERY_TESTS_H_ */
diff --git a/src/tests/libknot/libknot/rdata_tests.c b/src/tests/libknot/libknot/rdata_tests.c
deleted file mode 100644
index 663124a..0000000
--- a/src/tests/libknot/libknot/rdata_tests.c
+++ /dev/null
@@ -1,953 +0,0 @@
-/* Copyright (C) 2011 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 <stdlib.h>
-#include <assert.h>
-
-#include "tests/libknot/libknot/rdata_tests.h"
-#include "libknot/common.h"
-#include "libknot/rdata.h"
-#include "libknot/dname.h"
-#include "libknot/util/descriptor.h"
-#include "libknot/util/utils.h"
-
-enum { TEST_DOMAINS_OK = 8 };
-
-struct test_domain {
- char *str;
- char *wire;
- uint size;
- char *labels;
- short label_count;
-};
-
-/*! \warning Do not change the order in those, if you want to test some other
- * feature with new dname, add it at the end of these arrays.
- */
-static const struct test_domain
- test_domains_ok[TEST_DOMAINS_OK] = {
- { "abc.test.domain.com.", "\3abc\4test\6domain\3com", 21,
- "\x0\x4\x9\x10", 4 },
- { "some.test.domain.com.", "\4some\4test\6domain\3com", 22,
- "\x0\x5\xA\x11", 4 },
- { "xyz.test.domain.com.", "\3xyz\4test\6domain\3com", 21,
- "\x0\x4\x9\x10", 4 },
- { "some.test.domain.com.", "\4some\4test\6domain\3com", 22,
- "\x0\x5\xA\x11", 4 },
- { "test.domain.com.", "\4test\6domain\3com", 17,
- "\x0\x5\xC", 3 },
- { ".", "\0", 1,
- "", 0 },
- { "foo.bar.net.", "\3foo\3bar\3net", 13,
- "\x0\x4\x8", 3},
- { "bar.net.", "\3bar\3net", 9,
- "\x0\x4", 2}
-};
-
-
-static int knot_rdata_tests_count(int argc, char *argv[]);
-static int knot_rdata_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api rdata_tests_api = {
- "DNS library - rdata", //! Unit name
- &knot_rdata_tests_count, //! Count scheduled tests
- &knot_rdata_tests_run //! Run scheduled tests
-};
-
-/*----------------------------------------------------------------------------*/
-/*
- * Unit implementation.
- */
-
-static uint16_t *RDATA_ITEM_PTR = (uint16_t *)0xDEADBEEF;
-
-enum { RDATA_ITEMS_COUNT = 7, TEST_RDATA_COUNT = 4 , RDATA_DNAMES_COUNT = 2 };
-
-static knot_dname_t RDATA_DNAMES[RDATA_DNAMES_COUNT] = {
- {{}, (uint8_t *)"\6abcdef\7example\3com", (uint8_t *)"\x0\x7\xF",
- NULL, 0, 20, 3},
- {{}, (uint8_t *)"\6abcdef\3foo\3com", (uint8_t *)"\x0\x7\xB", NULL, 0,
- 16, 3}
-};
-
-static knot_rdata_item_t TEST_RDATA_ITEMS[RDATA_ITEMS_COUNT] = {
- {.dname = (knot_dname_t *)0xF00},
- {.raw_data = (uint16_t *)"some data"},
- {.raw_data = (uint16_t *)"other data"},
- {.raw_data = (uint16_t *)"123456"},
- {.raw_data = (uint16_t *)"654321"},
- {.dname = &RDATA_DNAMES[0]},
- {.dname = &RDATA_DNAMES[1]}
-};
-
-/* \note indices 0 to 3 should not be changed - used in (and only in)
- * test_rdata_compare() - better than creating new struct just for this
- */
-static knot_rdata_t test_rdata[TEST_RDATA_COUNT] = {
- {&TEST_RDATA_ITEMS[3], 1, &test_rdata[1]},
- {&TEST_RDATA_ITEMS[4], 1, &test_rdata[2]},
- {&TEST_RDATA_ITEMS[5], 1, &test_rdata[3]},
- {&TEST_RDATA_ITEMS[6], 1, &test_rdata[4]},
-};
-
-static knot_rdata_t TEST_RDATA = {
- &TEST_RDATA_ITEMS[0],
- 3,
- &TEST_RDATA
-};
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tests knot_rdata_new().
- *
- * Creates new RDATA structure with no items and tests if there really are no
- * items in it.
- *
- * \retval > 0 on success.
- * \retval 0 otherwise.
- */
-static int test_rdata_create()
-{
- knot_rdata_t *rdata = knot_rdata_new();
- if (rdata == NULL) {
- diag("RDATA structure not created!");
- return 0;
- }
-
- if (knot_rdata_item(rdata, 0) != NULL) {
- diag("Get item returned something else than NULL!");
- knot_rdata_free(&rdata);
- return 0;
- }
-
- knot_rdata_free(&rdata);
- return 1;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tests knot_rdata_free().
- *
- * \retval > 0 on success.
- * \retval 0 otherwise.
- */
-static int test_rdata_delete()
-{
- // how to test this??
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static void generate_rdata(uint8_t *data, int size)
-{
- for (int i = 0; i < size; ++i) {
- data[i] = rand() % 256;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int fill_rdata(uint8_t *data, int max_size, uint16_t rrtype,
- knot_rdata_t *rdata)
-{
- assert(rdata != NULL);
- assert(data != NULL);
- assert(max_size > 0);
-
- uint8_t *pos = data;
- int used = 0;
- int wire_size = 0;
-
- //note("Filling RRType %u", rrtype);
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrtype);
-
- uint item_count = desc->length;
- knot_rdata_item_t *items =
- (knot_rdata_item_t *)malloc(item_count
- * sizeof(knot_rdata_item_t));
-
- for (int i = 0; i < item_count; ++i) {
- uint size = 0;
- int domain = 0;
- knot_dname_t *dname = NULL;
- int binary = 0;
- int stored_size = 0;
-
- switch (desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME:
- dname = knot_dname_new_from_wire(
- (uint8_t *)test_domains_ok[0].wire,
- test_domains_ok[0].size, NULL);
- assert(dname != NULL);
- /* note("Created domain name: %s",
- knot_dname_name(dname)); */
- //note("Domain name ptr: %p", dname);
- domain = 1;
- size = knot_dname_size(dname);
- //note("Size of created domain name: %u", size);
- assert(size < KNOT_MAX_RDATA_ITEM_SIZE);
- // store size of the domain name
- *(pos++) = size;
- // copy the domain name
- memcpy(pos, knot_dname_name(dname), size);
- pos += size;
- break;
- default:
- binary = 1;
- size = rand() % KNOT_MAX_RDATA_ITEM_SIZE;
- }
-
- if (binary) {
- // Rewrite the actual 2 bytes in the data array
- // with length.
- // (this is a bit ugly, but does the work ;-)
- knot_wire_write_u16(pos, size);
- //*pos = size;
- }
-
- //note("Filling %u bytes", size);
- used += size;
- assert(used < max_size);
-
- if (domain) {
- items[i].dname = dname;
- wire_size += knot_dname_size(dname);
-/* note("Saved domain name ptr on index %d: %p",
- i, items[i].dname); */
- } else {
- free(dname);
-// note("Saved raw data ptr on index %d: %p",i, pos);
- items[i].raw_data = (uint16_t *)pos;
- pos += size;
- wire_size += size;
- if (binary && !stored_size) {
- wire_size -= 2;
- }
- }
- }
-
- int res = knot_rdata_set_items(rdata, items, item_count);
- if (res != 0) {
- diag("knot_rdata_set_items() returned %d.", res);
- free(items);
- return -1;
- } else {
- free(items);
- return wire_size;
- }
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Checks if all RDATA items in the given RDATA structure are correct.
- *
- * \return Number of errors encountered. Error is either if some RDATA item
- * is not set (i.e. NULL) or if it has other than the expected value.
- */
-static int check_rdata(const uint8_t *data, int max_size, uint16_t rrtype,
- const knot_rdata_t *rdata)
-{
- assert(rdata != NULL);
- assert(data != NULL);
- assert(max_size > 0);
-
- int errors = 0;
-
- const uint8_t *pos = data;
- int used = 0;
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrtype);
- uint item_count = desc->length;
- //note("check_rdata(), RRType: %u", rrtype);
- //note(" item count: %u", item_count);
-
- for (int i = 0; i < item_count; ++i) {
- uint size = 0;
- int domain = 0;
- int binary = 0;
-
- //note(" item: %d", i);
-
- switch (desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME:
- //note(" domain name");
- domain = 1;
- size = knot_dname_size(knot_rdata_item(
- rdata, i)->dname);
- break;
- default:
- size =
- knot_wire_read_u16((uint8_t *)
- (knot_rdata_item(
- rdata, i)->raw_data));
- }
-
- assert(size > 0);
- //note("Size: %u", size);
- used += size;
- assert(used < max_size);
-
- //note(" item size: %u", size);
-
- if (domain) {
- /*note("Domain name ptr: %p",
- knot_rdata_get_item(rdata, i)->dname);*/
- // check dname size
- if (*pos != size) {
- diag("Domain name stored in %d-th"
- "RDATA has wrong size: %d"
- " (should be %d)", size, *pos);
- ++errors;
- } else if (strncmp((char *)knot_dname_name(
- knot_rdata_item(rdata, i)->dname),
- (char *)(pos + 1), *pos) != 0) {
- diag("Domain name stored in %d-th"
- "RDATA item is wrong: %s ("
- "should be %.*s)", i,
- knot_dname_name(knot_rdata_item(
- rdata, i)->dname),
- *pos, (char *)(pos + 1));
- ++errors;
- }
-
- pos += *pos + 1;
-
- continue;
- }
-
- if (binary &&
- size !=
- knot_wire_read_u16(
- (uint8_t *)(knot_rdata_item(rdata, i)->raw_data))) {
- diag("Size of stored binary data is wrong:"
- " %u (should be %u)",
- knot_rdata_item(rdata, i)->raw_data[0] + 1,
- size);
- ++errors;
- }
-
- if (strncmp((char *)
- (&knot_rdata_item(rdata, i)->raw_data[0]),
- (char *)pos, size) != 0) {
-/* knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrtype); */
-
- diag("Data stored in %d-th RDATA item are wrong.", i);
- ++errors;
- }
-
- pos += size;
- }
-
- return errors;
-}
-
-/*----------------------------------------------------------------------------*/
-
-//static int convert_to_wire(const uint8_t *data, int max_size, uint16_t rrtype,
-// uint8_t *data_wire)
-//{
-// //note("Converting type %u", rrtype);
-
-// int wire_size = 0;
-// const uint8_t *pos = data;
-// uint8_t *pos_wire = data_wire;
-
-// knot_rrtype_descriptor_t *desc =
-// knot_rrtype_descriptor_by_type(rrtype);
-// uint item_count = desc->length;
-
-// for (int i = 0; i < item_count; ++i) {
-// const uint8_t *from = NULL;
-// uint to_copy = 0;
-
-// switch (desc->wireformat[i]) {
-// case KNOT_RDATA_WF_COMPRESSED_DNAME:
-// case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
-// case KNOT_RDATA_WF_LITERAL_DNAME:
-// // copy the domain name without its length
-// from = pos + 1;
-// to_copy = *pos;
-// pos += *pos + 1;
-///* note("Domain name in wire format (size %u): %s",
-// to_copy, (char *)from); */
-// break;
-// case KNOT_RDATA_WF_BYTE:
-// //note(" 1byte int");
-// from = pos;
-// to_copy = 1;
-// pos += 1;
-// break;
-// case KNOT_RDATA_WF_SHORT:
-// //note(" 2byte int");
-// from = pos;
-// to_copy = 2;
-// pos += 2;
-// break;
-// case KNOT_RDATA_WF_LONG:
-// //note(" 4byte int");
-// from = pos;
-// to_copy = 4;
-// pos += 4;
-// break;
-// case KNOT_RDATA_WF_A:
-// //note(" A");
-// from = pos;
-// to_copy = 4;
-// pos += 4;
-// break;
-// case KNOT_RDATA_WF_AAAA:
-// //note(" AAAA");
-// from = pos;
-// to_copy = 16;
-// pos += 16;
-// break;
-// case KNOT_RDATA_WF_BINARY:
-// case KNOT_RDATA_WF_APL: // saved as binary
-// case KNOT_RDATA_WF_IPSECGATEWAY: // saved as binary
-// //note(" binary");
-// from = pos + 1;
-// to_copy = *pos;
-// pos += *pos + 1;
-// break;
-// case KNOT_RDATA_WF_TEXT:
-// case KNOT_RDATA_WF_BINARYWITHLENGTH:
-// //note(" text or binary with length (%u)", *pos);
-// to_copy = *pos + 1;
-// from = pos;
-// pos += *pos + 1;
-// break;
-// default:
-// assert(0);
-// }
-
-// //note("Copying %u bytes from %p", to_copy, from);
-
-// assert(from != NULL);
-// assert(to_copy != 0);
-
-// memcpy(pos_wire, from, to_copy);
-// pos_wire += to_copy;
-// wire_size += to_copy;
-
-// assert(wire_size < max_size);
-// }
-
-// return wire_size;
-//}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tests knot_rdata_set_item().
- *
- * \retval > 0 on success.
- * \retval 0 otherwise.
- */
-static int test_rdata_set_item()
-{
- knot_rdata_t *rdata = knot_rdata_new();
- knot_rdata_item_t item;
- item.raw_data = RDATA_ITEM_PTR;
-
- int ret = knot_rdata_set_item(rdata, 0, item);
- if (ret == 0) {
- diag("knot_rdata_set_item() called on empty RDATA"
- "returned %d instead of error (-1).", ret);
- knot_rdata_free(&rdata);
- return 0;
- }
-
-// uint8_t *data = malloc(sizeof(uint8_t) * KNOT_MAX_RDATA_WIRE_SIZE);
-// assert(data);
- uint8_t data[KNOT_MAX_RDATA_WIRE_SIZE];
- generate_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE);
-
- // set items through set_items() and then call set_item()
- uint16_t rrtype = rand() % KNOT_RRTYPE_LAST + 1;
- if (fill_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE, rrtype, rdata) < 0) {
- knot_rdata_free(&rdata);
- diag("Error filling RDATA");
- return 0;
- }
-
- uint8_t pos = rand() % knot_rrtype_descriptor_by_type(rrtype)->length;
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrtype);
-
- // if the rdata on this position is domain name, free it to avoid leaks
- if (desc->wireformat[pos] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME
- || desc->wireformat[pos] == KNOT_RDATA_WF_COMPRESSED_DNAME
- || desc->wireformat[pos] == KNOT_RDATA_WF_LITERAL_DNAME) {
- knot_dname_free(&(rdata->items[pos].dname));
- }
-
- ret = knot_rdata_set_item(rdata, pos, item);
- if (ret != 0) {
- diag("knot_rdata_set_item() called on filled"
- " RDATA returned %d instead of 0.", ret);
- knot_rdata_free(&rdata);
- return 0;
- }
-
- if (knot_rdata_item(rdata, pos)->raw_data != RDATA_ITEM_PTR) {
- diag("RDATA item on position %d is wrong: %p (should be %p).",
- pos, knot_rdata_item(rdata, pos)->raw_data,
- RDATA_ITEM_PTR);
- knot_rdata_free(&rdata);
- return 0;
- }
-
- for (int x = 0; x < desc->length; x++) {
- if (x != pos && (
- desc->wireformat[x] ==
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[x] ==
- KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[x] ==
- KNOT_RDATA_WF_LITERAL_DNAME)) {
- knot_dname_free(&(rdata->items[x].dname));
- }
- }
-
-// knot_rdata_free(&rdata);
- return 1;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tests knot_rdata_set_items().
- *
- * Iterates over the test_rdatas array and for each testing RDATA it creates
- * the RDATA structure, sets its items (\see set_rdata_all()) and checks if the
- * items are set properly (\see check_rdata()).
- *
- * \retval > 0 on success.
- * \retval 0 otherwise.
- */
-static int test_rdata_set_items()
-{
- knot_rdata_t *rdata = NULL;
- knot_rdata_item_t *item = (knot_rdata_item_t *)0xDEADBEEF;
- int errors = 0;
-
- // check error return values
- if (knot_rdata_set_items(rdata, NULL, 0) != KNOT_EINVAL) {
- diag("Return value of knot_rdata_set_items() "
- "when rdata == NULL is wrong");
- return 0;
- } else {
- rdata = knot_rdata_new();
- assert(rdata != NULL);
-
- if (knot_rdata_set_items(rdata, NULL, 0) != KNOT_EINVAL) {
- diag("Return value of knot_rdata_set_items()"
- " when items == NULL is wrong");
-// knot_rdata_free(&rdata);
- return 0;
- } else if (knot_rdata_set_items(rdata, item, 0) !=
- KNOT_EINVAL) {
- diag("Return value of knot_rdata_set_items()"
- " when count == 0"
- "is wrong");
-// knot_rdata_free(&rdata);
- return 0;
- }
-// knot_rdata_free(&rdata);
- }
-
- // generate some random data
-// uint8_t *data = malloc(sizeof(uint8_t) * KNOT_MAX_RDATA_WIRE_SIZE);
- uint8_t data [KNOT_MAX_RDATA_WIRE_SIZE];
- generate_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE);
-
- for (int i = 0; i <= KNOT_RRTYPE_LAST; ++i) {
- rdata = knot_rdata_new();
-
- if (fill_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE, i, rdata)
- < 0) {
- ++errors;
- }
- errors += check_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE, i,
- rdata);
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(i);
-
- for (int x = 0; x < desc->length; x++) {
- if (desc->wireformat[x] ==
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[x] ==
- KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[x] ==
- KNOT_RDATA_WF_LITERAL_DNAME) {
-// printf("freeing %p\n", rdata->items[x].dname);
- knot_dname_free(&(rdata->items[x].dname));
- }
- }
-
-// knot_rdata_free(&rdata);
- }
-
- return (errors == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tests knot_rdata_get_item().
- *
- * \retval > 0 on success.
- * \retval 0 otherwise.
- */
-static int test_rdata_get_item()
-{
- const knot_rdata_t *rdata = &TEST_RDATA;
-
- if (knot_rdata_item(rdata, TEST_RDATA.count) != NULL) {
- diag("knot_rdata_get_item() called with"
- "invalid position did not return NULL");
- return 0;
- }
-
- int errors = 0;
- if ((knot_rdata_item(rdata, 0)->dname)
- != TEST_RDATA.items[0].dname) {
- diag("RDATA item on position 0 is wrong: %p (should be %p)",
- knot_rdata_item(rdata, 0), TEST_RDATA.items[0]);
- ++errors;
- }
- if ((knot_rdata_item(rdata, 1)->raw_data)
- != TEST_RDATA.items[1].raw_data) {
- diag("RDATA item on position 0 is wrong: %p (should be %p)",
- knot_rdata_item(rdata, 1), TEST_RDATA.items[1]);
- ++errors;
- }
- if ((knot_rdata_item(rdata, 2)->raw_data)
- != TEST_RDATA.items[2].raw_data) {
- diag("RDATA item on position 0 is wrong: %p (should be %p)",
- knot_rdata_item(rdata, 2), TEST_RDATA.items[2]);
- ++errors;
- }
-
- return (errors == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int test_rdata_compare()
-{
- int errors = 0;
-
- uint8_t format_rawdata = KNOT_RDATA_WF_BINARY;
-
- uint8_t format_dname = KNOT_RDATA_WF_LITERAL_DNAME;
-
- /* 123456 \w 654321 -> result -1 */
- if (knot_rdata_compare(&test_rdata[0],
- &test_rdata[1],
- &format_rawdata) != -1) {
- diag("RDATA raw data comparison failed 0");
- errors++;
- }
-
- /* 123456 \w 123456 -> result 0 */
- if (knot_rdata_compare(&test_rdata[0],
- &test_rdata[0],
- &format_rawdata) != 0) {
- diag("RDATA raw data comparison failed 1 ");
- errors++;
- }
-
- /* 123456 \w 654321 -> result 1 */
- if (knot_rdata_compare(&test_rdata[1],
- &test_rdata[0],
- &format_rawdata) != 1) {
- diag("RDATA raw data comparison failed 2");
- errors++;
- }
-
- /* abcdef.example.com. \w abcdef.foo.com. -> result -1 */
- int ret = 0;
- if ((ret = knot_rdata_compare(&test_rdata[2],
- &test_rdata[3],
- &format_dname)) >= 0) {
- diag("RDATA dname comparison failed 3");
- errors++;
- }
-
- /* abcdef.example.com. \w abcdef.example.com. -> result 0 */
- if (knot_rdata_compare(&test_rdata[2],
- &test_rdata[2],
- &format_dname) != 0) {
- diag("RDATA dname comparison failed 4");
- errors++;
- }
-
- /* abcdef.example.com. \w abcdef.foo.com -> result 1 */
- if (knot_rdata_compare(&test_rdata[3],
- &test_rdata[2],
- &format_dname) != 1) {
- diag("RDATA dname comparison failed 5");
- errors++;
- }
-
-
-
-
- return (errors == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-//static int test_rdata_wire_size()
-//{
-// knot_rdata_t *rdata;
-// int errors = 0;
-
-// // generate some random data
-// uint8_t data[KNOT_MAX_RDATA_WIRE_SIZE];
-// generate_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE);
-
-// for (int i = 0; i <= KNOT_RRTYPE_LAST; ++i) {
-// rdata = knot_rdata_new();
-
-// int size =
-// fill_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE, i, rdata);
-
-// if (size < 0) {
-// ++errors;
-// } else {
-// int counted_size = knot_rdata_wire_size(rdata,
-// knot_rrtype_descriptor_by_type(i)->wireformat);
-// if (size != counted_size) {
-// diag("Wrong wire size computed (type %d):"
-// " %d (should be %d)",
-// i, counted_size, size);
-// ++errors;
-// }
-// }
-
-// knot_rrtype_descriptor_t *desc =
-// knot_rrtype_descriptor_by_type(i);
-
-// for (int x = 0; x < desc->length; x++) {
-// if (desc->wireformat[x] ==
-// KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
-// desc->wireformat[x] ==
-// KNOT_RDATA_WF_COMPRESSED_DNAME ||
-// desc->wireformat[x] ==
-// KNOT_RDATA_WF_LITERAL_DNAME) {
-// knot_dname_free(&(rdata->items[x].dname));
-// }
-// }
-// knot_rdata_free(&rdata);
-// }
-
-// return (errors == 0);
-//}
-
-/*----------------------------------------------------------------------------*/
-
-//static int test_rdata_to_wire()
-//{
-// knot_rdata_t *rdata;
-// int errors = 0;
-
-// // generate some random data
-// uint8_t data[KNOT_MAX_RDATA_WIRE_SIZE];
-// uint8_t data_wire[KNOT_MAX_RDATA_WIRE_SIZE];
-// uint8_t rdata_wire[KNOT_MAX_RDATA_WIRE_SIZE];
-// generate_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE);
-
-// for (int i = 0; i <= KNOT_RRTYPE_LAST; ++i) {
-// rdata = knot_rdata_new();
-
-// int size =
-// fill_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE, i, rdata);
-
-// int size_expected =
-// convert_to_wire(data, KNOT_MAX_RDATA_WIRE_SIZE, i,
-// data_wire);
-
-// if (size < 0) {
-// ++errors;
-// } else {
-// if (size != size_expected) {
-// diag("Wire format size (%u) not"
-// " as expected (%u)",
-// size, size_expected);
-// ++errors;
-// } else {
-// if (knot_rdata_to_wire(rdata,
-// knot_rrtype_descriptor_by_type(i)->
-// wireformat, rdata_wire,
-// KNOT_MAX_RDATA_WIRE_SIZE) != 0) {
-// diag("Error while converting RDATA"
-// " to wire format.");
-// ++errors;
-// } else {
-// if (strncmp((char *)data_wire,
-// (char *)rdata_wire, size)
-// != 0) {
-// diag("RDATA converted to wire"
-// "format does not match"
-// " the expected value");
-// ++errors;
-// }
-// }
-// }
-// }
-
-// knot_rrtype_descriptor_t *desc =
-// knot_rrtype_descriptor_by_type(i);
-
-// for (int x = 0; x < desc->length; x++) {
-// if (desc->wireformat[x] ==
-// KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
-// desc->wireformat[x] ==
-// KNOT_RDATA_WF_COMPRESSED_DNAME ||
-// desc->wireformat[x] ==
-// KNOT_RDATA_WF_LITERAL_DNAME) {
-// knot_dname_free(&(rdata->items[x].dname));
-// }
-// }
-// knot_rdata_free(&rdata);
-// }
-
-// return (errors == 0);
-//}
-
-static int test_rdata_free()
-{
- return 0;
-// knot_rdata_t *tmp_rdata;
-
-// tmp_rdata = knot_rdata_new();
-
-// knot_rdata_free(&tmp_rdata);
-
-// return (tmp_rdata == NULL);
-}
-/* Can't test this with current implementation
- * would be trying to free pointers on stack */
-static int test_rdata_deep_free()
-{
- return 0;
-
-/* int errors = 0;
-
- knot_rdata_t *tmp_rdata;
-
- uint8_t data[KNOT_MAX_RDATA_WIRE_SIZE];
-
- for (int i = 0; i <= KNOT_RRTYPE_LAST; i++) {
- tmp_rdata = knot_rdata_new();
-
- fill_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE, i, tmp_rdata);
-
- knot_rdata_deep_free(&tmp_rdata, i, 0);
- errors += (tmp_rdata != NULL);
- }
-
- return (errors == 0); */
-}
-
-/*----------------------------------------------------------------------------*/
-
-static const int KNOT_RDATA_TEST_COUNT = 8;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_rdata_tests_count(int argc, char *argv[])
-{
- return KNOT_RDATA_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_rdata_tests_run(int argc, char *argv[])
-{
- int res = 0,
- res_final = 1;
-
- res = test_rdata_create();
- ok(res, "rdata: create empty");
- res_final *= res;
-
- skip(!res, 6);
-
- todo();
-
- ok(res = test_rdata_delete(), "rdata: delete");
- //res_final *= res;
-
- endtodo;
-
- ok(res = test_rdata_get_item(), "rdata: get item");
- res_final *= res;
-
- skip(!res, 4)
-
- ok(res = test_rdata_set_items(), "rdata: set items all at once");
- res_final *= res;
-
- skip(!res, 3);
-
- ok(res = test_rdata_set_item(), "rdata: set items one-by-one");
- res_final *= res;
-
- ok(res = test_rdata_compare(), "rdata: compare");
- res_final *= res;
-
-// ok(res = test_rdata_wire_size(), "rdata: wire size");
-// res_final *= res;
-
-// skip(!res, 1);
-
-// ok(res = test_rdata_to_wire(), "rdata: to wire");
-// res_final *= res;
-
-// endskip; /* test_rdata_wire_size() failed */
-
- endskip; /* test_rdata_set_items() failed */
-
- endskip; /* test_rdata_get_item() failed */
-
- endskip; /* test_rdata_create() failed */
-
- todo();
-
- ok(res = test_rdata_deep_free(), "rdata: deep free");
- res_final *= res;
-
- ok(res = test_rdata_free(), "rdata: free");
- res_final *= res;
-
- endtodo;
-
- return res_final;
-}
diff --git a/src/tests/libknot/libknot/rdata_tests.h b/src/tests/libknot/libknot/rdata_tests.h
deleted file mode 100644
index 1f43c91..0000000
--- a/src/tests/libknot/libknot/rdata_tests.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (C) 2011 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 rdata_tests.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * Contains unit tests for RDATA (knot_rdata_t) and RDATA item
- * (knot_rdata_item_t) structures.
- *
- * Contains tests for:
- * - creating empty RDATA structure with or without reserved space.
- * - setting RDATA items one-by-one
- * - setting RDATA items all at once
- *
- * As for now, the tests use several (TEST_RDATAS) RDATA structures, each
- * with different number of RDATA items (given by test_rdatas). These are all
- * initialized to pointers derived from RDATA_ITEM_PTR (first is RDATA_ITEM_PTR,
- * second RDATA_ITEM_PTR + 1, etc.). The functions only test if the pointer
- * is set properly.
- *
- * \todo It may be better to test also some RDATAs with predefined contents,
- * such as some numbers, some domain name, etc. For this purpose, we'd
- * need RDATA descriptors (telling the types of each RDATA item within an
- * RDATA).
- *
- * \todo It will be fine to test all possible output values of all functions,
- * e.g. test whether knot_rdata_get_item() returns NULL when passed an
- * illegal position, etc.
- */
-#ifndef _KNOTD_RDATA_TESTS_H_
-#define _KNOTD_RDATA_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api rdata_tests_api;
-
-#endif /* _KNOTD_RDATA_TESTS_H_ */
diff --git a/src/tests/libknot/libknot/response_tests.c b/src/tests/libknot/libknot/response_tests.c
deleted file mode 100644
index 834d838..0000000
--- a/src/tests/libknot/libknot/response_tests.c
+++ /dev/null
@@ -1,449 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-#include <inttypes.h>
-
-//#define RESP_TEST_DEBUG
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "tests/libknot/libknot/response_tests.h"
-#include "common/lists.h"
-#include "libknot/common.h"
-#include "libknot/packet/response.h"
-#include "libknot/rdata.h"
-#include "libknot/rrset.h"
-#include "libknot/dname.h"
-#include "libknot/util/wire.h"
-#include "libknot/util/descriptor.h"
-#include "libknot/edns.h"
-
-#ifdef TEST_WITH_LDNS
-#include "ldns/ldns.h"
-#endif
-
-static int knot_response_tests_count(int argc, char *argv[]);
-static int knot_response_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api response_tests_api = {
- "DNS library - response", //! Unit name
- &knot_response_tests_count, //! Count scheduled tests
- &knot_response_tests_run //! Run scheduled tests
-};
-
-static int test_response_init()
-{
- int errors = 0;
- int lived = 0;
- lives_ok({
- if (knot_response_init(NULL) != KNOT_EINVAL) {
- diag("Calling response_init with NULL packet did "
- "not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "response: init NULL tests");
- errors += lived != 1;
-
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
- assert(response);
- response->max_size = KNOT_WIRE_HEADER_SIZE - 1;
- if (knot_response_init(response) != KNOT_ESPACE) {
- diag("Calling response_init too small packet did "
- "not return KNOT_ESPACE!");
- errors++;
- }
-
- return (errors == 0);
-}
-
-static int test_response_init_query()
-{
- int errors = 0;
- int lived = 0;
- lives_ok({
- if (knot_response_init_from_query(NULL, NULL, 1) !=
- KNOT_EINVAL) {
- diag("Calling response_init_query with NULL packet and "
- "NULL query did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
- knot_packet_set_max_size(response,
- KNOT_PACKET_PREALLOC_RESPONSE);
- knot_response_init(response);
- lived = 0;
- if (knot_response_init_from_query(response, NULL, 1) !=
- KNOT_EINVAL) {
- diag("Calling response_init_query with NULL query "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- knot_packet_t *query =
- knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
- if (knot_response_init_from_query(NULL, query, 1) !=
- KNOT_EINVAL) {
- diag("Calling response_init_query with NULL response "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- }, "response: init from query NULL tests");
- errors += lived != 1;
-
- /* Cannot test the rest of return values, since there is now constant
- * controlling value that could return KNOT_EDNAMEPTR */
-
- return (errors == 0);
-}
-
-int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count)
-{
- int i = 0;
- while (i < count &&
- wire1[i] == wire2[i]) {
- i++;
- }
- return (!(count == i));
-}
-
-
-//static int test_response_clear()
-//{
-// int errors = 0;
-// int lived = 0;
-// lives_ok({
-// knot_response_clear(NULL, 1);
-// lived = 1;
-// }, "response: clear NULL tests");
-// errors += lived != 1;
-
-// /*
-// * Create new response, convert to wire, then add something, clear
-// * the response, convert to wire again and compare wires.
-// */
-
-// knot_packet_t *response =
-// knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
-// knot_packet_set_max_size(response, KNOT_WIRE_HEADER_SIZE * 100);
-// assert(knot_response_init(response) == KNOT_EOK);
-
-// uint8_t *original_wire = NULL;
-// size_t original_size = 0;
-// assert(knot_packet_to_wire(response, &original_wire,
-// &original_size) ==
-// KNOT_EOK);
-// /* Do something in question section. */
-//// test_dname_t test_dname;
-//// test_dname.str = "ns8.nic.cz.";
-//// knot_dname_t *dname = dname_from_test_dname_str(&test_dname);
-//// assert(dname);
-
-// response->question.qtype = KNOT_RRTYPE_HINFO;
-// response->question.qclass = KNOT_CLASS_CH;
-
-// uint8_t *question_changed_wire = NULL;
-// size_t question_changed_size = 0;
-// assert(knot_packet_to_wire(response,
-// &question_changed_wire,
-// &question_changed_size) ==
-// KNOT_EOK);
-
-// knot_response_set_aa(response);
-// knot_response_set_tc(response);
-// knot_response_set_rcode(response, knot_quick_rand());
-
-// knot_response_clear(response, 0);
-// uint8_t *new_wire = NULL;
-// size_t new_size = 0;
-// assert(knot_packet_to_wire(response, &new_wire, &new_size) ==
-// KNOT_EOK);
-// if (question_changed_size != new_size) {
-// diag("Wrong wire size after calling response_clear! "
-// "got %d should be %d", new_size, question_changed_size);
-// errors++;
-// } else {
-// if (compare_wires_simple(question_changed_wire,
-// new_wire, new_size)) {
-// diag("Wrong wire after calling response_clear! ");
-// errors++;
-// }
-// }
-// free(new_wire);
-
-// new_wire = NULL;
-// new_size = 0;
-
-// /*!< \todo figure out this segfault! */
-
-//// knot_response_clear(response, 1);
-//// assert(knot_packet_to_wire(response, &new_wire, &new_size) ==
-//// KNOT_EOK);
-
-//// if (original_size != new_size) {
-//// diag("Wrong wire size after calling response_clear!");
-//// errors++;
-//// } else {
-//// if (compare_wires_simple(original_wire,
-//// new_wire, new_size)) {
-//// diag("Wrong wire after calling response_clear!");
-//// errors++;
-//// }
-//// }
-
-//// free(new_wire);
-//// free(original_wire);
-//// free(question_changed_wire);
-//// knot_packet_free(&response);
-
-// return (errors == 0);
-//}
-
-static int test_response_add_opt()
-{
- int errors = 0;
- int lived = 0;
-
- knot_opt_rr_t opt;
- opt.payload = 512;
- opt.ext_rcode = 0;
- opt.version = EDNS_VERSION_0;
- opt.flags = 0;
- opt.options = NULL;
- opt.option_count = 0;
- opt.options_max = 0;
- opt.size = 25; // does it matter?
-
- lives_ok({
- if (knot_response_add_opt(NULL, NULL, 0, 0) != KNOT_EINVAL) {
- diag("Calling response add opt with NULL arguments "
- "did not result to KNOT_EINVAL");
- errors++;
- }
- lived = 1;
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
- lived = 0;
- if (knot_response_add_opt(response,
- NULL, 0, 0) != KNOT_EINVAL) {
- diag("Calling response add opt with NULL OPT RR "
- "did not result to KNOT_EINVAL");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- if (knot_response_add_opt(NULL,
- &opt, 0, 0) != KNOT_EINVAL) {
- diag("Calling response add opt with NULL response "
- "did not result to KNOT_EINVAL");
- errors++;
- }
- lived = 1;
- knot_packet_free(&response);
- }, "response: add opt NULL tests");
- errors += lived != 1;
-
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
- knot_packet_set_max_size(response, KNOT_PACKET_PREALLOC_RESPONSE * 100);
- assert(knot_response_init(response) == KNOT_EOK);;
-
- if (knot_response_add_opt(response, &opt, 0, 0) != KNOT_EOK) {
- diag("Adding valid OPT RR to response "
- "did not return KNOT_EOK");
- errors++;
- }
-
- opt.payload = response->max_size + 1;
- if (knot_response_add_opt(response, &opt, 1, 0) != KNOT_EPAYLOAD) {
- diag("If OPT RR payload is bigger than response max size "
- "response_add_opt does not return KNOT_EPAYLOAD!");
- errors++;
- }
-
- opt.payload = 0;
- if (knot_response_add_opt(response, &opt, 1, 0) != KNOT_EINVAL) {
- diag("Calling response_add_opt with OPT RR payload set to 0 "
- "did not return KNOT_EINVAL");
- }
-
- knot_packet_free(&response);
- return (errors == 0);
-}
-
-static int test_response_add_generic(int (*func)(knot_packet_t *,
- knot_rrset_t *,
- int, int, int, int))
-{
- int errors = 0;
- int lived = 0;
-
- lives_ok({
- if (func(NULL, NULL, 0, 0, 0, 0) != KNOT_EINVAL) {
- diag("Calling response add rrset with NULL "
- "arguments did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
- lived = 0;
- if (func(response, NULL, 0, 0, 0, 0) != KNOT_EINVAL) {
- diag("Calling response add rrset with NULL rrset "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- knot_dname_t *owner =
- knot_dname_new_from_str("ns.nic.cz.",
- strlen("ns.nic.cz."),
- NULL);
- assert(owner);
- knot_rrset_t *rrset =
- knot_rrset_new(owner, KNOT_RRTYPE_A,
- KNOT_CLASS_IN, 3600);
- assert(rrset);
- lived = 0;
- if (func(NULL, rrset, 0, 0, 0, 0) != KNOT_EINVAL) {
- diag("Calling response add rrset with NULL response "
- "did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- knot_rrset_deep_free(&rrset, 1, 0, 0);
- knot_packet_free(&response);
- }, "response: rrset adding NULL tests");
- errors += lived != 1;
-
- /*!< \todo Test case when KNOT_ESPACE should be returned. */
- /*!< \todo Compression and so on - should it be tested here? */
-
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
-
- knot_dname_t *owner =
- knot_dname_new_from_str("ns12.nic.cz.",
- strlen("ns12.nic.cz."),
- NULL);
- assert(owner);
- knot_rrset_t *rrset =
- knot_rrset_new(owner, KNOT_RRTYPE_NS,
- KNOT_CLASS_IN, 3600);
- assert(rrset);
- if (func(response, rrset, 0, 0, 0, 0) != KNOT_EOK) {
- diag("Adding valid RRSet to response did not result to "
- "KNOT_EOK");
- errors++;
- }
-
- knot_rrset_deep_free(&rrset, 1, 0, 0);
- knot_packet_free(&response);
-
- return (errors == 0);
-}
-
-static void test_response_add_rrset()
-{
- ok(test_response_add_generic(knot_response_add_rrset_answer),
- "response: add answer rrset");
- ok(test_response_add_generic(knot_response_add_rrset_authority),
- "response: add answer authority");
- ok(test_response_add_generic(knot_response_add_rrset_additional),
- "response: add answer additional");
-}
-
-static int test_response_add_nsid()
-{
- int errors = 0;
- int lived = 0;
-
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
-
- uint8_t *nsid = (uint8_t *)"knotDNS";
- uint16_t nsid_size = strlen((char *)nsid);
- lives_ok({
- if (knot_response_add_nsid(NULL,
- NULL, 1) != KNOT_EINVAL) {
- diag("Calling response add nsid with NULL arguments "
- "did not return KNOT_EINVAL");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- if (knot_response_add_nsid(NULL, nsid,
- nsid_size) != KNOT_EINVAL) {
- diag("Calling response add nsid with NULL response "
- "did not return KNOT_EINVAL");
- errors++;
- }
- lived = 1;
-// lived = 0;
-// if (knot_response_add_nsid(response, nsid,
-// 0) != KNOT_EINVAL) {
-// diag("Calling response add nsid with zero size "
-// "did not return KNOT_EINVAL");
-// errors++;
-// }
-// lived = 1;
- }, "response: add nsid NULL tests");
- errors += lived != 1;
-
- if (knot_response_add_nsid(response, nsid,
- nsid_size) != KNOT_EOK) {
- diag("Adding valid nsid to response did not return KNOT_EOK");
- errors++;
- }
-
- knot_packet_free(&response);
- return (errors == 0);
-}
-
-static const int KNOT_response_TEST_COUNT = 14;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_response_tests_count(int argc, char *argv[])
-{
- return KNOT_response_TEST_COUNT;
-}
-
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_response_tests_run(int argc, char *argv[])
-{
- ok(test_response_init(), "response: init");
- ok(test_response_init_query(), "response: init from query");
-// ok(test_response_clear(), "response: clear");
- ok(test_response_add_opt(), "response: add opt");
- test_response_add_rrset();
- ok(test_response_add_nsid(), "response: add nsid");
- return 1;
-}
diff --git a/src/tests/libknot/libknot/response_tests.h b/src/tests/libknot/libknot/response_tests.h
deleted file mode 100644
index c9a117b..0000000
--- a/src/tests/libknot/libknot/response_tests.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_response_TESTS_H_
-#define _KNOTD_response_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api response_tests_api;
-
-#endif /* _KNOTD_response_TESTS_H_ */
diff --git a/src/tests/libknot/libknot/rrset_tests.c b/src/tests/libknot/libknot/rrset_tests.c
deleted file mode 100644
index 41284df..0000000
--- a/src/tests/libknot/libknot/rrset_tests.c
+++ /dev/null
@@ -1,888 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "tests/libknot/libknot/rrset_tests.h"
-#include "libknot/common.h"
-#include "libknot/util/descriptor.h"
-#include "libknot/rrset.h"
-#include "libknot/dname.h"
-#include "libknot/rdata.h"
-#include "libknot/util/utils.h"
-#include "libknot/zone/node.h"
-#include "libknot/util/debug.h"
-
-static int knot_rrset_tests_count(int argc, char *argv[]);
-static int knot_rrset_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api rrset_tests_api = {
- "DNS library - rrset", //! Unit name
- &knot_rrset_tests_count, //! Count scheduled tests
- &knot_rrset_tests_run //! Run scheduled tests
-};
-
-/*----------------------------------------------------------------------------*/
-/*
- * Unit implementation.
- */
-
-static knot_node_t *NODE_ADDRESS = (knot_node_t *)0xDEADBEEF;
-
-enum { TEST_RRSETS = 6 , TEST_RRSIGS = 6};
-
-//void *RRSIG_ADDRESS = (void *)0xDEADBEEF;
-//void *RRSIG_FIRST = RRSIG_ADDRESS + 10;
-
-struct test_domain {
- char *str;
- char *wire;
- uint size;
- char *labels;
- short label_count;
-};
-
-struct test_rrset {
- char *owner;
- uint16_t type;
- uint16_t rclass;
- uint32_t ttl;
- knot_rdata_t *rdata;
- const knot_rrset_t *rrsigs;
-};
-
-/* this has to changed */
-static const char *signature_strings[TEST_RRSIGS] =
-{"signature 1", "signature 2", "signature 3",
- "signature 4", "signature 5", "signature 6"};
-
-enum {
- RR_DNAMES_COUNT = 3,
- RR_ITEMS_COUNT = 3,
- RR_RDATA_COUNT = 4,
-};
-
-enum { TEST_DOMAINS_OK = 8 };
-
-static knot_dname_t RR_DNAMES[RR_DNAMES_COUNT] =
- { {{}, (uint8_t *)"\7example\3com", NULL, NULL, 0, 13, 0}, //0's at the end are added
- {{}, (uint8_t *)"\3ns1\7example\3com", NULL, NULL, 0, 17, 0},
- {{}, (uint8_t *)"\3ns2\7example\3com", NULL, NULL, 0, 17, 0} };
-
-/* 192.168.1.1 */
-static uint8_t address[4] = {0xc0, 0xa8, 0x01, 0x01};
-
-static knot_rdata_item_t RR_ITEMS[RR_ITEMS_COUNT] =
- { {.dname = &RR_DNAMES[1]},
- {.dname = &RR_DNAMES[2]},
- {.raw_data = (uint16_t *)address} };
-
-/*! \warning Do not change the order. */
-/* TODO this does not work as expected */
-static knot_rdata_t RR_RDATA[RR_RDATA_COUNT] =
- { {&RR_ITEMS[0], 1, &RR_RDATA[0]}, /* first ns */
- {&RR_ITEMS[1], 1, &RR_RDATA[1]}, /* second ns */
- {&RR_ITEMS[0], 1, &RR_RDATA[3]}, /* both in cyclic list */
- {&RR_ITEMS[1], 1, &RR_RDATA[2]} };
-
-/*! \warning Do not change the order in those, if you want to test some other
- * feature with new dname, add it at the end of these arrays.
- */
-static const struct test_domain
- test_domains_ok[TEST_DOMAINS_OK] = {
- { "abc.test.domain.com.", "\3abc\4test\6domain\3com", 21,
- "\x0\x4\x9\x10", 4 },
- { "some.test.domain.com.", "\4some\4test\6domain\3com", 22,
- "\x0\x5\xA\x11", 4 },
- { "xyz.test.domain.com.", "\3xyz\4test\6domain\3com", 21,
- "\x0\x4\x9\x10", 4 },
- { "some.test.domain.com.", "\4some\4test\6domain\3com", 22,
- "\x0\x5\xA\x11", 4 },
- { "test.domain.com.", "\4test\6domain\3com", 17,
- "\x0\x5\xC", 3 },
- { ".", "\0", 1,
- "", 0 },
- { "foo.bar.net.", "\3foo\3bar\3net", 13,
- "\x0\x4\x8", 3},
- { "bar.net.", "\3bar\3net", 9,
- "\x0\x4", 2}
-};
-
-static struct test_rrset test_rrsets[TEST_RRSETS] = {
- { "example.com.", KNOT_RRTYPE_NS, KNOT_CLASS_IN,
- 3600, NULL, NULL },
- { "example2.com.", KNOT_RRTYPE_NS, KNOT_CLASS_IN,
- 3600, NULL, NULL },
- { "example3.com.", KNOT_RRTYPE_NS, KNOT_CLASS_IN,
- 3600, NULL, NULL },
- { "example.com.", KNOT_RRTYPE_NS, KNOT_CLASS_IN,
- 3600, NULL, NULL },
- { "example.com.", KNOT_RRTYPE_NS, KNOT_CLASS_IN,
- 3600, NULL, NULL },
- { "example.com.", KNOT_RRTYPE_NS, KNOT_CLASS_IN,
- 3600, NULL, NULL }
-};
-
-static const struct test_rrset test_rrsigs[TEST_RRSIGS] = {
- { "example.com.", 46, 1, 3600, NULL },
- { "example2.com.", 46, 1, 3600, NULL },
- { "example3.com.", 46, 1, 3600, NULL },
- { "example4.com.", 46, 1, 3600, NULL },
- { "example5.com.", 46, 1, 3600, NULL },
- { "example6.com.", 46, 1, 3600, NULL }
-};
-
-static void generate_rdata(uint8_t *data, int size)
-{
- for (int i = 0; i < size; ++i) {
- data[i] = rand() % 256;
- }
-}
-
-static int fill_rdata_r(uint8_t *data, int max_size, uint16_t rrtype,
- knot_rdata_t *rdata)
-{
- assert(rdata != NULL);
- assert(data != NULL);
- assert(max_size > 0);
-
- uint8_t *pos = data;
- int used = 0;
- int wire_size = 0;
-
-// note("Filling RRType %u", rrtype);
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrtype);
-
- uint item_count = desc->length;
- knot_rdata_item_t *items =
- (knot_rdata_item_t *)malloc(item_count
- * sizeof(knot_rdata_item_t));
-
- for (int i = 0; i < item_count; ++i) {
- uint size = 0;
- int domain = 0;
- knot_dname_t *dname = NULL;
- int binary = 0;
- int stored_size = 0;
-
- switch (desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME:
- dname = knot_dname_new_from_wire(
- (uint8_t *)test_domains_ok[0].wire,
- test_domains_ok[0].size, NULL);
- assert(dname != NULL);
-// note("Created domain name: %s",
-// knot_dname_name(dname));
-// note("Domain name ptr: %p", dname);
- domain = 1;
- size = knot_dname_size(dname);
-// note("Size of created domain name: %u", size);
- assert(size < KNOT_MAX_RDATA_ITEM_SIZE);
- // store size of the domain name
- *(pos++) = size;
- // copy the domain name
- memcpy(pos, knot_dname_name(dname), size);
- pos += size;
- break;
- default:
- binary = 1;
- size = rand() % KNOT_MAX_RDATA_ITEM_SIZE;
- }
-
- if (binary) {
- // Rewrite the actual 2 bytes in the data array
- // with length.
- // (this is a bit ugly, but does the work ;-)
- knot_wire_write_u16(pos, size);
- //*pos = size;
- }
-
- //note("Filling %u bytes", size);
- used += size;
- assert(used < max_size);
-
- if (domain) {
- items[i].dname = dname;
- wire_size += knot_dname_size(dname);
-/* note("Saved domain name ptr on index %d: %p",
- i, items[i].dname); */
- } else {
- free(dname);
-// note("Saved raw data ptr on index %d: %p",i, pos);
- items[i].raw_data = (uint16_t *)pos;
- pos += size;
- wire_size += size;
- if (binary && !stored_size) {
- wire_size -= 2;
- }
- }
- }
-
- int res = knot_rdata_set_items(rdata, items, item_count);
- if (res != 0) {
- diag("knot_rdata_set_items() returned %d.", res);
- free(items);
- return -1;
- } else {
- free(items);
- return wire_size;
- }
-}
-
-/* fills test_rrsets with random rdata when empty */
-static void create_rdata()
-{
- knot_rdata_t *r;
-
- uint8_t *data =
- malloc(sizeof(uint8_t) * KNOT_MAX_RDATA_WIRE_SIZE);
-
- assert(data);
-
- for (int i = 0; i < TEST_RRSETS; i++) {
- if (test_rrsets[i].rdata == NULL) {
- r = knot_rdata_new();
-
- /* from rdata tests */
- generate_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE);
- if (fill_rdata_r(data, KNOT_MAX_RDATA_WIRE_SIZE,
- test_rrsets[i].type, r) <= 0) {
- diag("Error creating rdata!");
-
- }
-
- test_rrsets[i].rdata = r;
- }
- }
-
- free(data);
-}
-
-static int check_rrset(const knot_rrset_t *rrset, int i,
- int check_rdata, int check_items,
- int check_rrsigs)
-{
- /* following implementation should be self-explanatory */
- int errors = 0;
-
- if (rrset == NULL) {
- diag("RRSet not created!");
- return 1;
- }
-
- char *owner = knot_dname_to_str(rrset->owner);
- if (strcmp(owner, test_rrsets[i].owner) != 0) {
- diag("OWNER domain name wrong: '%s' (should be '%s')",
- owner, test_rrsets[i].owner);
- ++errors;
- }
- free(owner);
-
- if (rrset->type != test_rrsets[i].type) {
- diag("TYPE wrong: %u (should be: %u)", rrset->type,
- test_rrsets[i].type);
- ++errors;
- }
-
- if (rrset->rclass != test_rrsets[i].rclass) {
- diag("CLASS wrong: %u (should be: %u)", rrset->rclass,
- test_rrsets[i].rclass);
- ++errors;
- }
-
- if (rrset->ttl != test_rrsets[i].ttl) {
- diag("TTL wrong: %u (should be: %u)", rrset->ttl,
- test_rrsets[i].ttl);
- ++errors;
- }
-
- if (check_rdata) {
- /* TODO use rdata_compare */
- knot_rdata_t *rdata = rrset->rdata;
-
- if (rdata == NULL) {
- diag("There are no RDATAs in the RRSet");
- ++errors;
- }
-
- if (rdata != NULL) {
- while (rdata->next != NULL &&
- rdata->next != rrset->rdata) {
- rdata = rdata->next;
- }
- if (rdata->next == NULL) {
- diag("The list of RDATAs is not cyclic!");
- ++errors;
- } else {
- assert(rdata->next == rrset->rdata);
- }
- }
- }
-
- if (check_items) {
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
- if (knot_rdata_compare(rrset->rdata,
- test_rrsets[i].rdata,
- desc->wireformat) != 0) {
- diag("Rdata items do not match.");
- errors++;
- }
- }
-
- /* TODO this deserves a major improvement!!! */
-
- /*
- * Will work only with null terminated strings,
- * consider changing to more versatile implementation
- */
-
- /* How about, once it's tested, using rdata_compare */
-
- if (check_rrsigs) {
-
- const knot_rrset_t *rrsigs;
-
- rrsigs = knot_rrset_rrsigs(rrset);
- if (strcmp((const char *)rrsigs->rdata->items[0].raw_data,
- signature_strings[i])) {
- diag("Signatures are not equal"
- "to those set when creating."
- "Comparing %s with %s",
- rrsigs->rdata->items[0].raw_data,
- signature_strings[i]);
- errors++;
- }
- }
- return errors;
-}
-
-static int test_rrset_create()
-{
- int errors = 0;
-
- for (int i = 0; i < TEST_RRSETS; ++i) {
- knot_dname_t *owner = knot_dname_new_from_str(
- test_rrsets[i].owner,
- strlen(test_rrsets[i].owner),
- NODE_ADDRESS);
- if (owner == NULL) {
- diag("Error creating owner domain name!");
- return 0;
- }
- knot_rrset_t *rrset = knot_rrset_new(owner,
- test_rrsets[i].type,
- test_rrsets[i].rclass,
- test_rrsets[i].ttl);
-
- errors += check_rrset(rrset, i, 0, 0, 0);
-
- knot_rrset_free(&rrset);
- knot_dname_free(&owner);
- }
-
- //diag("Total errors: %d", errors);
-
- return (errors == 0);
-}
-
-/* Not implemented - no way how to test unfreed memory from here (yet) */
-static int test_rrset_delete()
-{
- return 0;
-}
-
-static int test_rrset_add_rdata()
-{
- /* rdata add */
- int errors = 0;
- for (int i = 0; i < TEST_RRSETS; i++) {
- knot_dname_t *owner = knot_dname_new_from_str(
- test_rrsets[i].owner,
- strlen(test_rrsets[i].owner),
- NODE_ADDRESS);
- if (owner == NULL) {
- diag("Error creating owner domain name!");
- return 0;
- }
-
- knot_rrset_t *rrset = knot_rrset_new(owner,
- test_rrsets[i].type,
- test_rrsets[i].rclass,
- test_rrsets[i].ttl);
-
- knot_rrset_add_rdata(rrset, test_rrsets[i].rdata);
-
- errors += check_rrset(rrset, i, 1, 0, 0);
-
- knot_rrset_free(&rrset);
- knot_dname_free(&owner);
- }
-
- /* test whether adding works properly = keeps order of added elements */
-
- /*
- * Beware, this is dependent on the internal structure of rrset and
- * may change.
- */
-
- knot_rrset_t *rrset = knot_rrset_new(NULL, 0, 0, 0);
-
- knot_rdata_t *r;
-
- knot_rdata_item_t *item;
-
- static const char *test_strings[10] =
- { "-2", "9", "2", "10", "1", "5", "8", "4", "6", "7" };
-
- /* add items */
-
- for (int i = 0; i < 10; i++) {
- r = knot_rdata_new();
- item = malloc(sizeof(knot_rdata_item_t));
- item->raw_data = (uint16_t *)test_strings[i];
- //following statement creates a copy
- knot_rdata_set_items(r, item, 1);
- knot_rrset_add_rdata(rrset, r);
- free(item);
- }
-
- knot_rdata_t *tmp = rrset->rdata;
-
- /* check if order has been kept */
-
- int i = 0;
- while (tmp->next != rrset->rdata && !errors) {
- if (strcmp(test_strings[i], (char *)tmp->items[0].raw_data)) {
- diag("Adding RDATA error!, is %s should be %s",
- tmp->items[0].raw_data, test_strings[i]);
- errors++;
- }
- i++;
- tmp = tmp->next;
-
- }
-
- tmp = rrset->rdata;
-
- knot_rdata_t *next;
-
- while (tmp->next != rrset->rdata) {
- next = tmp->next;
- knot_rdata_free(&tmp);
- tmp = next;
- }
-
- knot_rdata_free(&tmp);
-
- knot_rrset_free(&rrset);
-
- return (errors == 0);
-}
-
-static int test_rrset_rrsigs()
-{
- int errors = 0;
-
- knot_rdata_item_t *item;
-
- knot_rdata_t *tmp;
-
- knot_dname_t *owner;
-
- knot_rrset_t *rrset;
-
- /* Gets rrsigs and checks, if signatures are the same */
-
- for (int i = 0; i < TEST_RRSETS; i++) {
- owner = knot_dname_new_from_str(test_rrsets[i].owner,
- strlen(test_rrsets[i].owner), NODE_ADDRESS);
- if (owner == NULL) {
- diag("Error creating owner domain name!");
- return 0;
- }
-
- rrset = knot_rrset_new(owner, test_rrsets[i].type,
- test_rrsets[i].rclass, test_rrsets[i].ttl);
-
- knot_rrset_add_rdata(rrset, test_rrsets[i].rdata);
-
- //owners are the same
-
- assert(TEST_RRSETS == TEST_RRSIGS);
-
- knot_rrset_t *rrsig = knot_rrset_new(owner,
- test_rrsigs[i].type,
- test_rrsigs[i].rclass,
- test_rrsigs[i].ttl);
-
- tmp = knot_rdata_new();
- item = malloc(sizeof(knot_rdata_item_t));
- /* signature is just a string,
- * should be sufficient for testing */
- item->raw_data = (uint16_t *)signature_strings[i];
- knot_rdata_set_items(tmp, item, 1);
- knot_rrset_add_rdata(rrsig, tmp);
-
- if (knot_rrset_set_rrsigs(rrset, rrsig)
- != 0) {
- diag("Could not set rrsig");
- errors++;
- }
- errors += check_rrset(rrset, i, 0, 0, 1);
- knot_rrset_free(&rrset);
- free(item);
- knot_rdata_free(&tmp);
- knot_rrset_free(&rrsig);
- }
- return (errors == 0);
-}
-
-static int test_rrset_merge()
-{
- knot_rrset_t *merger1;
- knot_rrset_t *merger2;
- knot_dname_t *owner1;
- knot_dname_t *owner2;
-
- int r;
-
- owner1 = knot_dname_new_from_str(test_rrsets[3].owner,
- strlen(test_rrsets[3].owner), NULL);
- merger1 = knot_rrset_new(owner1, test_rrsets[3].type,
- test_rrsets[3].rclass,
- test_rrsets[3].ttl);
-
- knot_rrset_add_rdata(merger1, test_rrsets[3].rdata);
-
- owner2 = knot_dname_new_from_str(test_rrsets[4].owner,
- strlen(test_rrsets[4].owner), NULL);
- merger2 = knot_rrset_new(owner2, test_rrsets[4].type,
- test_rrsets[4].rclass,
- test_rrsets[4].ttl);
-
- knot_rrset_add_rdata(merger2, test_rrsets[4].rdata);
-
-// knot_rrset_dump(merger1, 1);
-
- int ret = 0;
- if ((ret = knot_rrset_merge((void **)&merger1,
- (void **)&merger2)) != 0) {
- diag("Could not merge rrsets. (reason %d)", ret);
- return 0;
- }
-
-// knot_rrset_dump(merger1, 1);
-
- r = check_rrset(merger1, 5, 1, 1, 0);
-
- knot_rrset_free(&merger1);
- knot_rrset_free(&merger2);
-
- if (r) {
- diag("Merged rdata are wrongly set.");
- return 0;
- }
-
- return 1;
-}
-
-static int test_rrset_owner(knot_rrset_t **rrsets)
-{
- int errors = 0;
- for (int i = 0; i < TEST_RRSETS; i++) {
- char *dname_str =
- knot_dname_to_str(knot_rrset_owner(rrsets[i]));
- if (strcmp(dname_str, test_rrsets[i].owner)) {
- diag("Got wrong value for owner from rrset.");
- errors++;
- }
- free(dname_str);
- }
- return errors;
-}
-
-static int test_rrset_type(knot_rrset_t **rrsets)
-{
- int errors = 0;
- for (int i = 0; i < TEST_RRSETS; i++) {
- if (knot_rrset_type(rrsets[i]) != test_rrsets[i].type) {
- errors++;
- diag("Got wrong value for type from rrset.");
- }
- }
- return errors;
-}
-
-static int test_rrset_class(knot_rrset_t **rrsets)
-{
- int errors = 0;
- for (int i = 0; i < TEST_RRSETS; i++) {
- if (knot_rrset_class(rrsets[i]) != test_rrsets[i].rclass) {
- errors++;
- diag("Got wrong value for class from rrset.");
- }
- }
-
- return errors;
-}
-
-static int test_rrset_ttl(knot_rrset_t **rrsets)
-{
- int errors = 0;
- for (int i = 0; i < TEST_RRSETS; i++) {
- if (knot_rrset_ttl(rrsets[i]) != test_rrsets[i].ttl) {
- errors++;
- diag("Got wrong value for ttl from rrset.");
- }
- }
- return errors;
-}
-
-static int test_rrset_ret_rdata(knot_rrset_t **rrsets)
-{
- int errors = 0;
-
- knot_rrtype_descriptor_t *desc;
-
- for (int i = 0; i < TEST_RRSETS; i++) {
-
- desc = knot_rrtype_descriptor_by_type(rrsets[i]->type);
- assert(desc);
-
-// knot_rdata_dump(test_rrsets[i].rdata, 1);
- // knot_rdata_dump(rrsets[i]->rdata, 1);
-
- if (knot_rdata_compare(knot_rrset_rdata(rrsets[i]),
- test_rrsets[i].rdata,
- desc->wireformat)) {
- errors++;
- diag("Got wrong value for rdata from rrset.");
- }
- }
- return errors;
-}
-
-static int test_rrset_get_rdata(knot_rrset_t **rrsets)
-{
- int errors = 0;
-
- knot_rrtype_descriptor_t *desc;
-
- for (int i = 0; i < TEST_RRSETS; i++) {
- desc = knot_rrtype_descriptor_by_type(rrsets[i]->type);
- assert(desc);
- if (knot_rdata_compare(knot_rrset_get_rdata(rrsets[i]),
- test_rrsets[i].rdata,
- desc->wireformat)) {
- errors++;
- diag("Got wrong value for rdata from rrset. (Get)");
- }
- }
- return errors;
-}
-
-static int test_rrset_ret_rrsigs(knot_rrset_t **rrsets)
-{
- int errors = 0;
-
- for (int i = 0; i < TEST_RRSETS; i++) {
- /* TODO should I test the insides of structure as well? */
- if (knot_rrset_rrsigs(rrsets[i]) != test_rrsets[i].rrsigs) {
- errors++;
- diag("Got wrong value for rrsigs from rrset.");
- }
- }
- return errors;
-}
-
-static int test_rrset_getters(uint type)
-{
- int errors = 0;
-
- knot_rrset_t *rrsets[TEST_RRSETS];
-
- for (int i = 0; i < TEST_RRSETS; i++) {
- knot_dname_t *owner = knot_dname_new_from_str(
- test_rrsets[i].owner,
- strlen(test_rrsets[i].owner),
- NODE_ADDRESS);
- if (owner == NULL) {
- diag("Error creating owner domain name!");
- return 0;
- }
- rrsets[i] = knot_rrset_new(owner,
- test_rrsets[i].type,
- test_rrsets[i].rclass,
- test_rrsets[i].ttl);
-
- knot_rrset_add_rdata(rrsets[i], test_rrsets[i].rdata);
- }
-
- switch (type) {
- case 0: {
- errors += test_rrset_owner(rrsets);
- break;
- }
- case 1: {
- errors += test_rrset_type(rrsets);
- break;
- }
- case 2: {
- errors += test_rrset_class(rrsets);
- break;
- }
- case 3: {
- errors += test_rrset_ttl(rrsets);
- break;
- }
- case 4: {
- errors += test_rrset_ret_rdata(rrsets);
- break;
- }
- case 5: {
- errors += test_rrset_get_rdata(rrsets);
- break;
- }
- case 6: {
- errors += test_rrset_ret_rrsigs(rrsets);
- break;
- }
- } /* switch */
-
- for (int i = 0; i < TEST_RRSETS; i++) {
- knot_dname_free(&rrsets[i]->owner);
- knot_rrset_free(&rrsets[i]);
- }
-
-
- return (errors == 0);
-}
-
-static int test_rrset_deep_free()
-{
- /*!< \warning Cannot be run when some rdata are on stack! */
- int errors = 0;
-
- knot_rrset_t *tmp_rrset;
- knot_dname_t *owner;
- for (int i = 0; i < TEST_RRSETS; i++) {
- owner = knot_dname_new_from_str(
- test_rrsets[i].owner,
- strlen(test_rrsets[i].owner),
- NODE_ADDRESS);
- if (owner == NULL) {
- diag("Error creating owner domain name!");
- return 0;
- }
-
- tmp_rrset = knot_rrset_new(owner,
- test_rrsets[i].type,
- test_rrsets[i].rclass,
- test_rrsets[i].ttl);
-
- knot_rrset_add_rdata(tmp_rrset, test_rrsets[i].rdata);
-
- knot_rrset_deep_free(&tmp_rrset, 1, 1, 0);
-
- errors += (tmp_rrset != NULL);
- }
-
- return (errors == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-
-static const int KNOT_RRSET_TEST_COUNT = 13;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_rrset_tests_count(int argc, char *argv[])
-{
- return KNOT_RRSET_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_rrset_tests_run(int argc, char *argv[])
-{
- int res = 0,
- res_final = 1;
-
-/* for (int i = 0; i < 4; i++) {
- knot_rdata_dump(&RR_RDATA[i], 2, 1);
- printf("%p %p\n", &RR_RDATA[i], (&RR_RDATA)[i]->next);
- } */
-
- create_rdata();
-
- res = test_rrset_create();
- ok(res, "rrset: create");
- res_final *= res;
-
- skip(!res, 11);
-
- todo();
-
- ok(res = test_rrset_delete(), "rrset: delete");
- //res_final *= res;
-
- endtodo;
-
- ok(res = test_rrset_getters(0), "rrset: owner");
- res_final *= res;
-
- ok(res = test_rrset_getters(1), "rrset: type");
- res_final *= res;
-
- ok(res = test_rrset_getters(2), "rrset: class");
- res_final *= res;
-
- ok(res = test_rrset_getters(3), "rrset: ttl");
- res_final *= res;
-
- ok(res = test_rrset_getters(4), "rrset: rdata");
- res_final *= res;
-
- ok(res = test_rrset_getters(5), "rrset: get rdata");
- res_final *= res;
-
- ok(res = test_rrset_getters(6), "rrset: rrsigs");
- res_final *= res;
-
- ok(res = test_rrset_add_rdata(), "rrset: add_rdata");
- res_final *= res;
-
- ok(res = test_rrset_rrsigs(), "rrset: rrsigs manipulation");
- res_final *= res;
-
- ok(res = test_rrset_merge(), "rrset: rdata merging");
- res_final *= res;
-
- ok(res = test_rrset_deep_free(), "rrset: deep free");
- res_final *= res;
-
- endskip; /* !res_create */
-
- return res_final;
-}
diff --git a/src/tests/libknot/libknot/tsig_tests.c b/src/tests/libknot/libknot/tsig_tests.c
deleted file mode 100644
index 53c90aa..0000000
--- a/src/tests/libknot/libknot/tsig_tests.c
+++ /dev/null
@@ -1,686 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-#include <time.h>
-
-#include "libknot/rrset.h"
-#include "libknot/packet/response.h"
-#include "libknot/dname.h"
-#include "libknot/util/wire.h"
-#include "libknot/tsig-op.h"
-#include "libknot/common.h"
-#include "common/print.h"
-
-#include "tsig_tests.h"
-
-static int knot_tsig_tests_count(int argc, char *argv[]);
-static int knot_tsig_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api tsig_tests_api = {
- "DNS library - tsig", //! Unit name
- &knot_tsig_tests_count, //! Count scheduled tests
- &knot_tsig_tests_run //! Run scheduled tests
-};
-
-static const int KNOT_TSIG_TEST_COUNT = 6;
-
-static knot_rrset_t *create_dummy_tsig_rr()
-{
- knot_dname_t *tsig_owner =
- knot_dname_new_from_str("dummy.key.name.",
- strlen("dummy.key.name."), NULL);
- assert(tsig_owner);
-
- /* Create dummy TSIG rr. */
- knot_rrset_t *tsig_rr = knot_rrset_new(tsig_owner, KNOT_RRTYPE_TSIG,
- KNOT_CLASS_ANY, 0);
- assert(tsig_rr);
-
- knot_rdata_t *tsig_rdata = knot_rdata_new();
- assert(tsig_rr);
- /* Create TSIG items. */
- knot_rdata_item_t items[9];
-
- /*
- * I am not sure if 9 is the right count in our impl,
- * but it should work fine.
- */
- knot_rdata_set_items(tsig_rdata, items, 9);
- knot_dname_t *alg_name =
- knot_dname_new_from_str("hmac-md5.sig-alg.reg.int.",
- strlen("hmac-md5.sig-alg.reg.int."),
- NULL);
- assert(alg_name);
- tsig_rdata_set_alg_name(tsig_rr, alg_name);
-
- /* Get current time and save it to TSIG rr. */
- time_t current_time = time(NULL);
- tsig_rdata_set_time_signed(tsig_rr, current_time);
- tsig_rdata_set_fudge(tsig_rr, 300);
- tsig_rdata_set_orig_id(tsig_rr, 0);
- tsig_rdata_set_tsig_error(tsig_rr, 0);
- tsig_rdata_set_mac(tsig_rr, strlen("nonsensemac"),
- (uint8_t *)"nonsensemac");
-
- return tsig_rr;
-}
-
-static int test_knot_tsig_sign()
-{
- int errors = 0;
- /* Test bad arguments. */
- int lived = 0;
- lives_ok({
- int ret = knot_tsig_sign(NULL, NULL, 0, NULL, 0, NULL,
- NULL, NULL, 0, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign((uint8_t *)0x1, NULL, 0, NULL, 0, NULL,
- NULL, NULL, 0, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign((uint8_t *)0x1, (size_t *)0x1, 0, NULL,
- 0, NULL,
- NULL, NULL, 0, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign((uint8_t *)0x1, (size_t *)0x1, 0,
- (uint8_t *)0x1, 0, NULL,
- NULL, NULL, 0, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign((uint8_t *)0x12345678, (size_t *)0x1,
- 0,(uint8_t *)0x1, 0,(uint8_t *) 0x1,
- NULL, NULL, 0, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign((uint8_t *)0x12345678, (size_t *)0x1, 0,
- (uint8_t *)0x1, 0,(uint8_t *) 0x1,
- (size_t *)0x1, NULL, 0, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "");
-
- errors += !lived;
-
- if (errors) {
- diag("NULL tests crashed!");
- }
-
- /* Create some dummy variables. */
- /* One NS rrset. */
- knot_dname_t *ns_dname = knot_dname_new_from_str("test.cz.",
- strlen("test.cz."),
- NULL);
- assert(ns_dname);
- knot_rrset_t *ns_rrset = knot_rrset_new(ns_dname, KNOT_RRTYPE_NS,
- KNOT_CLASS_IN, 3600);
- assert(ns_rrset);
- knot_packet_t *packet = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
-
- /* Add rdata. */
- knot_rdata_t *ns_rdata = knot_rdata_new();
- assert(ns_rdata);
-
- knot_rdata_item_t items[1];
- items[0].dname = ns_dname;
-
- int ret = knot_rdata_set_items(ns_rdata, items, 1);
- assert(ret == KNOT_EOK);
- ret = knot_rrset_add_rdata(ns_rrset, ns_rdata);
- assert(ret == KNOT_EOK);
-
- knot_packet_set_max_size(packet, 2048);
-
- if ((ret = knot_response_add_rrset_answer(packet, ns_rrset,
- 0, 0, 0, 0)) != KNOT_EOK) {
- diag("Could not add rrset to packet!"
- " %s\n", knot_strerror(ret));
- /* No point in continuing. */
- return 0;
- }
-
- uint8_t *msg = NULL;
- size_t msg_len;
- ret = knot_packet_to_wire(packet, &msg, &msg_len);
- assert(ret == KNOT_EOK);
-
- size_t msg_copy_length = msg_len;
- uint8_t msg_copy[msg_len];
- memcpy(msg_copy, msg, msg_len);
-
- size_t msg_max_len = 1024;
- uint8_t request_mac[16];
- size_t request_mac_length = 0;
- uint8_t digest[512];
- size_t digest_len;
-
- knot_key_t key;
- key.algorithm = KNOT_TSIG_ALG_HMAC_MD5;
- key.name = knot_dname_new_from_str("test.",
- strlen("test."), NULL);
- key.secret = "abcdefgh";
- key.secret_size = strlen("abcdefgh");
-
- /* Test not enough space for wire. */
- ret = knot_tsig_sign(msg, &msg_len, msg_len + 1, request_mac,
- request_mac_length,
- digest, &digest_len, &key, 0, 0);
- if (ret != KNOT_ESPACE) {
- diag("knot_tsig_sign did not return error when given too"
- " litle space for wire!");
- errors++;
- }
-
- /* Test normal operation. */
- ret = knot_tsig_sign(msg, &msg_len, msg_max_len, request_mac,
- request_mac_length,
- digest, &digest_len, &key, 0, 0);
- if (ret != KNOT_EOK) {
- diag("knot_tsig_sign failed when given right arguments!");
- return 0;
- }
-
- /*
- * Now check that the initial wire remained the same.
- * (Except for arcount)
- */
-
- /* Read arcount. Should be 1. */
- if (knot_wire_get_arcount(msg) != 1) {
- diag("Signed wire did not have its arcount changed!");
- errors++;
- }
-
- knot_wire_set_arcount(msg, 0);
- /* Wire now should be identical. Compare with its pre-signing copy. */
- if (strncmp((char *)msg, (char *)msg_copy, msg_len) != 0) {
- hex_print((const char*)msg, msg_len);
- hex_print((const char*)msg_copy, msg_len);
- diag("knot_tsig_sign has changed the signed wire!");
- errors++;
- }
-
- /* Do exactly the same, but add the request_mac variable. */
- request_mac_length = 16;
- memcpy(msg, msg_copy, msg_copy_length);
- msg = msg_copy;
- ret = knot_tsig_sign(msg, &msg_len, msg_max_len, request_mac,
- request_mac_length,
- digest, &digest_len, &key, 0, 0);
- if (ret != KNOT_EOK) {
- diag("knot_tsig_sign failed when given right arguments "
- "(request mac set)!");
- return 0;
- }
-
- /* Read arcount. Should be 1. */
- if (knot_wire_get_arcount(msg) != 1) {
- diag("Signed wire did not have its arcount changed!");
- errors++;
- }
-
- knot_wire_set_arcount(msg, 0);
- /* Wire now should be identical. Compare with its pre-signing copy. */
- if (strncmp((char *)msg, (char *)msg_copy, msg_len) != 0) {
- hex_print((const char*)msg, msg_len);
- hex_print((const char*)msg_copy, msg_len);
- diag("knot_tsig_sign has changed the signed wire!");
- errors++;
- }
-
- /*
- * Check that the wire is correctly signed
- * using knot_tsig_server_check.
- */
-
- /* Create dummy tsig_rr. */
- knot_rrset_t *tsig_rr = create_dummy_tsig_rr();
- assert(tsig_rr);
-
- /* Set the created digest. */
- tsig_rdata_set_mac(tsig_rr, digest_len, digest);
-
- ret = knot_tsig_server_check(tsig_rr, msg, msg_len, &key);
- if (ret != KNOT_EOK) {
- diag("Signed wire did not pass check!");
- errors++;
- }
-
-// free(msg);
- return errors == 0;
-}
-
-static int test_knot_tsig_sign_next()
-{
- int errors = 0;
- /* Test bad arguments. */
- int lived = 0;
- lives_ok({
- int ret = knot_tsig_sign_next(NULL, NULL, 0, NULL, 0, NULL,
- NULL, NULL, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign_next((uint8_t *)0x1, NULL, 0, NULL, 0,
- NULL,
- NULL, NULL, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign_next((uint8_t *)0x1, (size_t *)0x1, 0,
- NULL, 0, NULL,
- NULL, NULL, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign_next((uint8_t *)0x1, (size_t *)0x1, 0,
- (uint8_t *)0x1, 0, NULL,
- NULL, NULL, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign_next((uint8_t *)0x12345678, (size_t *)0x1,
- 0,(uint8_t *)0x1, 0,(uint8_t *) 0x1,
- NULL, NULL, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_sign_next((uint8_t *)0x12345678, (size_t *)0x1,
- 0, (uint8_t *)0x1, 0,(uint8_t *) 0x1,
- (size_t *)0x1, NULL, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "");
-
- errors += !lived;
-
- if (errors) {
- diag("NULL tests crashed!");
- }
-
- /* Create some dummy variables. */
- uint8_t msg[2048]; /* Should be random. */
- size_t msg_len = 512;
- size_t msg_max_len = 2048;
- uint8_t *prev_digest = NULL;
- size_t prev_digest_len = 0;
- uint8_t digest[512];
- size_t digest_len = 512;
-
- knot_key_t key;
- key.algorithm = KNOT_TSIG_ALG_HMAC_MD5;
- key.name = knot_dname_new_from_str("test.",
- strlen("test."), NULL);
- key.secret = "abcdefgh";
- key.secret_size = strlen("abcdefgh");
-
- /* Test not enough space for wire. */
- int ret = knot_tsig_sign_next(msg, &msg_len, 513, prev_digest,
- prev_digest_len,
- digest, &digest_len, &key, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_ESPACE) {
- diag("knot_tsig_sign_next did not return error when "
- "given too litle space for wire!"
- " returned: %s", knot_strerror(ret));
- errors++;
- }
-
- digest_len = 512;
-
- /* Test normal operation. */
- ret = knot_tsig_sign_next(msg, &msg_len, msg_max_len, prev_digest,
- prev_digest_len,
- digest, &digest_len, &key, NULL, 0); /*! \todo FIX */
- if (ret != KNOT_EOK) {
- diag("knot_tsig_sign_next failed when given right arguments!"
- " returned: %s", knot_strerror(ret));
- errors++;
- }
-
- /*!< \todo test that the variables have changed and so on. */
-
- return errors == 0;
-}
-
-static int test_knot_tsig_server_check()
-{
- int errors = 0;
- /* Test bad arguments. */
- int lived = 0;
- lives_ok({
- int ret = knot_tsig_server_check(NULL, NULL, 0, NULL);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_server_check((knot_rrset_t *)0x1,
- (uint8_t *)0x1, 0,
- NULL);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "");
-
- errors += !lived;
-
- if (errors) {
- diag("NULL tests crashed!");
- }
-
- /* Create dummy TSIG rr. */
- knot_rrset_t *tsig_rr = create_dummy_tsig_rr();
- assert(tsig_rr);
-
-
- /* Create dummy key. */
- knot_key_t key;
- key.algorithm = KNOT_TSIG_ALG_HMAC_MD5;
- key.secret = "supersecretsecret";
- key.secret_size = strlen("supersecretsecret");
- /* Bleeding eyes, I know. */
- key.name = (knot_dname_t *)knot_rrset_owner(tsig_rr);
-
- /* Create dummy wire. */
- uint8_t wire[500];
- size_t wire_size = 500;
-
- /*!< \note
- * Since there are no meaningful data in the wire,
- * the function should fail.
- */
- int ret = knot_tsig_server_check(tsig_rr, wire, wire_size, &key);
- if (ret != KNOT_TSIG_EBADSIG) {
- diag("tsig_server_check did not return "
- "TSIG_EBADSIG when given random wire!"
- " returned: %s", knot_strerror(ret));
- errors++;
- }
-
- /* Set 0 time - the error should be TSIG_EBADTIME. */
- tsig_rdata_set_time_signed(tsig_rr, 0);
- ret = knot_tsig_server_check(tsig_rr, wire, wire_size, &key);
- if (ret != KNOT_TSIG_EBADTIME) {
- diag("tsig_server_check did not return TSIG_EBADTIME "
- "when given zero time!");
- errors++;
- }
-
- return errors == 0;
-}
-
-static int test_knot_tsig_client_check()
-{
- int errors = 0;
- /* Test bad arguments. */
- int lived = 0;
- lives_ok({
- int ret = knot_tsig_client_check(NULL, NULL, 0, NULL,
- 0, NULL, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_client_check((knot_rrset_t *)0x1, NULL, 0, NULL,
- 0, NULL, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_client_check((knot_rrset_t *)0x1,
- (uint8_t *)0x1, 0, NULL,
- 0, NULL, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_client_check((knot_rrset_t *)0x1,
- (uint8_t *)0x1, 0, NULL,
- 0, NULL, 0);
- if (ret != KNOT_EINVAL) {
- diag("NULL argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "");
-
- errors += !lived;
-
- if (errors) {
- diag("NULL tests crashed!");
- }
-
- knot_dname_t *tsig_owner =
- knot_dname_new_from_str("dummy.key.name.",
- strlen("dummy.key.name."), NULL);
- assert(tsig_owner);
- /* Create dummy key. */
- knot_key_t key;
- key.algorithm = KNOT_TSIG_ALG_HMAC_MD5;
- key.secret = "supersecretsecret";
- key.secret_size = strlen("supersecretsecret");
- key.name = tsig_owner;
-
- /* Create dummy TSIG rr. */
- knot_rrset_t *tsig_rr = knot_rrset_new(tsig_owner,
- KNOT_RRTYPE_TSIG,
- KNOT_CLASS_ANY, 0);
- assert(tsig_rr);
-
- knot_rdata_t *tsig_rdata = knot_rdata_new();
- assert(tsig_rr);
- /* Create TSIG items. */
- knot_rdata_item_t items[9];
-
- /*
- * I am not sure if 9 is the right count in our impl.,
- * but is should work fine.
- */
- knot_rdata_set_items(tsig_rdata, items, 9);
- knot_dname_t *alg_name =
- knot_dname_new_from_str("hmac-md5.sig-alg.reg.int.",
- strlen("hmac-md5.sig-alg.reg.int."),
- NULL);
- assert(alg_name);
- tsig_rdata_set_alg_name(tsig_rr, alg_name);
- /* Get current time and save it to TSIG rr. */
- time_t current_time = time(NULL);
- tsig_rdata_set_time_signed(tsig_rr, current_time);
- tsig_rdata_set_fudge(tsig_rr, 300);
- tsig_rdata_set_orig_id(tsig_rr, 0);
- tsig_rdata_set_tsig_error(tsig_rr, 0);
- tsig_rdata_set_mac(tsig_rr, strlen("nonsensemac"),
- (uint8_t *)"nonsensemac");
-
- /* Create dummy wire. */
- uint8_t wire[500];
- size_t wire_size = 500;
-
- /*!< \note
- * Since there are no meaningful data in the wire,
- * the function should fail.
- */
- int ret = knot_tsig_client_check(tsig_rr,
- wire, wire_size, NULL, 0, &key, 0);
- if (ret != KNOT_TSIG_EBADSIG) {
- diag("tsig_server_check did not return TSIG_EBADSIG when "
- "given random wire!");
- errors++;
- }
-
- /* Set 0 time - the error should be TSIG_EBADTIME. */
- tsig_rdata_set_time_signed(tsig_rr, 0);
- ret = knot_tsig_client_check(tsig_rr, wire, wire_size, NULL,
- 0, &key, 0);
- if (ret != KNOT_TSIG_EBADTIME) {
- diag("tsig_server_check did not return "
- "TSIG_EBADTIME when given zero time!");
- errors++;
- }
-
- return errors == 0;
-}
-
-static int test_knot_tsig_client_check_next()
-{
- /*!< \todo think of extra test cases. */
- return test_knot_tsig_client_check();
-}
-
-static int test_knot_tsig_test_tsig_add()
-{
- int errors = 0;
-
- /* Faulty arguments. */
- int lived = 0;
- lives_ok({
- int ret = knot_tsig_add(NULL, NULL, 0, 0, NULL);
- if (ret != KNOT_EINVAL) {
- diag("tsig_add did not return EINVAL "
- "when given NULL parameters.");
- errors++;
- }
- lived = 1;
-
- lived = 0;
- ret = knot_tsig_add((uint8_t *)0x1, NULL, 0, 0, NULL);
- if (ret != KNOT_EINVAL) {
- diag("tsig_add did not return EINVAL when "
- "given NULL parameters.");
- errors++;
- }
- lived = 1;
- }, "");
-
- errors += !lived;
-
- if (errors) {
- diag("NULL tests failed!");
- }
-
- size_t wire_size = 512;
- uint8_t wire[wire_size * 2];
-
- /*! \todo Fix */
- int ret = knot_tsig_add(wire, &wire_size, wire_size * 2, 0, NULL);
- if (ret != KNOT_EOK) {
- diag("tsig_add did not return EOK when given valid parameters."
- " returned: %s", knot_strerror(ret));
- errors++;
- }
-
- return errors == 0;
-}
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_tsig_tests_count(int argc, char *argv[])
-{
- return KNOT_TSIG_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_tsig_tests_run(int argc, char *argv[])
-{
- int res_final = 0;
- int res = 0;
-
- ok(res = test_knot_tsig_sign(), "tsig: sign");
- res_final *= res;
- ok(res = test_knot_tsig_sign_next(), "tsig: sign next");
- res_final *= res;
- ok(res = test_knot_tsig_server_check(), "tsig: server check");
- res_final *= res;
- ok(res = test_knot_tsig_client_check(), "tsig: client check");
- res_final *= res;
- ok(res = test_knot_tsig_client_check_next(), "tsig: client check next");
- res_final *= res;
- ok(res = test_knot_tsig_test_tsig_add(), "tsig: tsig add");
- res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/libknot/tsig_tests.h b/src/tests/libknot/libknot/tsig_tests.h
deleted file mode 100644
index 8ea15f6..0000000
--- a/src/tests/libknot/libknot/tsig_tests.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef TSIH_TESTS_H
-#define TSIH_TESTS_H
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api tsig_tests_api;
-
-#endif // TSIH_TESTS_H
diff --git a/src/tests/libknot/libknot/zone_tests.c b/src/tests/libknot/libknot/zone_tests.c
deleted file mode 100644
index f348ebf..0000000
--- a/src/tests/libknot/libknot/zone_tests.c
+++ /dev/null
@@ -1,852 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "tests/libknot/libknot/zone_tests.h"
-#include "libknot/common.h"
-#include "libknot/zone/dname-table.h"
-#include "libknot/zone/zone.h"
-#include "libknot/zone/node.h"
-
-static int knot_zone_tests_count(int argc, char *argv[]);
-static int knot_zone_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api zone_tests_api = {
- "DNS library - zone", //! Unit name
- &knot_zone_tests_count, //! Count scheduled tests
- &knot_zone_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-enum { TEST_NODES_GOOD = 7, TEST_NODES_BAD = 1, TRAVERSAL_TYPES = 3};
-
-struct zone_test_node {
- knot_dname_t owner;
- knot_node_t *parent;
-};
-
-static struct zone_test_node test_apex =
-{{{}, (uint8_t *)"\3com\0", (uint8_t *)"\x0", NULL, 0, 5, 1}, (knot_node_t *)NULL};
-
-static struct zone_test_node test_nodes_bad[TEST_NODES_BAD] = {
- {{{},(uint8_t *)"\5other\6domain\0", (uint8_t *)"\x0\x6", NULL, 0, 14, 2},
- (knot_node_t *)NULL}
-};
-
-static struct zone_test_node test_nodes_good[TEST_NODES_GOOD] = {
- {{{}, (uint8_t *)"\7example\3com\0", (uint8_t *)"\x0\x8", NULL, 0, 13, 2},
- (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\3www\7example\3com\0", (uint8_t *)"\x0\x4\xC", NULL, 0, 17, 3},
- (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\7another\6domain\3com\0", (uint8_t *)"\x0\x8\xF", NULL, 0, 20, 3},
- (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\5mail1\7example\3com\0", (uint8_t *)"\x0\x6\xE", NULL, 0, 19, 3},
- (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\5mail2\7example\3com\0", (uint8_t *)"\x0\x6\xE", NULL, 0, 19, 3},
- (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\3smb\7example\3com\0", (uint8_t *)"\x0\x4\xC", NULL, 0, 17, 3},
- (knot_node_t *)NULL},
- {{{}, (uint8_t *)"\4smtp\7example\3com\0", (uint8_t *)"\x0\x5\xD", NULL, 0, 18, 3},
- (knot_node_t *)NULL},
-};
-
-static int test_zone_check_node(const knot_node_t *node,
- const struct zone_test_node *test_node,
- int test_parent)
-{
- return (node->owner == &test_node->owner) &&
- ((test_parent) ? node->parent == test_node->parent : 1);
-}
-
-static int test_zone_create(knot_zone_contents_t **zone)
-{
-// knot_dname_t *dname = knot_dname_new_from_wire(
-// test_apex.owner.name, test_apex.owner.size, NULL);
-// assert(dname);
-
- knot_node_t *node = knot_node_new(&test_apex.owner,
- test_apex.parent, 0);
- if (node == NULL) {
- diag("zone: Could not create zone apex.");
- return 0;
- }
-
- *zone = knot_zone_contents_new(node, 0, 0, NULL);
-
- if ((*zone) == NULL) {
- diag("zone: Failed to create zone.");
- knot_node_free(&node);
- return 0;
- }
-
- if ((*zone)->apex != node) {
- diag("zone: Zone apex not set right.");
- knot_node_free(&node);
- return 0;
- }
-
- return 1;
-}
-
-static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
-{
- /*
- * NSEC3 nodes are de facto identical to normal nodes, so there is no
- * need for separate tests. The only difference is where are they stored
- * in the zone structure.
- */
-
- int errors = 0;
- int res = 0;
-
- //note("Good nodes");
-
- for (int i = 0; i < TEST_NODES_GOOD; ++i) {
- knot_node_t *node = knot_node_new(&test_nodes_good[i].owner,
- test_nodes_good[i].parent, 0);
- if (node == NULL) {
- diag("zone: Could not create node.");
- return 0;
- }
-
- if ((res = ((nsec3) ? knot_zone_contents_add_nsec3_node(zone, node, 0, 0, 0)
- : knot_zone_contents_add_node(zone, node, 0, 0, 0))) != 0) {
- diag("zone: Failed to insert node into zone (returned"
- " %d).", res);
- knot_node_free(&node);
- ++errors;
- }
- /* TODO check values in the node as well */
- }
-
- //note("Bad nodes");
-
- for (int i = 0; i < TEST_NODES_BAD; ++i) {
- knot_node_t *node = knot_node_new(&test_nodes_bad[i].owner,
- test_nodes_bad[i].parent, 0);
- if (node == NULL) {
- diag("zone: Could not create node.");
- return 0;
- }
-
- if ((res = ((nsec3) ? knot_zone_contents_add_nsec3_node(zone, node, 0, 0, 0)
- : knot_zone_contents_add_node(zone, node, 0, 0, 0))) !=
- KNOT_EBADZONE) {
- diag("zone: Inserting wrong node did not result in"
- "proper return value (%d instead of %d).", res,
- KNOT_EBADZONE);
- ++errors;
- }
- knot_node_free(&node);
- }
-
- //note("NULL zone");
-
- note("Inserting into NULL zone...\n");
-
- knot_node_t *node = knot_node_new(&test_nodes_good[0].owner,
- test_nodes_good[0].parent, 0);
- if (node == NULL) {
- diag("zone: Could not create node.");
- return 0;
- }
-
- if ((res = ((nsec3) ? knot_zone_contents_add_nsec3_node(NULL, node, 0, 0, 0)
- : knot_zone_contents_add_node(NULL, node, 0, 0, 0))) != KNOT_EINVAL) {
- diag("zone: Inserting node to NULL zone did not result in"
- "proper return value (%d instead of %d)", res,
- KNOT_EINVAL);
- ++errors;
- }
-
- knot_node_free(&node);
-
- //note("NULL node");
- note("Inserting NULL node...\n");
-
- if ((res = ((nsec3) ? knot_zone_contents_add_nsec3_node(zone, NULL, 0, 0, 0)
- : knot_zone_contents_add_node(zone, NULL, 0, 0, 0))) != KNOT_EINVAL) {
- diag("zone: Inserting NULL node to zone did not result in"
- "proper return value (%d instead of %d)", res,
- KNOT_EINVAL);
- ++errors;
- }
-
- if (!nsec3) {
- //note("Inserting Apex again...\n");
-
- node = knot_node_new(&test_apex.owner, test_apex.parent, 0);
- if (node == NULL) {
- diag("zone: Could not create node.");
- return 0;
- }
-
- //note("Apex again");
-
- if ((res = knot_zone_contents_add_node(zone, node, 0, 0, 0)) !=
- KNOT_EBADZONE) {
- diag("zone: Inserting zone apex again did not result in"
- "proper return value (%d instead of -2)",
- KNOT_EBADZONE);
- ++errors;
- }
-
- knot_node_free(&node);
- }
-
- // check if all nodes are inserted
- //int nodes = 0;
- if (!nsec3
- && !test_zone_check_node(knot_zone_contents_apex(zone), &test_apex, !nsec3)) {
- diag("zone: Apex of zone not right.");
-// diag("Apex owner: %s (%p), apex parent: %p\n",
-// knot_dname_to_str(knot_zone_apex(zone)->owner),
-// knot_zone_apex(zone)->owner,
-// knot_zone_apex(zone)->parent);
-// diag("Should be: owner: %s (%p), parent: %p\n",
-// knot_dname_to_str(&test_apex.owner),
-// &test_apex.owner,
-// test_apex.parent);
- ++errors;
- }
- //++nodes;
- for (int i = 0; i < TEST_NODES_GOOD; ++i) {
- const knot_node_t *n = ((nsec3) ? knot_zone_contents_find_nsec3_node(
- zone, &test_nodes_good[i].owner) :
- knot_zone_contents_find_node(zone, &test_nodes_good[i].owner));
- if (n == NULL) {
- diag("zone: Missing node with owner %s",
- test_nodes_good[i].owner.name);
- ++errors;
- continue;
- }
-
- if (!test_zone_check_node(n, &test_nodes_good[i], !nsec3)) {
- diag("zone: Node does not match: owner: %s (should be "
- "%s), parent: %p (should be %p)",
- n->owner->name, test_nodes_good[i].owner.name,
- n->parent, test_nodes_good[i].parent);
- ++errors;
- }
- //++nodes;
- }
-
- //note("zone: %d nodes in the zone (including apex)", nodes);
-
- return (errors == 0);
-}
-
-static int test_zone_get_node(knot_zone_contents_t *zone, int nsec3)
-{
- int errors = 0;
-
- for (int i = 0; i < TEST_NODES_GOOD; ++i) {
- if (((nsec3) ? knot_zone_contents_get_nsec3_node(
- zone, &test_nodes_good[i].owner)
- : knot_zone_contents_get_node(zone, &test_nodes_good[i].owner))
- == NULL) {
- diag("zone: Node (%s) not found in zone.",
- (char *)test_nodes_good[i].owner.name);
- ++errors;
- }
- }
-
- for (int i = 0; i < TEST_NODES_BAD; ++i) {
- if (((nsec3) ? knot_zone_contents_get_nsec3_node(
- zone, &test_nodes_bad[i].owner)
- : knot_zone_contents_get_node(zone, &test_nodes_bad[i].owner))
- != NULL) {
- diag("zone: Node (%s) found in zone even if it should"
- "not be there.",
- (char *)test_nodes_bad[i].owner.name);
- ++errors;
- }
- }
-
- if (((nsec3)
- ? knot_zone_contents_get_nsec3_node(NULL, &test_nodes_good[0].owner)
- : knot_zone_contents_get_node(NULL, &test_nodes_good[0].owner)) != NULL) {
- diag("zone: Getting node from NULL zone did not result in"
- "proper return value (NULL)");
- ++errors;
- }
-
- if (((nsec3) ? knot_zone_contents_get_nsec3_node(zone, NULL)
- : knot_zone_contents_get_node(zone, NULL)) != NULL) {
- diag("zone: Getting node with NULL owner from zone did not "
- "result in proper return value (NULL)");
- ++errors;
- }
-
- if (!nsec3 && knot_zone_contents_get_node(zone, &test_apex.owner) == NULL) {
- diag("zone: Getting zone apex from the zone failed");
- ++errors;
- }
-
- return (errors == 0);
-}
-
-static int test_zone_find_node(knot_zone_contents_t *zone, int nsec3)
-{
- int errors = 0;
-
- for (int i = 0; i < TEST_NODES_GOOD; ++i) {
- if (((nsec3) ? knot_zone_contents_find_nsec3_node(
- zone, &test_nodes_good[i].owner)
- : knot_zone_contents_find_node(zone, &test_nodes_good[i].owner))
- == NULL) {
- diag("zone: Node (%s) not found in zone.",
- (char *)test_nodes_good[i].owner.name);
- ++errors;
- }
- }
-
- for (int i = 0; i < TEST_NODES_BAD; ++i) {
- if (((nsec3) ? knot_zone_contents_find_nsec3_node(
- zone, &test_nodes_bad[i].owner)
- : knot_zone_contents_find_node(zone, &test_nodes_bad[i].owner))
- != NULL) {
- diag("zone: Node (%s) found in zone even if it should"
- "not be there.",
- (char *)test_nodes_bad[i].owner.name);
- ++errors;
- }
- }
-
- if (((nsec3)
- ? knot_zone_contents_find_nsec3_node(NULL, &test_nodes_good[0].owner)
- : knot_zone_contents_find_node(NULL, &test_nodes_good[0].owner)) != NULL) {
- diag("zone: Finding node from NULL zone did not result in"
- "proper return value (NULL)");
- ++errors;
- }
-
- if (((nsec3) ? knot_zone_contents_find_nsec3_node(zone, NULL)
- : knot_zone_contents_find_node(zone, NULL)) != NULL) {
- diag("zone: Finding node with NULL owner from zone did not "
- "result in proper return value (NULL)");
- ++errors;
- }
-
- if (!nsec3 && knot_zone_contents_find_node(zone, &test_apex.owner) == NULL) {
- diag("zone: Finding zone apex from the zone failed");
- ++errors;
- }
-
- return (errors == 0);
-}
-
-//static void test_zone_destroy_node_from_tree(knot_node_t *node,
-// void *data)
-//{
-// UNUSED(data);
-// knot_node_free(&node, 0);
-//}
-
-/* explained below */
-static size_t node_index = 0;
-
-/*! \brief
- * This function will overwrite parent field in node structure -
- * we don't (and can't, with current structures) use it in these tests anyway.
- * Since zone structure itself has no count field, only option known to me
- * is (sadly) to use a global variable.
- */
-static void tmp_apply_function(knot_node_t *node, void *data)
-{
- node->parent = (knot_node_t *)node_index;
- node_index++;
-}
-
-/* \note Since I am unaware of a way how to get a return value from traversal
- * functions, I will use (hopefully for the last time here) global variable
- */
-
-static int compare_ok = 1;
-
-static void tmp_compare_function(knot_node_t *node, void *data)
-{
- /* node_index will start set to zero */
- if (node->parent != (knot_node_t *)node_index) {
- compare_ok = 0;
- return;
- } else if (!compare_ok) {
- diag("Traversal function has partially set values right");
- }
- node->parent = NULL;
- node_index++;
-}
-
-static int test_zone_tree_apply(knot_zone_contents_t *zone,
- int type, int nsec3)
-{
-
- assert(node_index == 0);
- assert(compare_ok == 1);
-
- int (*traversal_func)(knot_zone_contents_t *zone,
- void (*function)(knot_node_t *node,
- void *data),
- void *data);
-
- switch (type) {
- case 0: {
- if (nsec3) {
- traversal_func =
- &knot_zone_contents_nsec3_apply_postorder;
- diag("Testing postorder traversal");
- } else {
- traversal_func =
- &knot_zone_contents_tree_apply_postorder;
- diag("Testing postorder traversal - NSEC3");
- }
- break;
- }
- case 1: {
- if (nsec3) {
- traversal_func =
- &knot_zone_contents_nsec3_apply_inorder;
- diag("Testing inorder traversal");
- } else {
- traversal_func =
- &knot_zone_contents_tree_apply_inorder;
- diag("Testing inorder traversal - NSEC3");
- }
- break;
- }
- case 2: {
- if (nsec3) {
- traversal_func =
- &knot_zone_contents_nsec3_apply_inorder_reverse;
- diag("Testing inorder reverse traversal");
- } else {
- traversal_func =
- &knot_zone_contents_tree_apply_inorder_reverse;
- diag("Testing inorder reverse "
- "traversal - NSEC3");
- }
- break;
- }
- default: {
- diag("Unknown traversal function type");
- return 0;
- }
- }
-
- /*
- * This will iterate through tree and set node->parent field values
- * from 0 to number of nodes.
- */
-
- traversal_func(zone, &tmp_apply_function, NULL);
-
- node_index = 0;
-
- /*
- * This will check whether the values were set accordingly.
- */
-
- traversal_func(zone, &tmp_compare_function, NULL);
-
- int ret = compare_ok;
-
- compare_ok = 1;
- node_index = 0;
-
- return (ret);
-}
-
-/* Tests all kinds of zone traversals, explainded above */
-static int test_zone_traversals(knot_zone_contents_t *zone)
-{
- for (int i = 0; i < TRAVERSAL_TYPES; i++) {
- for (int j = 0; j < 2; j++) {
- if (!test_zone_tree_apply(zone, i, j)) {
- return 0;
- }
- }
- }
- return 1;
-}
-
-struct zone_test_param {
- /* Times 2 so that we don't have to mess with mallocs. */
- knot_node_t *knot_node_array[TEST_NODES_GOOD * 5];
- knot_dname_t *table_node_array[TEST_NODES_GOOD * 5];
- size_t count;
-};
-
-static void tree_node_to_array(knot_node_t *node, void *data)
-{
- struct zone_test_param *param = (struct zone_test_param *)data;
- param->knot_node_array[param->count++] = node;
-}
-
-static void tree_dname_node_to_array(knot_dname_t *node,
- void *data)
-{
- struct zone_test_param *param = (struct zone_test_param *)data;
- param->table_node_array[param->count++] = node;
-}
-
-extern int compare_wires_simple(uint8_t *w1, uint8_t *w2, uint count);
-static int test_zone_shallow_copy()
-{
- int errors = 0;
- int lived = 0;
- knot_dname_t *apex_dname =
- knot_dname_new_from_str("a.ns.nic.cz.",
- strlen("a.ns.nic.cz"), NULL);
- assert(apex_dname);
- knot_node_t *apex_node =
- knot_node_new(apex_dname, NULL, 0);
- assert(apex_node);
- lives_ok({
- if (knot_zone_contents_shallow_copy(NULL, NULL) != KNOT_EINVAL) {
- diag("Calling zone_shallow_copy with NULL "
- "arguments did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- lived = 0;
- knot_zone_contents_t *zone = knot_zone_contents_new(apex_node,
- 0, 1, 0);
- if (knot_zone_contents_shallow_copy(zone, NULL) != KNOT_EINVAL) {
- diag("Calling zone_shallow_copy with NULL destination "
- "zone argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_contents_shallow_copy(NULL, &zone) != KNOT_EINVAL) {
- diag("Calling zone_shallow_copy with NULL source "
- "zone argument did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_contents_shallow_copy(zone, &zone) != KNOT_EINVAL) {
- diag("Calling zone_shallow_copy with identical source "
- "and destination zone did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- knot_zone_contents_free(&zone);
- }, "zone: shallow copy NULL tests");
- errors += lived != 1;
-
- knot_dname_t *d = knot_dname_deep_copy(&test_nodes_good[0].owner);
- if (d == NULL) {
- return 0;
- }
- knot_node_t *n = knot_node_new(d, NULL, 0);
-
- /* example.com. */
-// knot_zone_t *from_zone =
-// knot_zone_new(knot_node_new(&test_nodes_good[0].owner,
-// test_nodes_good[0].parent, 0), 10, 1);
- knot_zone_t *from_zone = knot_zone_new(n, 10, 1);
- knot_zone_contents_t *from = knot_zone_get_contents(from_zone);
-
- /* Add nodes to zone. */
- for (int i = 1; i < TEST_NODES_GOOD; ++i) {
- knot_dname_t *d = knot_dname_deep_copy(&test_nodes_good[i].owner);
- if (d == NULL) {
- return 0;
- }
- knot_node_t *node = knot_node_new(d, test_nodes_good[i].parent,
- 0);
- if (node == NULL) {
- diag("zone: Could not create node.");
- return 0;
- }
-
- if (knot_zone_contents_add_node(from, node, 1, 1, 1) != KNOT_EOK) {
- diag("zone: Could not add node. %s",
- knot_dname_to_str(node->owner));
-// return 0;
- }
- }
-
- /* Make a copy of zone */
- knot_zone_contents_t *to = NULL;
- int ret = 0;
- if ((ret = knot_zone_contents_shallow_copy(from, &to) != KNOT_EOK)) {
- diag("Could not copy zone! %s", knot_strerror(ret));
- return 0;
- }
-
- assert(to);
-
- /* Compare non-tree parts of the zone. */
-// if (from->data != to->data) {
-// diag("Zone data field wrong after shallow copy!");
-// errors++;
-// }
-
-// if (from->dtor != to->dtor) {
-// diag("Zone data destructor field wrong after shallow copy!");
-// errors++;
-// }
-
- if (from->node_count != to->node_count) {
- diag("Zone node count data field wrong after shallow copy!");
- errors++;
- }
-
-// if (from->version != to->version) {
-// diag("Zone version data field wrong after shallow copy!");
-// errors++;
-// }
-
- if (from->apex != to->apex) {
- diag("Zone apex differ after shallow copy!");
- }
-
- if (compare_wires_simple((uint8_t *)(&from->nsec3_params),
- (uint8_t *)(&to->nsec3_params),
- sizeof(from->nsec3_params)) != 0) {
- diag("Nsec3_params data field wrong after shallow copy!");
- errors++;
- }
-
- if (from->nodes == to->nodes) {
- diag("Copied zones have identical trees!");
- errors++;
- }
-
- if (from->nsec3_nodes == to->nsec3_nodes) {
- diag("Copied zones have identical trees!");
- errors++;
- }
-
- /* Compare nodes, convert tree to array then compare those arrays. */
- struct zone_test_param param1;
- memset(&param1, 0, sizeof(struct zone_test_param));
-
- knot_zone_contents_tree_apply_inorder(from, tree_node_to_array,
- (void *)&param1);
-
- struct zone_test_param param2;
- memset(&param2, 0, sizeof(struct zone_test_param));
-
- knot_zone_contents_tree_apply_inorder(to, tree_node_to_array,
- (void *)&param2);
-
- if (param1.count != param2.count) {
- diag("wrong tree");
- return 0;
- }
-
- for (int i = 0; i < param1.count; i++) {
- if (param1.knot_node_array[i] !=
- param2.knot_node_array[i]) {
- diag("wrong tree");
- return 0;
- }
- }
-
- param1.count = 0;
- knot_dname_table_tree_inorder_apply(from->dname_table,
- tree_dname_node_to_array,
- (void *)&param1);
-
- param2.count = 0;
- knot_dname_table_tree_inorder_apply(to->dname_table,
- tree_dname_node_to_array,
- (void *)&param2);
-
- if (param1.count != param2.count) {
- diag("wrong table count");
- return 0;
- }
-
- for (int i = 0; i < param1.count; i++) {
- if (param1.table_node_array[i] != param2.table_node_array[i]) {
- diag("wrong table nodes");
- errors++;
- }
- }
-
-#ifdef USE_HASH_TABLE
- if (from->table) {
- if (from->table == to->table) {
- diag("hash tables after shallow copy are identical!");
- return 0;
- }
- uint i;
- if (hashsize(from->table->table_size_exp) !=
- hashsize(to->table->table_size_exp)) {
- diag("hash tables after shallow copy error!");
- return 0;
- }
-
- if (from->table->table_count != to->table->table_count) {
- diag("hash tables after shallow copy error!");
- return 0;
- }
-
- for (uint t = 0; t < from->table->table_count; ++t) {
- for (i = 0; i <
- hashsize(from->table->table_size_exp); i++) {
- if (from->table->tables[t][i] == NULL) {
- if (to->table->tables[t][i] != NULL) {
- diag("hash table item error");
- }
- continue;
- }
- if ((from->table->tables[t])[i]->key_length !=
- (to->table->tables[t])[i]->key_length) {
- diag("hash table key lengths error!");
- return 0;
- }
- if ((from->table->tables[t])[i]->key !=
- (to->table->tables[t])[i]->key) {
- diag("hash table key error!");
- return 0;
- }
- if ((from->table->tables[t])[i]->value !=
- (to->table->tables[t])[i]->value) {
- diag("hash table value error!");
- return 0;
- }
- }
- }
-
- ck_stash_item_t *item1 = from->table->stash;
- ck_stash_item_t *item2 = to->table->stash;
- while (item1 != NULL && item2 != NULL) {
- if (item1->item->key_length !=
- item2->item->key_length) {
- diag("hash stash key length error!");
- return 0;
- }
- if (item1->item->key != item2->item->key) {
- diag("hash stash key error!");
- return 0;
- }
- if (item1->item->value != item2->item->value) {
- diag("hash stash value error!");
- return 0;
- }
-
- item1 = item1->next;
- item2 = item2->next;
- }
- } else {
- if (to->table) {
- diag("Hash table is not set to NULL "
- "after shallow copy!");
- errors++;
- }
- }
-#endif
-
-// knot_zone_deep_free(&from_zone, 0);
-// knot_zone_contents_free(&to);
- return (errors == 0);
-
-}
-
-//static int test_zone_free(knot_zone_t **zone)
-//{
-// knot_zone_tree_apply_postorder(*zone,
-// test_zone_destroy_node_from_tree,
-// NULL);
-// knot_zone_nsec3_apply_postorder(*zone,
-// test_zone_destroy_node_from_tree,
-// NULL);
-// knot_zone_free(zone);
-// return (*zone == NULL);
-//}
-
-static const int KNOT_ZONE_TEST_COUNT = 10;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_zone_tests_count(int argc, char *argv[])
-{
- return KNOT_ZONE_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_zone_tests_run(int argc, char *argv[])
-{
- int res = 0,
- res_final = 0;
-
- knot_zone_contents_t *zone = NULL;
-
- ok((res = test_zone_create(&zone)), "zone: create");
- res_final *= res;
-
- skip(!res, 6);
-
- ok((res = test_zone_add_node(zone, 0)), "zone: add node");
- res_final *= res;
-
- skip(!res, 2);
-
- ok((res = test_zone_get_node(zone, 0)), "zone: get node");
- res_final *= res;
-
- skip(!res, 1);
-
- ok((res = test_zone_find_node(zone, 0)), "zone: find node");
- res_final *= res;
-
- endskip; // get node failed
-
- endskip; // add node failed
-
- ok((res = test_zone_add_node(zone, 1)), "zone: add nsec3 node");
- res_final *= res;
-
- skip(!res, 2);
-
- ok((res = test_zone_get_node(zone, 1)), "zone: get nsec3 node");
- res_final *= res;
-
- skip(!res, 1);
-
- ok((res = test_zone_find_node(zone, 1)), "zone: find nsec3 node");
- res_final *= res;
-
- endskip; // get nsec3 node failed
-
- endskip; // add nsec3 node failed
-
- ok(res = test_zone_traversals(zone), "zone: traversals");
- res_final *= res;
-
- ok((res = test_zone_shallow_copy()), "zone: shallow copy");
- res_final *= res;
-
-// ok((res = test_zone_free(&zone)), "zone: free");
-// res_final *= res;
-
- endskip; // create failed
-
- return res_final;
-}
diff --git a/src/tests/libknot/libknot/zone_tree_tests.c b/src/tests/libknot/libknot/zone_tree_tests.c
deleted file mode 100644
index 80fa8f4..0000000
--- a/src/tests/libknot/libknot/zone_tree_tests.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/* Copyright (C) 2011 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 <string.h>
-#include <assert.h>
-
-#include "tests/libknot/libknot/zone_tree_tests.h"
-#include "libknot/zone/zone-tree.h"
-#include "libknot/common.h"
-
-static int knot_zone_tree_tests_count(int argc, char *argv[]);
-static int knot_zone_tree_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api zone_tree_tests_api = {
- "DNS library - zone tree", //! Unit name
- &knot_zone_tree_tests_count, //! Count scheduled tests
- &knot_zone_tree_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-static int test_tree_init()
-{
- int errors = 0;
- int lived = 0;
-
- lives_ok({
- if (knot_zone_tree_init(NULL) != KNOT_EINVAL) {
- diag("Calling knot_zone_tree_init with NULL "
- "tree did not return KNOT_EINVAL!");
- errors++;
- }
- lived = 1;
- }, "zone tree: init NULL tests");
- errors += lived != 1;
-
- return (errors == 0);
-}
-
-static int test_tree_insert()
-{
- int errors = 0;
- int lived = 0;
-
- knot_zone_tree_t *tree = malloc(sizeof(knot_zone_tree_t));
- assert(tree);
- knot_zone_tree_init(tree);
- knot_node_t *node =
- knot_node_new(knot_dname_new_from_str("a.ns.nic.cz.",
- strlen("a.ns.nic.cz."),
- NULL),
- NULL, 0);
- assert(node);
-
- lives_ok({
- if (knot_zone_tree_insert(NULL, NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_insert(tree, NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_insert(NULL, node) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- }, "zone tree: insert NULL tests");
- if (errors) {
- diag("Zone tree insert did not return KNOT_EINVAL "
- "when given wrong arguments");
- }
- errors += lived != 1;
-
- if (knot_zone_tree_insert(tree, node) != KNOT_EOK) {
- diag("Calling zone tree insert with valid arguments "
- "did not return KNOT_EOK");
- errors++;
- }
-
- /* Sorting will be tested in traversal functions. */
- return (errors == 0);
-}
-
-static int test_tree_finding()
-{
- int errors = 0;
- int lived = 0;
-
- knot_zone_tree_t *tree = malloc(sizeof(knot_zone_tree_t));
- assert(tree);
- knot_zone_tree_init(tree);
- const knot_node_t *node =
- knot_node_new(knot_dname_new_from_str("a.ns.nic.cz.",
- strlen("a.ns.nic.cz."),
- NULL),
- NULL, 0);
- assert(node);
-
- lives_ok({
- if (knot_zone_tree_find(NULL, NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_find(tree, NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_find(tree, node->owner,
- NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- const knot_node_t *found_node = NULL;
- lived = 0;
- if (knot_zone_tree_find(NULL, node->owner,
- &found_node) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_find(tree, NULL,
- &found_node) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- }, "zone tree: find NULL tests");
- if (errors) {
- diag("Zone tree find did not return KNOT_EINVAL "
- "when given wrong arguments");
- }
-
- errors += lived != 1;
-
- /* Insert node */
- assert(knot_zone_tree_insert(tree, (knot_node_t *)node) == KNOT_EOK);
-
- knot_node_t *found_node = NULL;
- if (knot_zone_tree_find(tree, node->owner,
- (const knot_node_t **)&found_node) !=
- KNOT_EOK) {
- diag("Calling zone tree find with valid arguments did "
- "not return KNOT_EOK");
- errors++;
- }
-
- if (found_node != node) {
- diag("Zone tree find did not return right node");
- errors++;
- }
-
- if (knot_zone_tree_get(tree, node->owner, &found_node) !=
- KNOT_EOK) {
- diag("Calling zone tree get with valid arguments did "
- "not return KNOT_EOK");
- errors++;
- }
-
- if (found_node != node) {
- diag("Zone tree get did not return right node");
- errors++;
- }
-
- /* Try to search for node not in tree. */
- knot_dname_t *alien_dname =
- knot_dname_new_from_str("this.name.is.not.in.the.tree.",
- strlen("this.name.is.not.in.the.tree."),
- NULL);
-
- if (knot_zone_tree_find(tree, alien_dname,
- (const knot_node_t **)&found_node) !=
- KNOT_EOK) {
- diag("Calling zone tree find with valid arguments did "
- "not return KNOT_EOK");
- errors++;
- }
-
- if (found_node != NULL) {
- diag("Zone tree find returned node that was not in the tree!");
- errors++;
- }
-
- if (knot_zone_tree_get(tree, alien_dname, &found_node) !=
- KNOT_EOK) {
- diag("Calling zone tree get with valid arguments did "
- "not return KNOT_EOK");
- errors++;
- }
-
- if (found_node != NULL) {
- diag("Zone tree get returned node that was not in the tree!");
- errors++;
- }
-
- return (errors == 0);
-}
-
-static int test_tree_finding_less_or_equal()
-{
- diag("Issue nr.: 1145");
- int errors = 0;
- int lived = 0;
-
- knot_zone_tree_t *tree = malloc(sizeof(knot_zone_tree_t));
- assert(tree);
- knot_zone_tree_init(tree);
- const knot_node_t *node =
- knot_node_new(knot_dname_new_from_str("a.ns.nic.cz.",
- strlen("a.ns.nic.cz"),
- NULL),
- NULL, 0);
- assert(node);
-
- lives_ok({
- if (knot_zone_tree_find_less_or_equal(NULL,
- NULL,
- NULL,
- NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_find_less_or_equal(tree, NULL,
- NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_find_less_or_equal(tree,
- node->owner,
- NULL,
- NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- const knot_node_t *found_node = NULL;
- lived = 0;
- if (knot_zone_tree_find_less_or_equal(NULL, node->owner,
- &found_node, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- const knot_node_t *previous_node = NULL;
- lived = 0;
- if (knot_zone_tree_find_less_or_equal(tree, NULL,
- &found_node,
- &previous_node) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- }, "zone tree: tree find less or equal NULL tests");
- if (errors) {
- diag("Zone tree find did not return KNOT_EINVAL "
- "when given wrong arguments");
- }
-
- if (!lived) {
- errors++;
- }
-
- const knot_node_t *previous_node = NULL;
-
- /* Insert node - exact match. */
- assert(knot_zone_tree_insert(tree, (knot_node_t *)node) == KNOT_EOK);
-
-
- const knot_node_t *found_node = NULL;
- if (knot_zone_tree_find_less_or_equal(tree,
- node->owner,
- &found_node,
- &previous_node) <= 0) {
- diag("Calling zone tree find less with valid arguments did "
- "not return KNOT_EOK");
- errors++;
- }
-
- if (found_node != node) {
- diag("Zone tree find did not return right node");
- errors++;
- }
-
- if (knot_zone_tree_get_less_or_equal(tree, node->owner,
- (knot_node_t **)&found_node,
- (knot_node_t **)&previous_node)
- <= 0) {
- diag("Calling zone tree get less with valid arguments did "
- "not return KNOT_EOK");
- errors++;
- }
-
- if (found_node != node) {
- diag("Zone tree get less did not return right node");
- errors++;
- }
-
- knot_dname_t *less_dname =
- knot_dname_new_from_str("ns.nic.cz.",
- strlen("ns.nic.cz."),
- NULL);
-
- assert(knot_dname_compare(less_dname, node->owner) < 0);
-
- if (knot_zone_tree_find_less_or_equal(tree,
- less_dname,
- &found_node,
- &previous_node) <= 0) {
- diag("Calling zone tree find less or equal "
- "with valid arguments did "
- "not return > 0");
- errors++;
- }
-
- if (found_node != node) {
- diag("Zone tree find less or equal did not return right node");
- errors++;
- }
-
- if (knot_zone_tree_get_less_or_equal(tree, less_dname,
- (knot_node_t **)&found_node,
- (knot_node_t **)&previous_node)
- <= 0) {
- diag("Calling zone tree less or equal with valid arguments did "
- "not return > 0");
- errors++;
- }
-
- if (found_node != node) {
- diag("Zone tree get less or equal did not return right node");
- errors++;
- }
-
- /* Try to search for node not in tree. */
- knot_dname_t *alien_dname =
- knot_dname_new_from_str("this.name.is.not.in.the.tree.",
- strlen("this.name.is.not.in.the.tree."),
- NULL);
-
- if (knot_zone_tree_find_less_or_equal(tree, alien_dname,
- &found_node,
- &previous_node) !=
- 0) {
- diag("Calling zone tree find less with valid arguments did "
- "not return 0");
- errors++;
- }
-
- if (knot_zone_tree_get_less_or_equal(tree,
- alien_dname,
- (knot_node_t **)&found_node,
- (knot_node_t **)&previous_node)
- != 0) {
- diag("Calling zone tree get with valid arguments did "
- "not return 0");
- errors++;
- }
-
- /* Set node previous label. */
- knot_node_t *tmp_node =
- knot_node_new(knot_dname_new_from_str("ns.nic.cz.",
- strlen("ns.nic.cz"),
- NULL), NULL, 0);
- assert(tmp_node);
- knot_node_set_parent((knot_node_t *)node, tmp_node);
-
- if (knot_zone_tree_find_less_or_equal(tree, node->owner,
- &found_node,
- &previous_node) <=
- 0) {
- diag("Calling zone tree find with valid arguments did "
- "not return > 0");
- errors++;
- }
-
- if (found_node != node || previous_node != tmp_node) {
- diag("Zone tree find did not return valid nodes!");
- errors++;
- }
-
-
- if (knot_zone_tree_get_less_or_equal(tree, node->owner,
- (knot_node_t **)&found_node,
- (knot_node_t **)&previous_node)
- <= 0) {
- diag("Calling zone tree get with valid arguments did "
- "not return > 0");
- errors++;
- }
-
- if (found_node != node || previous_node != tmp_node) {
- diag("Zone get find did not return valid nodes!");
- errors++;
- }
-
- return (errors == 0);
-}
-
-static int test_tree_remove()
-{
- int errors = 0;
- int lived = 0;
-
- knot_zone_tree_t *tree = malloc(sizeof(knot_zone_tree_t));
- assert(tree);
- knot_zone_tree_init(tree);
- knot_node_t *node =
- knot_node_new(knot_dname_new_from_str("a.ns.nic.cz.",
- strlen("a.ns.nic.cz"),
- NULL),
- NULL, 0);
- assert(node);
-
- /* Add node. */
- int ret = knot_zone_tree_insert(tree, node);
- assert(ret == 0);
- assert(ret == 0);
-
- lives_ok({
- if (knot_zone_tree_remove(NULL, NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_remove(tree, NULL, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_remove(tree, node->owner, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_remove(NULL, node->owner, NULL) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- knot_zone_tree_node_t *deleted_node = NULL;
- lived = 0;
- if (knot_zone_tree_remove(NULL, node->owner, &deleted_node) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_remove(tree, NULL, &deleted_node) !=
- KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- }, "zone tree: remove NULL tests");
- if (errors) {
- diag("Zone tree remove did not return KNOT_EINVAL "
- "when given wrong arguments");
- }
-
- errors += lived != 1;
-
- knot_zone_tree_node_t *removed_node = NULL;
-
- /* Remove previously inserted node. */
- if (knot_zone_tree_remove(tree, node->owner, &removed_node) !=
- KNOT_EOK) {
- diag("Could not remove previously inserted node!");
- errors++;
- }
-
- if (removed_node == NULL || removed_node->node != node) {
- diag("Wrong node was removed!");
- errors++;
- }
-
- /*
- * Try remove the node again - it should not be there and
- * removed_node should be NULL.
- */
-
- if (knot_zone_tree_remove(tree, node->owner, &removed_node) !=
- KNOT_EOK) {
- diag("Could not remove previously inserted node!");
- errors++;
- }
-
- if (removed_node != NULL) {
- diag("Zone tree remove returned previously removed node!");
- errors++;
- }
-
- return (errors == 0);
-
-}
-
-struct test_zone_tree_args {
- knot_node_t *array[10 * 1024];
- size_t count;
-};
-
-static void add_to_array(knot_zone_tree_node_t *node, void *data)
-{
- struct test_zone_tree_args *args =
- (struct test_zone_tree_args *)data;
- args->array[args->count++] = node->node;
-}
-
-static int test_traversal(knot_node_t **nodes,
- size_t node_count,
- uint code)
-{
- int errors = 0;
- int lived = 0;
-
- int (*trav_func)(knot_zone_tree_t *,
- void (*)(knot_zone_tree_node_t *, void *),
- void *);
-
- trav_func = (code) ? knot_zone_tree_reverse_apply_inorder :
- knot_zone_tree_forward_apply_inorder;
-
- knot_zone_tree_t *tree = malloc(sizeof(knot_zone_tree_t));
- assert(tree);
- knot_zone_tree_init(tree);
-
- lives_ok({
- if (trav_func(NULL, NULL, NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (trav_func(tree, NULL, NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (trav_func(NULL, add_to_array, NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- }, "zone tree: traversal NULL tests");
-
- if (errors) {
- diag("Traversal function did not return KNOT_EINVAL "
- "when given NULL parameters");
- }
-
- errors += lived != 1;
-
- /* Add nodes to tree. */
- for (int i = 0; i < node_count; i++) {
- assert(knot_zone_tree_insert(tree, nodes[i]) == KNOT_EOK);
- }
-
- struct test_zone_tree_args args;
- args.count = 0;
-
- trav_func(tree, add_to_array, &args);
-
- if (args.count != node_count) {
- diag("Traversal function traversed more nodes than it "
- "should have!");
- return ++errors;
- }
-
- for (int i = 0; i < node_count; i++) {
- int match = nodes[i] == args.array[i];
- if (!match) {
- diag("Traversal function returned nodes in wrong "
- "order!");
- errors++;
- }
- }
-
- return errors;
-}
-
-static int test_tree_traversals()
-{
- /*!< \todo I can test inorder and reverse inorder, but I don't know
- * how to test others. It is somehow tested in zone tests. */
- int errors = 0;
-
- /* Create few nodes. (5 should be enough) */
- knot_node_t *nodes[5];
- for (int i = 0; i < 5; i++) {
- char owner_string[20];
- owner_string[0] = i + '0';
- memcpy(owner_string + 1, ".ns.test.cz.",
- strlen(".ns.test.cz.") + 1);
- nodes[i] =
- knot_node_new(knot_dname_new_from_str(owner_string,
- strlen(owner_string),
- NULL), NULL, 0);
- }
-
- if (test_traversal(nodes, 5, 0)) {
- diag("Inorder traversal failed");
- errors++;
- }
-
- for (int i = 0; i < 5; i++) {
- char owner_string[20];
- owner_string[0] = (5 - i) + '0';
- memcpy(owner_string + 1, ".ns.test.cz.",
- strlen(".ns.test.cz.") + 1);
- nodes[i] =
- knot_node_new(knot_dname_new_from_str(owner_string,
- strlen(owner_string),
- NULL), NULL, 0);
- }
-
- if (test_traversal(nodes, 5, 1)) {
- diag("Reverse inorder traversal failed");
- errors++;
- }
-
- return (errors == 0);
-}
-
-static int test_tree_shallow_copy()
-{
- int errors = 0;
- int lived = 0;
-
- knot_zone_tree_t *tree = malloc(sizeof(knot_zone_tree_t));
- assert(tree);
- knot_zone_tree_init(tree);
-
- lives_ok({
- if (knot_zone_tree_shallow_copy(NULL, NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_shallow_copy(tree, NULL) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- lived = 0;
- if (knot_zone_tree_shallow_copy(NULL, tree) != KNOT_EINVAL) {
- errors++;
- }
- lived = 1;
- }, "zone tree: shallow copy NULL tests");
- if (errors) {
- diag("Zone tree shallow copy did not return KNOT_EINVAL when "
- "given NULL arguments");
- }
- errors += lived != 1;
-
- /* Create few nodes. (5 should be enough) */
- knot_node_t *nodes[5];
- for (int i = 0; i < 5; i++) {
- char owner_string[20];
- owner_string[0] = i + '0';
- memcpy(owner_string + 1, ".ns.test.cz.",
- strlen(".ns.test.cz.") + 1);
- nodes[i] =
- knot_node_new(knot_dname_new_from_str(owner_string,
- strlen(owner_string),
- NULL), NULL, 0);
- /* Insert node to tree. */
- assert(knot_zone_tree_insert(tree, nodes[i]) == KNOT_EOK);
- }
-
- /* Create shallow copy. */
- knot_zone_tree_t *new_tree = malloc(sizeof(knot_zone_tree_t));
- assert(new_tree);
- knot_zone_tree_init(new_tree);
-
- if (knot_zone_tree_shallow_copy(tree, new_tree) != KNOT_EOK) {
- diag("Zone tree shallow copy did not return KNOT_EOK "
- "when executed with valid parameters");
- return 0;
- }
-
- /* Traverse the tree twice and check that arrays are the same. */
- struct test_zone_tree_args args1;
- args1.count = 0;
-
- knot_zone_tree_forward_apply_inorder(tree, add_to_array,
- &args1);
-
-
- struct test_zone_tree_args args2;
- args2.count = 0;
- knot_zone_tree_forward_apply_inorder(new_tree, add_to_array,
- &args2);
-
- if (args1.count != args2.count) {
- diag("Zone tree created by shallow copy has wrong count"
- "of nodes");
- return 0;
- }
-
- for (int i = 0; i < args1.count; i++) {
- if (args1.array[i] != args2.array[i]) {
- diag("Zone tree created by shallow copy has wrong "
- "nodes");
- errors++;
- }
- }
-
- return (errors == 0);
-
-}
-
-
-static const int KNOT_ZONE_TREE_TEST_COUNT = 14;
-
-static int knot_zone_tree_tests_count(int argc, char *argv[])
-{
- return KNOT_ZONE_TREE_TEST_COUNT;
-}
-
-static int knot_zone_tree_tests_run(int argc, char *argv[])
-{
- ok(test_tree_init(), "zone tree: init");
- ok(test_tree_insert(), "zone tree: insertion");
- ok(test_tree_finding(), "zone tree: finding");
- todo();
- ok(test_tree_finding_less_or_equal(), "zone tree: find less or equal");
- endtodo;
- ok(test_tree_remove(), "zone tree: removal");
- ok(test_tree_traversals(), "zone tree: traversals");
- ok(test_tree_shallow_copy(), "zone tree: shallow copy");
-
- return 1;
-}
diff --git a/src/tests/libknot/libknot/zone_tree_tests.h b/src/tests/libknot/libknot/zone_tree_tests.h
deleted file mode 100644
index 4cea88c..0000000
--- a/src/tests/libknot/libknot/zone_tree_tests.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTDZONE_TREE_TESTS_H_
-#define _KNOTDZONE_TREE_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api zone_tree_tests_api;
-
-#endif /* _KNOTDZONE_TREE_TESTS_H_ */
diff --git a/src/tests/libknot/libknot/zonedb_tests.h b/src/tests/libknot/libknot/zonedb_tests.h
deleted file mode 100644
index 0c4f8ef..0000000
--- a/src/tests/libknot/libknot/zonedb_tests.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_ZONEDB_TESTS_H_
-#define _KNOTD_ZONEDB_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api zonedb_tests_api;
-
-#endif /* _KNOTD_ZONEDB_TESTS_H_ */
diff --git a/src/tests/libknot/realdata/files/parsed_data b/src/tests/libknot/realdata/files/parsed_data
deleted file mode 100644
index fe22b90..0000000
--- a/src/tests/libknot/realdata/files/parsed_data
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/realdata/files/parsed_data_queries b/src/tests/libknot/realdata/files/parsed_data_queries
deleted file mode 100644
index 5857c87..0000000
--- a/src/tests/libknot/realdata/files/parsed_data_queries
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/realdata/files/raw_data b/src/tests/libknot/realdata/files/raw_data
deleted file mode 100644
index 502005e..0000000
--- a/src/tests/libknot/realdata/files/raw_data
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/realdata/files/raw_data_queries b/src/tests/libknot/realdata/files/raw_data_queries
deleted file mode 100644
index 9062d5a..0000000
--- a/src/tests/libknot/realdata/files/raw_data_queries
+++ /dev/null
Binary files differ
diff --git a/src/tests/libknot/realdata/libknot/dname_tests_realdata.c b/src/tests/libknot/realdata/libknot/dname_tests_realdata.c
deleted file mode 100644
index d0216c7..0000000
--- a/src/tests/libknot/realdata/libknot/dname_tests_realdata.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/* Copyright (C) 2011 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 <string.h>
-#include <assert.h>
-#include <stdarg.h>
-
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "tests/libknot/realdata/libknot/dname_tests_realdata.h"
-#include "libknot/dname.h"
-#include "libknot/common.h"
-
-#include "common/print.h"
-#include "common/lists.h"
-
-static int knot_dname_tests_count(int argc, char *argv[]);
-static int knot_dname_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api dname_tests_api = {
- "DNS library - dname", //! Unit name
- &knot_dname_tests_count, //! Count scheduled tests
- &knot_dname_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-int check_domain_name(const knot_dname_t *dname,
- const test_dname_t *test_dname)
-{
- int errors = 0;
-
- if (dname == NULL) {
- diag("Domain name not created!");
- return 1;
- }
-
-// diag("test_dname: %p, dname: %p", test_dname, dname);
- // check size
- if (knot_dname_size(dname) != test_dname->size) {
- diag("Bad size of the created domain name: %u (should be %u).",
- knot_dname_size(dname), test_dname->size);
- ++errors;
- } else {
- // check wire format
- uint size = knot_dname_size(dname);
- if (strncmp((char *)knot_dname_name(dname),
- (char *)test_dname->wire, size) != 0) {
- diag("The wire format of the created "
- "domain name is wrong:"
- " '%.*s' (should be '%.*s').",
- size, knot_dname_name(dname),
- size, test_dname->wire);
- ++errors;
- }
- }
- // check labels
- if (test_dname->label_count != dname->label_count) {
- diag("Label count of the created domain name is wrong:"
- " %d (should be %d)\n", dname->label_count,
- test_dname->label_count);
- ++errors;
- }
- if (strncmp((char *)dname->labels, (char *)test_dname->labels,
- test_dname->label_count) != 0) {
- diag("Label offsets of the created domain name are wrong.\n");
- hex_print((char *)dname->labels, test_dname->label_count);
- hex_print((char *)test_dname->labels, test_dname->label_count);
- ++errors;
- }
-
- return errors;
-}
-
-static int test_dname_create_from_str(const list *dname_list)
-{
- int errors = 0;
- knot_dname_t *dname = NULL;
-
- /* Test with real data. */
- node *n = NULL;
- WALK_LIST(n, *dname_list) {
- //note("testing domain: %s", test_domains_ok[i].str);
- test_dname_t *test_dname = (test_dname_t *)n;
- dname = knot_dname_new_from_str(test_dname->str,
- strlen(test_dname->str), NULL);
- errors += check_domain_name(dname, test_dname);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_create_from_wire(const list *dname_list)
-{
- int errors = 0;
- knot_dname_t *dname = NULL;
-
- node *n = NULL;
- WALK_LIST(n, *dname_list) {
- test_dname_t *test_dname = (test_dname_t *)n;
- dname = knot_dname_new_from_wire(test_dname->wire,
- test_dname->size, NULL);
- errors += check_domain_name(dname, test_dname);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_to_str(const list *dname_list)
-{
- int errors = 0;
-
- /*
- * Converts dname wireformat to string represenation, which is compared
- * with entries in test_domains structure.
- */
-
- knot_dname_t *dname = NULL;
-
- /* Test with real data. */
- node *n = NULL;
- WALK_LIST(n, *dname_list) {
- //note("testing domain: %s", test_domains_ok[i].str);
- test_dname_t *test_dname = (test_dname_t *)n;
- dname = knot_dname_new_from_wire(
- test_dname->wire,
- test_dname->size,
- NULL);
- if (dname == NULL) {
- ERR_ALLOC_FAILED;
- return 0;
- }
-
- char *name_str = knot_dname_to_str(dname);
- if (strcmp(name_str, test_dname->str) != 0) {
- diag("Presentation format of domain name wrong:"
- " %s (should be %s)",
- name_str, test_dname->str);
- ++errors;
- }
- free(name_str);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-static int test_dname_is_fqdn(const list *dname_list)
-{
- int errors = 0;
-
- knot_dname_t *dname;
-
- /* All dnames from real data are fqdn */
-
- node *n = NULL;
- WALK_LIST(n, *dname_list) {
- test_dname_t *test_dname = (test_dname_t *)n;
- dname = knot_dname_new_from_wire(test_dname->wire,
- test_dname->size, NULL);
- errors += !knot_dname_is_fqdn(dname);
- knot_dname_free(&dname);
- }
-
- return (errors == 0);
-}
-
-//static int check_wires(const uint8_t *wire1, uint size1,
-// uint8_t *wire2, uint size2)
-//{
-// if (size1 != size2) {
-// return 0;
-// }
-
-// int i;
-
-// for (i = 0; (i < size1); i++) {
-// if (wire1[i] != wire2[i]) {
-// return 0;
-// }
-// }
-
-// return 1;
-//}
-
-///* \note not to be run separately */
-//static int test_dname_name(knot_dname_t **dnames_fqdn,
-// knot_dname_t **dnames_non_fqdn)
-//{
-// assert(dnames_fqdn);
-// assert(dnames_non_fqdn);
-
-// int errors = 0;
-
-// for (int i = 0; i < TEST_DOMAINS_OK; i++) {
-// const uint8_t *tmp_name;
-// tmp_name = knot_dname_name(dnames_fqdn[i]);
-// if (!check_wires(tmp_name, dnames_fqdn[i]->size,
-// (uint8_t *)test_domains_ok[i].wire,
-// test_domains_ok[i].size)) {
-// diag("Got bad name value from structure: "
-// "%s, should be: %s",
-// tmp_name, test_domains_ok[i].wire);
-// errors++;
-// }
-// }
-
-// for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
-// const uint8_t *tmp_name;
-// tmp_name = knot_dname_name(dnames_non_fqdn[i]);
-// if (!check_wires(tmp_name, dnames_non_fqdn[i]->size,
-// (uint8_t *)test_domains_non_fqdn[i].wire,
-// test_domains_non_fqdn[i].size)) {
-// diag("Got bad name value from structure: "
-// "%s, should be: %s",
-// tmp_name, test_domains_non_fqdn[i].wire);
-// errors++;
-// }
-// }
-
-// return errors;
-//}
-
-///* \note not to be run separately */
-//static int test_dname_size(knot_dname_t **dnames_fqdn,
-// knot_dname_t **dnames_non_fqdn)
-//{
-// assert(dnames_fqdn);
-// assert(dnames_non_fqdn);
-
-// int errors = 0;
-
-// for (int i = 0; i < TEST_DOMAINS_OK; i++) {
-// uint8_t tmp_size;
-// if ((tmp_size = knot_dname_size(dnames_fqdn[i])) !=
-// test_domains_ok[i].size) {
-// diag("Got bad size value from structure: "
-// "%u, should be: %u",
-// tmp_size, test_domains_ok[i].size);
-// errors++;
-// }
-// }
-
-// for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
-// uint8_t tmp_size;
-// if ((tmp_size = knot_dname_size(dnames_non_fqdn[i])) !=
-// test_domains_non_fqdn[i].size) {
-// diag("Got bad size value from structure: "
-// "%u, should be: %u",
-// tmp_size, test_domains_non_fqdn[i].size);
-// errors++;
-// }
-// }
-
-// return errors;
-//}
-
-///* \note not to be run separately */
-//static int test_dname_node(knot_dname_t **dnames_fqdn,
-// knot_dname_t **dnames_non_fqdn)
-//{
-// assert(dnames_fqdn);
-// assert(dnames_non_fqdn);
-
-// int errors = 0;
-
-// for (int i = 0; i < TEST_DOMAINS_OK; i++) {
-// const knot_node_t *tmp_node;
-// if ((tmp_node = knot_dname_node(dnames_fqdn[i])) !=
-// NODE_ADDRESS) {
-// diag("Got bad node value from structure: "
-// "%p, should be: %p",
-// tmp_node, NODE_ADDRESS);
-// errors++;
-// }
-// }
-
-// for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
-// const knot_node_t *tmp_node;
-// if ((tmp_node = knot_dname_node(dnames_non_fqdn[i])) !=
-// NODE_ADDRESS) {
-// diag("Got bad node value from structure: "
-// "%s, should be: %s",
-// tmp_node, NODE_ADDRESS);
-// errors++;
-// }
-// }
-
-// return errors;
-//}
-
-//static int test_dname_getters(uint type)
-//{
-// int errors = 0;
-
-// knot_dname_t *dnames_fqdn[TEST_DOMAINS_OK];
-// knot_dname_t *dnames_non_fqdn[TEST_DOMAINS_NON_FQDN];
-
-// for (int i = 0; i < TEST_DOMAINS_OK; i++) {
-// dnames_fqdn[i] = knot_dname_new_from_wire(
-// (uint8_t *)test_domains_ok[i].wire,
-// test_domains_ok[i].size, NODE_ADDRESS);
-// assert(dnames_fqdn[i] != NULL);
-// }
-
-// for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
-// dnames_non_fqdn[i] = knot_dname_new_from_wire(
-// (uint8_t *)test_domains_non_fqdn[i].wire,
-// test_domains_non_fqdn[i].size, NODE_ADDRESS);
-// assert(dnames_non_fqdn[i] != NULL);
-// }
-
-// switch (type) {
-// case 0: {
-// errors += test_dname_name(dnames_fqdn, dnames_non_fqdn);
-// break;
-// }
-
-// case 1: {
-// errors += test_dname_size(dnames_fqdn, dnames_non_fqdn);
-// break;
-// }
-
-// case 2: {
-// errors += test_dname_node(dnames_fqdn, dnames_non_fqdn);
-// break;
-// }
-// } /* switch */
-
-// for (int i = 0; i < TEST_DOMAINS_OK; i++) {
-// knot_dname_free(&dnames_fqdn[i]);
-// }
-
-// for (int i = 0; i < TEST_DOMAINS_NON_FQDN; i++) {
-// knot_dname_free(&dnames_non_fqdn[i]);
-// }
-
-// return (errors == 0);
-//}
-
-static const int KNOT_DNAME_TEST_COUNT = 4;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_dname_tests_count(int argc, char *argv[])
-{
- return KNOT_DNAME_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_dname_tests_run(int argc, char *argv[])
-{
- const test_data_t *data = data_for_knot_tests;
-
- int res = 0,
- res_str = 0,
- res_wire = 0,
- res_str_non_fqdn = 0,
- res_final = 1;
-
- ok((res_str = test_dname_create_from_str(&data->dname_list)),
- "dname: create from string");
- ok((res_wire = test_dname_create_from_wire(&data->dname_list)),
- "dname: create from wire");
-
- res_final *= res_str;
- res_final *= res_wire;
- res_final *= res_str_non_fqdn;
-
-// res = test_dname_getters(0);
-// ok(res, "dname: name");
-
-// res = test_dname_getters(1);
-// ok(res, "dname: size");
-
-// res = test_dname_getters(2);
-// ok(res, "dname: node");
-
-// skip(!res_str || !res_wire || !res_str_non_fqdn, 2);
-
- ok((res = test_dname_to_str(&data->dname_list)),
- "dname: convert to str");
- res_final *= res;
-
-// endskip; /* !res_str || !res_wire */
-
- ok((res = test_dname_is_fqdn(&data->dname_list)), "dname: fqdn");
- res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/realdata/libknot/dname_tests_realdata.h b/src/tests/libknot/realdata/libknot/dname_tests_realdata.h
deleted file mode 100644
index a7d75aa..0000000
--- a/src/tests/libknot/realdata/libknot/dname_tests_realdata.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_DNAME_TESTS_H_
-#define _KNOTD_DNAME_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api dname_tests_api;
-
-#endif /* _KNOTD_DNAME_TESTS_H_ */
diff --git a/src/tests/libknot/realdata/libknot/edns_tests_realdata.c b/src/tests/libknot/realdata/libknot/edns_tests_realdata.c
deleted file mode 100644
index 257d480..0000000
--- a/src/tests/libknot/realdata/libknot/edns_tests_realdata.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "tests/libknot/realdata/libknot/edns_tests_realdata.h"
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "libknot/common.h"
-#include "libknot/edns.h"
-
-static int knot_edns_tests_count(int argc, char *argv[]);
-static int knot_edns_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api edns_tests_api = {
- "DNS library - EDNS", //! Unit name
- &knot_edns_tests_count, //! Count scheduled tests
- &knot_edns_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-///* Creates actual knot_opt_rr_t variable from test_edns_t variable */
-//static knot_opt_rr_t *opt_rr_from_test_edns(test_edns_t *test_edns)
-//{
-// knot_opt_rr_t *ret = knot_edns_new();
-
-// CHECK_ALLOC_LOG(ret, NULL);
-
-// ret->flags = test_edns->flags;
-// ret->ext_rcode = test_edns->ext_rcode;
-// ret->payload = test_edns->payload;
-// ret->version = test_edns->version;
-
-// for (int i = 0; i < test_edns->option_count; i++) {
-// if (knot_edns_add_option(ret, test_edns->options[i].code,
-// test_edns->options[i].length,
-// test_edns->options[i].data) != 0) {
-// knot_edns_free(&ret);
-// return NULL;
-// }
-// }
-
-// return ret;
-//}
-
-///* simple wire compare - 0 if same, 1 otherwise */
-//static int edns_compare_wires(uint8_t *wire1,
-// uint8_t *wire2,
-// uint16_t length)
-//{
-// for (uint i = 0; i < length; i++) {
-// if (wire1[i] != wire2[i]) {
-// return 1;
-// }
-// }
-
-// return 0;
-//}
-
-//static int check_edns(const knot_opt_rr_t *edns,
-// const test_edns_t *test_edns)
-//{
-// if (edns->option_count != test_edns->option_count) {
-// diag("Option count is wrong");
-// return -1;
-// }
-
-// for (int i = 0; i < edns->option_count; i++) {
-// /* check options */
-// if (edns->options[i].code != test_edns->options[i].code) {
-// diag("Code in options is wrong");
-// return -1;
-// }
-
-// if (edns->options[i].length != test_edns->options[i].length) {
-// diag("Length in options is wrong");
-// return -1;
-// }
-
-// if (edns_compare_wires(edns->options[i].data,
-// test_edns->options[i].data,
-// edns->options[i].length) != 0) {
-// diag("Data in options are wrong");
-// return -1;
-// }
-// }
-
-// if (edns->version != test_edns->version) {
-// diag("Version is wrong");
-// return -1;
-// }
-
-// if (edns->flags != test_edns->flags) {
-// diag("Flags are wrong");
-// return -1;
-// }
-
-// if (edns->size != test_edns->size) {
-// diag("Size is wrong");
-// return -1;
-// }
-
-// return 0;
-//}
-
-//static int test_edns_get_payload(const knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// if (knot_edns_get_payload(edns) !=
-// test_edns->payload) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_get_ext_rcode(const knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// if (knot_edns_get_ext_rcode(edns) !=
-// test_edns->ext_rcode) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_get_flags(const knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// if (knot_edns_get_flags(edns) !=
-// test_edns->flags) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_get_version(const knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// if (knot_edns_get_version(edns) !=
-// test_edns->version) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_do(const knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// if (knot_edns_do(edns) !=
-// (test_edns->flags & KNOT_EDNS_DO_MASK)) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_size(knot_opt_rr_t *edns, test_edns_t *test_edns)
-//{
-// diag("%d %d\n", edns->size, test_edns->size);
-// if (knot_edns_size(edns) !=
-// test_edns->size) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_set_payload(knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// knot_edns_set_payload(edns, test_edns->payload);
-
-// if (edns->payload !=
-// test_edns->payload) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_set_ext_rcode(knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// knot_edns_set_ext_rcode(edns, test_edns->ext_rcode);
-// if (edns->ext_rcode !=
-// test_edns->ext_rcode) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_set_version(knot_opt_rr_t *edns,
-// test_edns_t *test_edns)
-//{
-// knot_edns_set_version(edns,
-// test_edns->version);
-
-// if (edns->version !=
-// test_edns->version) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_set_do(knot_opt_rr_t *edns)
-//{
-// knot_edns_set_do(edns);
-
-// if (!knot_edns_do(edns)) {
-// return 0;
-// } else {
-// return 1;
-// }
-//}
-
-//static int test_edns_getters(uint type)
-//{
-// int errors = 0;
-// for (int i = 0; i < TEST_EDNS; i++) {
-// knot_opt_rr_t *edns =
-// opt_rr_from_test_edns(&(test_edns_data[i]));
-// if (edns == NULL) {
-// ERR_ALLOC_FAILED;
-// return -1;
-// }
-
-// switch(type) {
-// case 0:
-// if (test_edns_get_payload(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Got wrong payload!");
-// errors++;
-// }
-// break;
-// case 1:
-// if (test_edns_get_ext_rcode(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Got wrong extended RCODE!");
-// errors++;
-// }
-// break;
-// case 2:
-// if (test_edns_get_flags(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Got wrong flags!");
-
-// errors++;
-// }
-// break;
-// case 3:
-// if (test_edns_get_version(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Got wrong version!");
-// errors++;
-// }
-// break;
-// case 4:
-// if (test_edns_do(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Got wrong DO bit!");
-// errors++;
-// }
-// break;
-// case 5:
-// if (test_edns_size(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Got wrong size!");
-// errors++;
-// }
-// break;
-// default:
-// diag("Unknown option");
-// errors++;
-// } /* switch */
-
-// knot_edns_free(&edns);
-// }
-
-// return (errors == 0);
-//}
-
-//static int test_edns_setters(uint type)
-//{
-// int errors = 0;
-// for (int i = 0; i < TEST_EDNS; i++) {
-// knot_opt_rr_t *edns =
-// opt_rr_from_test_edns(&(test_edns_data[i]));
-// if (edns == NULL) {
-// ERR_ALLOC_FAILED;
-// return -1;
-// }
-
-// switch(type) {
-// case 0:
-// if (test_edns_set_payload(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Set wrong payload!");
-// errors++;
-// }
-// break;
-// case 1:
-// if (test_edns_set_ext_rcode(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Set wrong ext_rcode");
-// errors++;
-// }
-// break;
-// case 2:
-// if (test_edns_set_version(edns,
-// &test_edns_data[i]) != 1) {
-// diag("Set wrong version!");
-// errors++;
-// }
-// break;
-// case 3:
-// if (test_edns_set_do(edns) != 1) {
-// diag("Set wrong DO bit!");
-// errors++;
-// }
-// break;
-// default:
-// diag("Unknown option");
-// errors++;
-// } /* switch */
-
-// knot_edns_free(&edns);
-// }
-
-// return (errors == 0);
-//}
-
-//static int test_edns_wire()
-//{
-// /*
-// * Tests to_wire and from_wire in one test.
-// */
-// for (int i = 0; i < TEST_EDNS; i++) {
-// /* Creates instance from test_edns_t. */
-// knot_opt_rr_t *edns =
-// opt_rr_from_test_edns(&(test_edns_data[i]));
-// if (edns == NULL) {
-// ERR_ALLOC_FAILED;
-// return -1;
-// }
-
-// uint8_t *wire = NULL;
-// wire = malloc(sizeof(uint8_t) * edns->size);
-// CHECK_ALLOC_LOG(wire, 0);
-
-// /* Converts EDNS to wire. */
-// short wire_size = knot_edns_to_wire(edns, wire, 100);
-
-// if (wire_size == -1) {
-// diag("Could not create EDNS wire");
-// return 0;
-// }
-
-// knot_opt_rr_t *edns_from_wire = knot_edns_new();
-// if (edns == NULL) {
-// return 0;
-// }
-
-// /* TODO use some constant */
-// /* Creates new EDNS from wire */
-// if (knot_edns_new_from_wire(edns_from_wire,
-// wire,
-// 100) <= 0) {
-// diag("Could not create from wire");
-// return 0;
-// }
-
-// /* Checks whether EDNS created from wire is the same */
-// if (check_edns(edns_from_wire,
-// &(test_edns_data[i])) != 0) {
-// diag("EDNS created from wire is different from the "
-// "original one");
-// }
-
-// free(wire);
-// knot_edns_free(&edns_from_wire);
-// knot_edns_free(&edns);
-// }
-// return 1;
-//}
-
-//static int test_edns_add_option()
-//{
-// /*
-// * Create empty EDNS and add options one by one, testing their presence.
-// */
-// for (int i = 0; i < TEST_EDNS; i++) {
-// knot_opt_rr_t *edns = knot_edns_new();
-// assert(edns->option_count == 0);
-
-// if (edns == NULL) {
-// ERR_ALLOC_FAILED;
-// return 0;
-// }
-
-// for (int j = 0; j < test_edns_data[i].option_count; j++) {
-// if (knot_edns_add_option(edns,
-// test_edns_data[i].options[j].code,
-// test_edns_data[i].options[j].length,
-// test_edns_data[i].options[j].
-// data) != 0) {
-// diag("Could not add option");
-// return 0;
-// }
-
-// if (edns->options[j].code !=
-// test_edns_data[i].options[j].code) {
-// diag("Option code wrongly added!");
-// return 0;
-// }
-
-// if (edns->options[j].length !=
-// test_edns_data[i].options[j].length) {
-// diag("Option length wrongly added!");
-// return 0;
-// }
-
-// if (edns_compare_wires(edns->options[j].data,
-// test_edns_data[i].
-// options[j].data,
-// edns->options[j].length) != 0) {
-// diag("Option wire wrongly added!");
-// return 0;
-// }
-// }
-// knot_edns_free(&edns);
-// }
-// return 1;
-//}
-
-//static int test_edns_has_option()
-//{
-// /*
-// * Create empty EDNS and add options one by one, testing their presence
-// */
-// for (int i = 0; i < TEST_EDNS; i++) {
-// knot_opt_rr_t *edns = knot_edns_new();
-// assert(edns->option_count == 0);
-
-// if (edns == NULL) {
-// ERR_ALLOC_FAILED;
-// return 0;
-// }
-
-// for (int j = 0; j < test_edns_data[i].option_count; j++) {
-// if (knot_edns_add_option(edns,
-// test_edns_data[i].options[j].code,
-// test_edns_data[i].options[j].length,
-// test_edns_data[i].options[j].
-// data) != 0) {
-// diag("Could not add option");
-// return 0;
-// }
-
-// if (knot_edns_has_option(edns,
-// test_edns_data[i].options[j].code) != 1) {
-// diag("Option not found!");
-// return 0;
-// }
-// }
-// knot_edns_free(&edns);
-// }
-// return 1;
-//}
-
-static const int KNOT_EDNS_TESTS_COUNT = 0;
-
-///*! This helper routine should report number of
-// * scheduled tests for given parameters.
-// */
-static int knot_edns_tests_count(int argc, char *argv[])
-{
- return KNOT_EDNS_TESTS_COUNT;
-}
-
-///*! Run all scheduled tests for given parameters.
-// */
-static int knot_edns_tests_run(int argc, char *argv[])
-{
-// int res = 0;
- int res_final = 1;
-
-// res = test_edns_getters(0);
-// ok(res, "EDNS: get payload");
-// res_final *= res;
-
-// res = test_edns_getters(1);
-// ok(res, "EDNS: get extenden RCODE");
-// res_final *= res;
-
-// res = test_edns_getters(2);
-// ok(res, "EDNS: get flags");
-// res_final *= res;
-
-// res = test_edns_getters(3);
-// ok(res, "EDNS: get version");
-// res_final *= res;
-
-// res = test_edns_getters(4);
-// ok(res, "EDNS: do");
-// res_final *= res;
-
-// res = test_edns_getters(5);
-// ok(res, "EDNS: size");
-// res_final *= res;
-
-// res = test_edns_setters(0);
-// ok(res, "EDNS: set payload");
-// res_final *= res;
-
-// res = test_edns_setters(1);
-// ok(res, "EDNS: set extended RCODE");
-// res_final *= res;
-
-// res = test_edns_setters(2);
-// ok(res, "EDNS: set version");
-// res_final *= res;
-
-// res = test_edns_setters(3);
-// ok(res, "EDNS: set DO");
-// res_final *= res;
-
-// res = test_edns_add_option();
-// ok(res, "EDNS: add option");
-// res_final *= res;
-
-// res = test_edns_has_option();
-// ok(res, "EDNS: has option");
-// res_final *= res;
-
-// res = test_edns_wire();
-// ok(res, "EDNS: to_wire and from_wire");
-// res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/realdata/libknot/node_tests_realdata.c b/src/tests/libknot/realdata/libknot/node_tests_realdata.c
deleted file mode 100644
index 91209c9..0000000
--- a/src/tests/libknot/realdata/libknot/node_tests_realdata.c
+++ /dev/null
@@ -1,385 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "tests/libknot/realdata/libknot/node_tests_realdata.h"
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "libknot/dname.h"
-#include "libknot/zone/node.h"
-#include "libknot/util/descriptor.h"
-
-static int knot_node_tests_count(int argc, char *argv[]);
-static int knot_node_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api node_tests_api = {
- "DNS library - node", //! Unit name
- &knot_node_tests_count, //! Count scheduled tests
- &knot_node_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-/* TODO It would be wise not to name variables totally same as structures ... */
-knot_dname_t *dname_from_test_dname(const test_dname_t *test_dname)
-{
- assert(test_dname != NULL);
- knot_dname_t *ret = knot_dname_new_from_wire(test_dname->wire,
- test_dname->size,
- NULL);
- CHECK_ALLOC(ret, NULL);
-
- return ret;
-}
-
-static knot_rrset_t *rrset_from_test_rrset(const test_rrset_t *test_rrset)
-{
- assert(test_rrset != NULL);
- knot_dname_t *owner = dname_from_test_dname(test_rrset->owner);
- CHECK_ALLOC(owner, NULL);
-
- knot_rrset_t *ret = knot_rrset_new(owner, test_rrset->type,
- test_rrset->rclass,
- test_rrset->ttl);
- if (ret == NULL) {
- ERR_ALLOC_FAILED;
- knot_dname_free(&owner);
- return NULL;
- }
-
- return ret;
-}
-
-static int test_node_create(const list *node_list)
-{
- /* Tests creation of node by comparing with test_node struct */
- knot_node_t *tmp;
- int errors = 0;
-
- node *n = NULL;
- WALK_LIST(n, *node_list) {
- const test_node_t *tmp_node = (test_node_t *)n;
- assert(tmp_node);
-
- knot_dname_t *owner =
- dname_from_test_dname(tmp_node->owner);
- if (owner == NULL) {
- return 0;
- }
- tmp = knot_node_new(owner,
- (knot_node_t *)tmp_node->parent, 0);
- if (tmp == NULL ||
- (strncmp((char *)tmp->owner->name,
- (char *)tmp_node->owner->wire,
- tmp->owner->size) != 0) ||
- tmp->parent != (knot_node_t *)tmp_node->parent ||
- tmp->rrset_tree == NULL) {
- errors++;
- diag("Failed to create node structure");
- }
- knot_node_free(&tmp);
- }
-
- return (errors == 0);
-}
-
-static int test_node_add_rrset(list *rrset_list)
-{
- knot_node_t *tmp;
- knot_rrset_t *rrset;
- int errors = 0;
-
- node *n = NULL;
- WALK_LIST(n, *rrset_list) {
- test_rrset_t *test_rrset = (test_rrset_t *)n;
- rrset = rrset_from_test_rrset(test_rrset);
- if (rrset == NULL) {
- diag("Could not create rrset from test data");
- return 0;
- }
-
- /* create node from test_node structure. Always the first one.*/
- knot_dname_t *owner =
- dname_from_test_dname(test_rrset->owner);
- if (owner == NULL) {
- diag("Could not create owner from test data");
- return 0;
- }
-
- tmp = knot_node_new(owner, NULL, 0);
-
- if (knot_node_add_rrset(tmp, rrset, 0) != 0) {
- errors++;
- diag("Failed to insert rrset into node");
- }
-
- /* check if rrset is really there */
-
- const knot_rrset_t *rrset_from_node = NULL;
- if ((rrset_from_node =
- knot_node_rrset(tmp, rrset->type)) == NULL) {
- errors++;
- diag("Inserted rrset could not be found");
- continue;
- }
-
- /* compare rrset from node with original rrset */
-
- const knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
-
- int cmp = 0;
-
- if ((rrset_from_node->rdata == NULL) &&
- (rrset->rdata == NULL)) {
- cmp = 0;
- } else if ((rrset_from_node->rdata != NULL) &&
- (rrset->rdata != NULL)) {
- cmp = knot_rdata_compare(rrset_from_node->rdata,
- rrset->rdata,
- desc->wireformat);
- } else { /* one is not NULL and other is -> error */
- cmp = 1;
- }
-
- if (!((rrset_from_node->type == rrset->type) &&
- (rrset_from_node->rclass == rrset->rclass) &&
- (rrset_from_node->ttl == rrset->ttl) &&
- (rrset_from_node->rrsigs == rrset->rrsigs) &&
- (cmp == 0))) {
- errors++;
- diag("Values in found rrset are wrong");
- }
-
- knot_node_free(&tmp);
- }
-
- return (errors == 0);
-}
-
-//static int test_node_get_rrset()
-//{
-// knot_node_t *tmp;
-// knot_rrset_t *rrset;
-// int errors = 0;
-
-// knot_node_t *nodes[TEST_NODES];
-
-// for (int i = 0; i < TEST_NODES && !errors; i++) {
-// tmp = knot_node_new(&test_nodes[i].owner,
-// test_nodes[i].parent);
-// nodes[i] = tmp;
-// for (int j = 0; j < RRSETS; j++) {
-// knot_node_add_rrset(tmp, &rrsets[j]);
-// }
-// }
-
-// for (int i = 0; i < TEST_NODES && !errors; i++) {
-// for (int j = 0; j < RRSETS; j++) {
-// rrset = &rrsets[j];
-// if (knot_node_rrset(nodes[i], rrset->type)
-// != rrset) {
-// errors++;
-// diag("Failed to get proper rrset from node");
-// }
-// }
-// knot_node_free(&nodes[i], 0);
-// }
-
-// return (errors == 0);
-//}
-
-//static int test_node_get_parent()
-//{
-// knot_node_t *tmp;
-// knot_rrset_t *rrset;
-// int errors = 0;
-
-// knot_node_t *nodes[TEST_NODES];
-
-// for (int i = 0; i < TEST_NODES && !errors; i++) {
-// tmp = knot_node_new(&test_nodes[i].owner,
-// test_nodes[i].parent);
-// nodes[i] = tmp;
-// rrset = &rrsets[i];
-// knot_node_add_rrset(tmp, rrset);
-// }
-
-// for (int i = 0; i < TEST_NODES && !errors; i++) {
-// rrset = &rrsets[i];
-// if (knot_node_parent(nodes[i]) != test_nodes[i].parent) {
-// errors++;
-// diag("Failed to get proper parent from node");
-// }
-// knot_node_free(&nodes[i], 0);
-// }
-// return (errors == 0);
-//}
-
-//static int test_node_sorting()
-//{
-// knot_node_t *tmp = NULL;
-// knot_rrset_t *rrset = NULL;
-// int errors = 0;
-
-// knot_dname_t *owner = dname_from_test_dname(test_nodes[0].owner);
-
-// tmp = knot_node_new(owner,
-// (knot_node_t *)test_nodes[0].parent);
-
-// /* Will add rrsets to node. */
-// knot_node_add_rrset(tmp, rrset);
-// }
-
-// const skip_node_t *node = skip_first(tmp->rrsets);
-
-// int last = *((uint16_t *)node->key);
-
-// /* TODO there is now an API function knot_node_rrsets ... */
-
-// /* Iterates through skip list and checks, whether it is sorted. */
-
-// while ((node = skip_next(node)) != NULL) {
-// if (last > *((uint16_t *)node->key)) {
-// errors++;
-// diag("RRset sorting error");
-// }
-// last = *((uint16_t *)node->key);
-// }
-
-// knot_node_free(&tmp, 1);
-// return (errors == 0);
-//}
-
-//static int test_node_delete()
-//{
-// int errors = 0;
-
-// knot_node_t *tmp_node;
-
-// for (int i = 0; i < TEST_NODES; i++) {
-// knot_dname_t *owner =
-// dname_from_test_dname(test_nodes[i].owner);
-// tmp_node = knot_node_new(owner,
-// (knot_node_t *)test_nodes[i].parent);
-
-// knot_node_free(&tmp_node, 1);
-
-// errors += (tmp_node != NULL);
-// }
-
-// return (errors == 0);
-//}
-
-//static int test_node_set_parent()
-//{
-// knot_node_t *tmp_parent = (knot_node_t *)0xABCDEF;
-// int errors = 0;
-
-// knot_node_t *tmp_node;
-
-// for (int i = 0; i < TEST_NODES; i++) {
-// tmp_node = knot_node_new(&test_nodes[i].owner,
-// test_nodes[i].parent);
-
-// knot_node_set_parent(tmp_node, tmp_parent);
-
-// if (tmp_node->parent != tmp_node->parent) {
-// diag("Parent node is wrongly set.");
-// errors++;
-// }
-// knot_node_free(&tmp_node, 0);
-// }
-// return (errors == 0);
-//}
-
-//static int test_node_free_rrsets()
-//{
-// int errors = 0;
-
-// knot_node_t *tmp_node;
-
-// for (int i = 0; i < TEST_NODES; i++) {
-// knot_dname_t *owner =
-// dname_from_test_dname(test_nodes[i].owner);
-// if (owner == NULL) {
-// return 0;
-// }
-
-// tmp_node = knot_node_new(owner,
-// (knot_node_t *)test_nodes[i].parent);
-
-// knot_node_free_rrsets(tmp_node, 0);
-
-// errors += (tmp_node->rrsets != NULL);
-
-// knot_node_free(&tmp_node, 1);
-// }
-// return (errors == 0);
-//}
-
-static const int KNOT_NODE_TEST_COUNT = 2;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_node_tests_count(int argc, char *argv[])
-{
- return KNOT_NODE_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_node_tests_run(int argc, char *argv[])
-{
- test_data_t *data = data_for_knot_tests;
- int res = 0,
- res_final = 1;
-
- res = test_node_create(&data->node_list);
- ok(res, "node: create");
- res_final *= res;
-
-
- ok((res = test_node_add_rrset(&data->rrset_list)), "node: add");
- res_final *= res;
-
-// ok((res = test_node_get_rrset()), "node: get");
-// res_final *= res;
-
-// ok((res = test_node_get_parent()), "node: get parent");
-// res_final *= res;
-
-// ok((res = test_node_set_parent()), "node: set parent");
-// res_final *= res;
-
-// ok((res = test_node_sorting()), "node: sort");
-// res_final *= res;
-
-// ok((res = test_node_free_rrsets()), "node: free rrsets");
-// res_final *= res;
-
-// endskip;
-
-// ok((res = test_node_delete()), "node: delete");
-// //res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/realdata/libknot/packet_tests_realdata.c b/src/tests/libknot/realdata/libknot/packet_tests_realdata.c
deleted file mode 100644
index 94aac89..0000000
--- a/src/tests/libknot/realdata/libknot/packet_tests_realdata.c
+++ /dev/null
@@ -1,678 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-/* blame: jan.kadlec@nic.cz */
-
-#include <assert.h>
-
-#include <config.h>
-#include "knot/common.h"
-#include "packet_tests_realdata.h"
-#include "libknot/packet/packet.h"
-#include "libknot/packet/response.h"
-/* *test_t structures */
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#ifdef TEST_WITH_LDNS
-#include "ldns/ldns.h"
-#endif
-
-static int packet_tests_count(int argc, char *argv[]);
-static int packet_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api packet_tests_api = {
- "DNS library - packet", //! Unit name
- &packet_tests_count, //! Count scheduled tests
- &packet_tests_run //! Run scheduled tests
-};
-
-#ifdef TEST_WITH_LDNS
-/* Compares one rdata knot with rdata from ldns.
- * Comparison is done through comparing wireformats.
- * Returns 0 if rdata are the same, 1 otherwise
- */
-int compare_rr_rdata(knot_rdata_t *rdata, ldns_rr *rr,
- uint16_t type)
-{
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- for (int i = 0; i < rdata->count; i++) {
- /* check for ldns "descriptors" as well */
-
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME) {
- if (rdata->items[i].dname->size !=
- ldns_rdf_size(ldns_rr_rdf(rr, i))) {
- diag("%s", rdata->items[i].dname->name);
- diag("%s", ldns_rdf_data(ldns_rr_rdf(rr, i)));
- diag("%d", ldns_rdf_size(ldns_rr_rdf(rr, i)));
- diag("%d", rdata->items[i].dname->size);
- diag("Dname sizes in rdata differ");
- return 1;
- }
- if (compare_wires_simple(rdata->items[i].dname->name,
- ldns_rdf_data(ldns_rr_rdf(rr, i)),
- rdata->items[i].dname->size) != 0) {
- diag("%s", rdata->items[i].dname->name);
- diag("%s", ldns_rdf_data(ldns_rr_rdf(rr, i)));
- diag("Dname wires in rdata differ");
- return 1;
- }
- } else {
- /* Compare sizes first, then actual data */
- if (rdata->items[i].raw_data[0] !=
- ldns_rdf_size(ldns_rr_rdf(rr, i))) {
- /* \note ldns stores the size including the
- * length, knot does not */
- diag("Raw data sizes in rdata differ");
- diag("knot: %d ldns: %d",
- rdata->items[i].raw_data[0],
- ldns_rdf_size(ldns_rr_rdf(rr, i)));
-// hex_print((char *)
-// (rdata->items[i].raw_data + 1),
-// rdata->items[i].raw_data[0]);
-// hex_print((char *)ldns_rdf_data(ldns_rr_rdf(rr,
-// i)),
-// ldns_rdf_size(ldns_rr_rdf(rr, i)));
- if (abs(rdata->items[i].raw_data[0] -
- ldns_rdf_size(ldns_rr_rdf(rr, i))) != 1) {
- return 1;
- }
- }
- if (compare_wires_simple((uint8_t *)
- (rdata->items[i].raw_data + 1),
- ldns_rdf_data(ldns_rr_rdf(rr, i)),
- rdata->items[i].raw_data[0]) != 0) {
-// hex_print((char *)
-// (rdata->items[i].raw_data + 1),
-// rdata->items[i].raw_data[0]);
-// hex_print((char *)
-// ldns_rdf_data(ldns_rr_rdf(rr, i)),
-// rdata->items[i].raw_data[0]);
- diag("Raw data wires in rdata differ in item "
- "%d", i);
-
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-int compare_rrset_w_ldns_rr(const knot_rrset_t *rrset,
- ldns_rr_list *rr_set, char check_rdata)
-{
- /* We should have only one rrset from ldns, although it is
- * represented as rr_list ... */
-
- int errors = 0;
-
- ldns_rr *rr = ldns_rr_list_rr(rr_set, 0);
- assert(rr);
- assert(rrset);
-
- /* compare headers */
-
- if (rrset->owner->size != ldns_rdf_size(ldns_rr_owner(rr))) {
- char *tmp_dname = knot_dname_to_str(rrset->owner);
- diag("RRSet owner names differ in length");
- diag("ldns: %d, knot: %d", ldns_rdf_size(ldns_rr_owner(rr)),
- rrset->owner->size);
- diag("%s", tmp_dname);
- diag("%s", ldns_rdf_data(ldns_rr_owner(rr)));
- free(tmp_dname);
- errors++;
- }
-
- if (compare_wires_simple(rrset->owner->name,
- ldns_rdf_data(ldns_rr_owner(rr)),
- rrset->owner->size) != 0) {
- diag("RRSet owner wireformats differ");
- diag("%s \\w %s\n", rrset->owner->name,
- ldns_rdf_data(ldns_rr_owner(rr)));
- errors++;
- }
-
- if (rrset->type != ldns_rr_get_type(rr)) {
- diag("RRset types differ");
- diag("knot type: %d Ldns type: %d", rrset->type,
- ldns_rr_get_type(rr));
- errors++;
- }
-
- if (rrset->rclass != ldns_rr_get_class(rr)) {
- diag("RRset classes differ");
- errors++;
- }
-
- if (rrset->ttl != ldns_rr_ttl(rr)) {
- diag("RRset TTLs differ");
- diag("knot: %d ldns: %d", rrset->ttl, ldns_rr_ttl(rr));
- errors++;
- }
-
- /* compare rdatas */
-
- if (rrset->rdata == NULL) {
- diag("RRSet has no RDATA!");
- return errors;
- }
- knot_rdata_t *tmp_rdata = rrset->rdata;
-
- int i = 0;
-
- while ((rr = ldns_rr_list_pop_rr(rr_set))) {
- assert(rr);
-
- if (compare_rr_rdata(tmp_rdata, rr, rrset->type) != 0) {
- diag("Rdata differ");
- return 1;
- }
-
- tmp_rdata = tmp_rdata->next;
- i++;
- }
-
-//// if (check_rdata) {
-//// if (compare_rr_rdata(rrset->rdata, rr, rrset->type) != 0) {
-//// diag("Rdata differ");
-//// errors++;
-//// }
-//// }
-
- return errors;
-}
-
-int compare_rrsets_w_ldns_rrlist(const knot_rrset_t **rrsets,
- ldns_rr_list *rrlist, int count)
-{
- int errors = 0;
-
- /* There are no rrsets currenty. Everything is just rr */
-
- ldns_rr_list *rr_set = NULL;
-
- ldns_rr_list_sort(rrlist);
-
- if (count < 0) {
- return 0;
- }
-
- for (int i = 0; i < count ; i++) {
- /* normally ldns_pop_rrset or such should be here */
-
- rr_set = ldns_rr_list_pop_rrset(rrlist);
- /* Get one rr from list. */
- ldns_rr *rr = ldns_rr_list_rr(rr_set, 0);
- assert(rr);
-
- if (rr_set == NULL) {
- diag("Ldns and knot structures have different "
- "counts of rrsets.");
- diag("knot: %d ldns: %d",
- count, (count - 1) - i);
- return -1;
- }
-
-// diag("RRset from ldns is %d long", ldns_rr_list_rr_count(rr_set));
-
-// diag("Got type from ldns: %d (%d)\n", ldns_rr_get_type(rr), i);
-
- int j = 0;
- for (j = 0; j < count; j++) {
-// diag("Got type from knot: %d\n", rrsets[j]->type);
- if (rrsets[j]->type == ldns_rr_get_type(rr) &&
- rrsets[j]->owner->size ==
- ldns_rdf_size(ldns_rr_owner(rr)) &&
- (compare_wires_simple(ldns_rdf_data(ldns_rr_owner(rr)), rrsets[j]->owner->name,
- rrsets[j]->owner->size) == 0)) {
- errors += compare_rrset_w_ldns_rr(rrsets[j],
- rr_set, 1);
- break;
- }
- }
- if (j == count) {
- diag("There was no RRSet of the same type!");
-// errors++;
- }
- }
-
- return errors;
-}
-
-int check_packet_w_ldns_packet(knot_packet_t *packet,
- ldns_pkt *ldns_packet,
- int check_header,
- int check_question,
- int check_body,
- int check_edns)
-{
- int errors = 0;
- if (check_header) {
-// if (packet->header.id != ldns_pkt_id(ldns_packet)) {
-// diag("response ID does not match - %d %d",
-// packet->header.id,
-// ldns_pkt_id(ldns_packet));
-// errors++;
-// }
-
- /* qdcount is always 1 in knot's case */
-
- /* TODO check flags1 and flags2 - no API for that,
- * write my own */
-
- if (packet->header.ancount !=
- ldns_pkt_ancount(ldns_packet)) {
- diag("Answer RRSet count wrongly converted");
- errors++;
- }
-
- if (packet->header.nscount !=
- ldns_pkt_nscount(ldns_packet)) {
- diag("Authority RRSet count wrongly converted.\n"
- "got %d should be %d",
- packet->header.nscount,
- ldns_pkt_nscount(ldns_packet));
- errors++;
- }
-
- /* - 1 because ldns does not include OPT_RR to additional "
- "section */
- int minus = (!ldns_pkt_edns_version(ldns_packet)) ? 1 : 0;
-// int minus = 0;
-
- if ((packet->header.arcount - minus) !=
- ldns_pkt_arcount(ldns_packet)) {
- diag("Additional RRSet count wrongly converted.\n"
- "got %d should be %d",
- packet->header.arcount,
- ldns_pkt_arcount(ldns_packet));
- errors++;
- }
-
- /*!< \todo Check OPT RR! */
-
- if (errors) {
- return errors;
- }
- }
- /* Header checked */
-
- /* Question section */
-
- int ret = 0;
- if (check_question) {
- knot_rrset_t *question_rrset =
- knot_rrset_new(packet->
- question.qname,
- packet->
- question.qtype,
- packet->
- question.qclass,
- 3600);
-
- if ((ret = compare_rrset_w_ldns_rr(question_rrset,
- ldns_pkt_question(ldns_packet), 0)) != 0) {
- diag("Question rrsets wrongly converted");
- errors++;
- }
- knot_rrset_free(&question_rrset);
- }
-
- if (check_body) {
-
- /* other RRSets */
-
- if ((ret =
- compare_rrsets_w_ldns_rrlist(packet->answer,
- ldns_pkt_answer(ldns_packet),
- knot_packet_answer_rrset_count(packet))) != 0) {
- diag("Answer rrsets wrongly converted");
- errors++;
- }
-
-
-
- if ((ret = compare_rrsets_w_ldns_rrlist(packet->authority,
- ldns_pkt_authority(ldns_packet),
- knot_packet_authority_rrset_count(packet))) != 0) {
- diag("Authority rrsets wrongly converted - %d", ret);
- errors++;
- }
-
- /* We don't want to test OPT RR, which is the last rrset
- * in the additional section */
-
- if ((ret = compare_rrsets_w_ldns_rrlist(packet->additional,
- ldns_pkt_additional(ldns_packet),
- knot_packet_additional_rrset_count(packet) - 1)) != 0) {
- diag("Additional rrsets wrongly converted");
- errors++;
- }
-
- }
-
- if (check_edns) {
-
- /* OPT RR */
-
- if (ldns_pkt_edns(ldns_packet)) {
- /* if (packet->edns_packet == NULL) {
- diag("ldns has edns section, knot has not");
- return 1;
- } */
-
- knot_opt_rr_t *opt = &(packet->opt_rr);
-
- if (ldns_pkt_edns_udp_size(ldns_packet) !=
- knot_edns_get_payload(opt)) {
- diag("Payloads in EDNS are different");
- errors++;
- }
-
- if (ldns_pkt_edns_version(ldns_packet) !=
- knot_edns_get_version(opt)) {
- diag("Versions in EDNS are different");
- errors++;
- }
-
- if (ldns_pkt_edns_extended_rcode(ldns_packet) !=
- knot_edns_get_ext_rcode(opt)) {
- diag("Extended rcodes in EDNS are different");
- errors++;
- }
-
- /* TODO parse flags do bit, z value ... */
- }
- }
-
- return errors;
-}
-#endif
-
-extern knot_rrset_t *rrset_from_test_rrset(const test_rrset_t *test_rrset);
-extern knot_dname_t *dname_from_test_dname(const test_dname_t *test_dname);
-
-/* Converts knot_rrset_t to knot_opt_rr */
-static knot_opt_rr_t *opt_rrset_to_opt_rr(knot_rrset_t *rrset)
-{
- if (rrset == NULL) {
- return NULL;
- }
-
- knot_opt_rr_t *opt_rr = knot_edns_new();
- assert(opt_rr);
-
- knot_edns_set_payload(opt_rr, rrset->rclass);
-
- knot_edns_set_ext_rcode(opt_rr, rrset->ttl);
-
- /* TODO rdata? mostly empty, I guess, but should be done */
-
- return opt_rr;
-}
-
-knot_packet_t *packet_from_test_response(test_response_t *test_packet)
-{
- knot_rrset_t *parsed_opt = NULL;
-
- for (int j = 0; j < test_packet->arcount; j++) {
- if (test_packet->additional[j]->type ==
- KNOT_RRTYPE_OPT) {
- parsed_opt =
- rrset_from_test_rrset(
- test_packet->additional[j]);
- assert(parsed_opt);
- break;
- }
- }
-
- knot_opt_rr_t *opt_rr = NULL;
- if (parsed_opt != NULL) {
- opt_rr =
- opt_rrset_to_opt_rr(parsed_opt);
- assert(opt_rr);
- } else {
- opt_rr = NULL;
- }
-
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
- knot_packet_set_max_size(packet, 1024 * 10);
-
- if (opt_rr != NULL) {
- packet->opt_rr = *opt_rr;
- }
-
- packet->header.id = test_packet->id;
- packet->header.qdcount = test_packet->qdcount;
-
- packet->question.qname = dname_from_test_dname(test_packet->qname);
- packet->size += test_packet->qname->size;
- packet->question.qtype = test_packet->qtype;
- packet->question.qclass = test_packet->qclass;
-
- packet->size += 4;
-
- packet->answer =
- malloc(sizeof(knot_rrset_t *) * test_packet->ancount);
- assert(packet->answer);
-
- for (int j = 0; j < test_packet->ancount; j++) {
- if (&(test_packet->answer[j])) {
- packet->answer[packet->an_rrsets++] =
- rrset_from_test_rrset(test_packet->answer[j]);
- }
- }
-
- packet->authority =
- malloc(sizeof(knot_rrset_t *) * test_packet->nscount);
- assert(packet->answer);
-
- for (int j = 0; j < test_packet->nscount; j++) {
- if (&(test_packet->authority[j])) {
- packet->authority[packet->ns_rrsets++] =
- rrset_from_test_rrset(test_packet->authority[j]);
- }
- }
-
- packet->authority =
- malloc(sizeof(knot_rrset_t *) * test_packet->arcount);
- assert(packet->answer);
-
- for (int j = 0; j < test_packet->arcount; j++) {
- if (&(test_packet->additional[j])) {
- if (test_packet->additional[j]->type ==
- KNOT_RRTYPE_OPT) {
- continue;
- }
- packet->additional[packet->ar_rrsets++] =
- rrset_from_test_rrset(test_packet->additional[j]);
- }
- }
-
- return packet;
-}
-
-static int test_packet_parse_from_wire(list raw_response_list)
-{
-#ifdef TEST_WITH_LDNS
- int errors = 0;
-
- node *n = NULL;
- WALK_LIST(n ,raw_response_list) {
- test_raw_packet_t *raw_packet = (test_raw_packet_t *)n;
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- int ret = 0;
- if ((ret =
- knot_packet_parse_from_wire(packet, raw_packet->data,
- raw_packet->size, 0)) !=
- KNOT_EOK) {
- diag("Warning: could not parse wire! "
- "(might be caused by malformed dump) - "
- "knot error: %s", knot_strerror(ret));
-// hex_print(raw_packet->data,
-// raw_packet->size);
- continue;
- }
-
- ldns_pkt *ldns_packet = NULL;
-
- if (ldns_wire2pkt(&ldns_packet, raw_packet->data,
- raw_packet->size) != LDNS_STATUS_OK) {
- diag("Could not parse wire using ldns");
- diag("%s",
- ldns_get_errorstr_by_id(ldns_wire2pkt(&ldns_packet,
- raw_packet->data,
- raw_packet->size)));
- return 0;
- }
-
- if (check_packet_w_ldns_packet(packet, ldns_packet, 1,
- 1, 1, 1) != 0) {
- diag("Wrongly created packet");
- errors++;
- }
-
- ldns_pkt_free(ldns_packet);
- knot_packet_free(&packet);
- }
-
- return (errors == 0);
-#endif
-#ifndef TEST_WITH_LDNS
- diag("Enable ldns to test this feature");
- return 0;
-#endif
-}
-
-static int test_packet_to_wire(list raw_response_list)
-{
-#ifdef TEST_WITH_LDNS
- int errors = 0;
- /*!< \todo test queries too! */
-// /* We'll need data from both lists. */
-// test_packet_t **test_packets = NULL;
-// uint test_packet_count = 0;
-// node *n = NULL;
-// WALK_LIST(n, response_list) {
-// test_packet_count++;
-// }
-
-// test_packets =
-// malloc(sizeof(test_packet_t *) * test_packet_count);
-// assert(test_packets);
-// int i = 0;
-// WALK_LIST(n, response_list) {
-// test_packets[i++] = (test_response_t *)n;
-// }
-
-// test_raw_packet_t **test_packets = NULL;
-// uint test_packet_count = 0;
-// n = NULL;
-// WALK_LIST(n, raw_response_list) {
-// test_packet_count++;
-// }
-
-// test_packets =
-// malloc(sizeof(test_raw_packet_t *) * test_packet_count);
-// assert(test_packets);
-// i = 0;
-// WALK_LIST(n, raw_response_list) {
-// test_packets[i++] = (test_raw_packet_t *)n;
-// }
-
-// assert(test_response_count == test_packet_count);
- node *n = NULL;
- WALK_LIST(n, raw_response_list) {
- /* Create packet from raw response. */
- knot_packet_t *packet =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(packet);
- test_raw_packet_t *raw_packet = (test_raw_packet_t *)n;
- if (knot_packet_parse_from_wire(packet, raw_packet->data,
- raw_packet->size, 0) !=
- KNOT_EOK) {
- diag("Warning: could not parse wire! "
- "(might be caused be malformed dump)");
- continue;
- }
- knot_packet_set_max_size(packet, 1024 * 10);
- /* Use this packet to create wire */
- uint8_t *wire = NULL;
- size_t size = 0;
- if (knot_packet_to_wire(packet, &wire ,&size) != KNOT_EOK) {
- diag("Could not convert packet to wire");
- }
- /* Create ldns packet from created wire */
- ldns_pkt *ldns_packet = NULL;
-
- if (ldns_wire2pkt(&ldns_packet, wire,
- size) != LDNS_STATUS_OK) {
- diag("Could not parse wire using ldns");
- /*!< \todo get rid of this */
- diag("%s",
- ldns_get_errorstr_by_id(ldns_wire2pkt(&ldns_packet,
- wire,
- size)));
- return 0;
- }
-
- if (check_packet_w_ldns_packet(packet, ldns_packet, 1, 1, 1,
- 1) != 0) {
- diag("Packet wrongly converted to wire!");
- errors++;
- }
- knot_packet_free(&packet);
- ldns_pkt_free(ldns_packet);
- }
-
- return (errors == 0);
-#endif
-#ifndef TEST_WITH_LDNS
- diag("Enable ldns to test this feature!");
- return 0;
-#endif
-}
-
-static const uint KNOT_PACKET_TEST_COUNT = 2;
-
-static int packet_tests_count(int argc, char *argv[])
-{
- return KNOT_PACKET_TEST_COUNT;
-}
-
-static int packet_tests_run(int argc, char *argv[])
-{
- const test_data_t *data = data_for_knot_tests;
-
- int res = 0;
- todo();
- ok(res = test_packet_parse_from_wire(data->raw_packet_list),
- "packet: from wire");
- diag("Resolve issue with arcount.");
- endtodo;
-// skip(!res, 1);
- ok(test_packet_to_wire(data->raw_packet_list), "packet: to wire");
-// endskip;
-
- return 1;
-}
-
diff --git a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.c b/src/tests/libknot/realdata/libknot/rdata_tests_realdata.c
deleted file mode 100644
index 0d39bfb..0000000
--- a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* Copyright (C) 2011 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 <stdlib.h>
-#include <assert.h>
-
-#include "tests/libknot/realdata/libknot/rdata_tests_realdata.h"
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "libknot/common.h"
-#include "libknot/rdata.h"
-#include "libknot/util/descriptor.h"
-#include "libknot/util/utils.h"
-
-static int knot_rdata_tests_count(int argc, char *argv[]);
-static int knot_rdata_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api rdata_tests_api = {
- "DNS library - rdata", //! Unit name
- &knot_rdata_tests_count, //! Count scheduled tests
- &knot_rdata_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-extern int check_domain_name(const knot_dname_t *dname,
- const test_dname_t *test_dname);
-
-extern int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count);
-
-/*!
- * \brief Checks if all RDATA items in the given RDATA structure are correct.
- *
- * \return Number of errors encountered. Error is either if some RDATA item
- * is not set (i.e. NULL) or if it has other than the expected value.
- */
-static int check_rdata(const knot_rdata_t *rdata,
- const test_rdata_t *test_rdata)
-{
- assert(rdata != NULL);
- assert(test_rdata != NULL);
-
- int errors = 0;
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(test_rdata->type);
- //note("check_rdata(), RRType: %u", rrtype);
-
- for (int i = 0; i < desc->length; ++i) {
-
- switch (desc->wireformat[i]) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- case KNOT_RDATA_WF_LITERAL_DNAME:
- if (check_domain_name(rdata->items[i].dname,
- test_rdata->items[i].dname) != 0) {
- errors++;
- diag("Rdata contains wrong dname item");
- }
- break;
- default:
- if (test_rdata->items[i].raw_data[0] !=
- rdata->items[i].raw_data[0]) {
- diag("Raw rdata in items have different "
- "sizes!");
- return 0;
- }
-
- errors +=
- compare_wires_simple(
- (uint8_t *)test_rdata->items[i].raw_data,
- (uint8_t *)rdata->items[i].raw_data,
- (uint)rdata->items[i].raw_data[0]);
- }
- }
- return errors;
-}
-
-extern knot_dname_t *dname_from_test_dname(test_dname_t *test_dname);
-
-///*!
-// * \brief Tests knot_rdata_set_item().
-// *
-// * \retval > 0 on success.
-// * \retval 0 otherwise.
-// */
-//static int test_rdata_set_item(list rdata_list)
-//{
-// node *n = NULL;
-// WALK_LIST(n, rdata_list) {
-// knot_rdata_t *rdata = knot_rdata_new();
-// assert(rdata);
-// test_rdata_t *test_rdata = (test_rdata_t *)n;
-
-// knot_rrtype_descriptor_t *desc =
-// knot_rrtype_descriptor_by_type(test_rdata->type);
-// for (int i = 0; i < test_rdata->count; i++) {
-// knot_rdata_item_t item;
-// if (test_rdata->items[i].type == TEST_ITEM_DNAME) {
-// item.dname =
-// dname_from_test_dname(
-// test_rdata->items[i].dname);
-// } else {
-// item.raw_data = test_rdata->items[i].raw_data;
-// }
-// if (knot_rdata_set_item(rdata, i, item) != 0) {
-// diag("Could not set item, rdata count: %d",
-// rdata->count);
-// return 0;
-// }
-// }
-
-// /* Check that all items are OK */
-// if (check_rdata(rdata, test_rdata) != 0) {
-// return 0;
-// }
-// }
-// return 1;
-//}
-
-static knot_rdata_item_t *items_from_test_items(test_item_t *test_items,
- size_t count)
-{
- knot_rdata_item_t *items =
- malloc(sizeof(knot_rdata_item_t) * count);
- assert(items);
- for (int i = 0; i < count; i++) {
- if (test_items[i].type == TEST_ITEM_DNAME) {
- items[i].dname =
- dname_from_test_dname(test_items[i].dname);
- } else {
- items[i].raw_data = test_items[i].raw_data;
- }
- }
-
- return items;
-}
-
-static int test_rdata_set_items(list rdata_list)
-{
- int errors = 0;
-
- // check error return values
- knot_rdata_t *rdata = knot_rdata_new();
- assert(rdata);
-
- node *n = NULL;
- WALK_LIST(n, rdata_list) {
- test_rdata_t *test_rdata = (test_rdata_t *)n;
- knot_rdata_t *rdata = knot_rdata_new();
-
- /* create dnslib items from tests items. */
- knot_rdata_item_t *items =
- items_from_test_items(test_rdata->items,
- test_rdata->count);
-
- assert(items);
- assert(test_rdata->count > 0);
- assert(rdata->items == NULL);
-
- if (knot_rdata_set_items(rdata, items,
- test_rdata->count) != 0) {
- diag("Could not set items!");
- errors++;
- }
-
- if (check_rdata(rdata, test_rdata) != 0) {
- diag("Wrong rdata after knot_rdata_set_items!");
- errors++;
- }
-
- knot_rdata_free(&rdata);
- }
-
- return (errors == 0);
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Tests knot_rdata_get_item().
- *
- * \retval > 0 on success.
- * \retval 0 otherwise.
- */
-static int test_rdata_get_item(list rdata_list)
-{
- node *n = NULL;
- WALK_LIST(n, rdata_list) {
- test_rdata_t *test_rdata = (test_rdata_t *)n;
- knot_rdata_t *rdata = knot_rdata_new();
- assert(rdata);
- knot_rdata_item_t *items =
- items_from_test_items(test_rdata->items,
- test_rdata->count);
- assert(knot_rdata_set_items(rdata, items,
- test_rdata->count) == 0);
- knot_rdata_item_t *new_items =
- malloc(sizeof(knot_rdata_item_t) * test_rdata->count);
- for (int i = 0; i < test_rdata->count; i++) {
- knot_rdata_item_t *item =
- knot_rdata_get_item(rdata, i);
- if (item == NULL) {
- diag("Could not get item");
- return 0;
- }
- new_items[i] = *item;
- }
-
- knot_rdata_free(&rdata);
- free(items);
-
- knot_rdata_t *new_rdata = knot_rdata_new();
- assert(new_rdata);
- assert(knot_rdata_set_items(new_rdata,
- new_items,
- test_rdata->count) == 0);
-
- if (check_rdata(new_rdata, test_rdata) != 0) {
- diag("Wrong rdata created using rdata_get_item");
- return 0;
- }
-
- knot_rdata_free(&new_rdata);
- free(new_items);
- }
-
- return 1;
-}
-
-//static int test_rdata_wire_size()
-//{
-// knot_rdata_t *rdata;
-// int errors = 0;
-
-// // generate some random data
-// uint8_t data[KNOT_MAX_RDATA_WIRE_SIZE];
-// generate_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE);
-
-// for (int i = 0; i <= KNOT_RRTYPE_LAST; ++i) {
-// rdata = knot_rdata_new();
-
-// int size =
-// fill_rdata(data, KNOT_MAX_RDATA_WIRE_SIZE, i, rdata);
-
-// if (size < 0) {
-// ++errors;
-// } else {
-// int counted_size = knot_rdata_wire_size(rdata,
-// knot_rrtype_descriptor_by_type(i)->wireformat);
-// if (size != counted_size) {
-// diag("Wrong wire size computed (type %d):"
-// " %d (should be %d)",
-// i, counted_size, size);
-// ++errors;
-// }
-// }
-
-// knot_rrtype_descriptor_t *desc =
-// knot_rrtype_descriptor_by_type(i);
-
-// for (int x = 0; x < desc->length; x++) {
-// if (desc->wireformat[x] ==
-// KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
-// desc->wireformat[x] ==
-// KNOT_RDATA_WF_COMPRESSED_DNAME ||
-// desc->wireformat[x] ==
-// KNOT_RDATA_WF_LITERAL_DNAME) {
-// knot_dname_free(&(rdata->items[x].dname));
-// }
-// }
-// knot_rdata_free(&rdata);
-// }
-
-// return (errors == 0);
-//}
-
-/*----------------------------------------------------------------------------*/
-
-/*----------------------------------------------------------------------------*/
-
-static const int KNOT_RDATA_TEST_COUNT = 2;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_rdata_tests_count(int argc, char *argv[])
-{
- return KNOT_RDATA_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_rdata_tests_run(int argc, char *argv[])
-{
- test_data_t *data = data_for_knot_tests;
- int res = 0,
- res_final = 1;
-
- ok(res = test_rdata_set_items(data->rdata_list),
- "rdata: set items all at once");
- res_final *= res;
-
- ok(res = test_rdata_get_item(data->rdata_list),
- "rdata: get item");
- res_final *= res;
-
-// ok(res = test_rdata_set_item(data->rdata_list),
-// "rdata: set items one-by-one");
-// res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.h b/src/tests/libknot/realdata/libknot/rdata_tests_realdata.h
deleted file mode 100644
index 570b2b1..0000000
--- a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*!
- * \file rdata_tests.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * Contains unit tests for RDATA (knot_rdata_t) and RDATA item
- * (knot_rdata_item_t) structures.
- *
- * Contains tests for:
- * - creating empty RDATA structure with or without reserved space.
- * - setting RDATA items one-by-one
- * - setting RDATA items all at once
- *
- * As for now, the tests use several (TEST_RDATAS) RDATA structures, each
- * with different number of RDATA items (given by test_rdatas). These are all
- * initialized to pointers derived from RDATA_ITEM_PTR (first is RDATA_ITEM_PTR,
- * second RDATA_ITEM_PTR + 1, etc.). The functions only test if the pointer
- * is set properly.
- *
- * \todo It may be better to test also some RDATAs with predefined contents,
- * such as some numbers, some domain name, etc. For this purpose, we'd
- * need RDATA descriptors (telling the types of each RDATA item within an
- * RDATA).
- *
- * \todo It will be fine to test all possible output values of all functions,
- * e.g. test whether knot_rdata_get_item() returns NULL when passed an
- * illegal position, etc.
- */
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_RDATA_TESTS_H_
-#define _KNOTD_RDATA_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api rdata_tests_api;
-
-#endif /* _KNOTD_RDATA_TESTS_H_ */
diff --git a/src/tests/libknot/realdata/libknot/response_tests_realdata.c b/src/tests/libknot/realdata/libknot/response_tests_realdata.c
deleted file mode 100644
index 63961f7..0000000
--- a/src/tests/libknot/realdata/libknot/response_tests_realdata.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-/* blame: jan.kadlec@nic.cz */
-
-#include <assert.h>
-
-#include "packet_tests_realdata.h"
-#include "knot/common.h"
-#include "libknot/packet/packet.h"
-#include "libknot/packet/response.h"
-/* *test_t structures */
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#ifdef TEST_WITH_LDNS
-#include "ldns/packet.h"
-#endif
-
-static int response_tests_count(int argc, char *argv[]);
-static int response_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api response_tests_api = {
- "DNS library - response", //! Unit name
- &response_tests_count, //! Count scheduled tests
- &response_tests_run //! Run scheduled tests
-};
-
-#ifdef TEST_WITH_LDNS
-extern int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count);
-extern int compare_rr_rdata(knot_rdata_t *rdata, ldns_rr *rr, uint16_t type);
-extern int compare_rrset_w_ldns_rr(const knot_rrset_t *rrset,
- ldns_rr *rr, char check_rdata);
-extern int compare_rrsets_w_ldns_rrlist(const knot_rrset_t **rrsets,
- ldns_rr_list *rrlist, int count);
-
-extern int check_packet_w_ldns_packet(knot_packet_t *packet,
- ldns_pkt *ldns_packet,
- int check_header,
- int check_question,
- int check_body,
- int check_edns);
-#endif
-
-extern knot_packet_t *packet_from_test_response(test_response_t *response);
-
-static int test_response_init_from_query(list query_list)
-{
- int errors = 0;
- node *n = NULL;
- WALK_LIST(n, query_list) {
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
- knot_packet_t *query =
- packet_from_test_response((test_response_t *)n);
- assert(query);
- knot_packet_set_max_size(response, 1024 * 10);
- if (knot_response_init_from_query(response,
- query, 1) != KNOT_EOK) {
- diag("Could not init response from query!");
- errors++;
- }
- knot_packet_free(&response);
- knot_packet_free(&query);
- }
- return (errors == 0);
-}
-
-//static int test_response_add_opt(list opt_list)
-//{
-// int errors = 0;
-// node *n = NULL;
-// WALK_LIST(n, query_list) {
-// knot_packet_t *response =
-// knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
-// assert(response);
-// knot_opt_rr_t *opt =
-// opt_from_test_opt((test_opt_t *)n);
-// assert(query);
-// if (knot_response_add_opt(response,
-// opt, 1)!= KNOT_EOK) {
-// diag("Could not add OPT RR to response!");
-// errors++;
-// }
-// knot_packet_free(&response);
-// knot_opt_rr_free(&opt);
-// }
-// return (errors == 0);
-//}
-
-extern knot_rrset_t *rrset_from_test_rrset(test_rrset_t *test_rrset);
-
-static int test_response_add_generic(int (*func)(knot_packet_t *,
- knot_rrset_t *,
- int, int, int, int),
- list rrset_list)
-{
- /*!< \todo Now adding only one RRSet at the time, try more, use nodes */
- int errors = 0;
- node *n = NULL;
- WALK_LIST(n, rrset_list) {
- knot_packet_t *response =
- knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
- assert(response);
- knot_packet_set_max_size(response,
- KNOT_PACKET_PREALLOC_RESPONSE * 100);
- assert(knot_response_init(response) == KNOT_EOK);
-
- knot_rrset_t *rrset =
- rrset_from_test_rrset((test_rrset_t *)n);
- assert(rrset);
-
- int ret = 0;
- if ((ret = func(response, rrset, 0, 1, 0, 0)) != KNOT_EOK) {
- diag("Could not add RRSet to response! Returned: %d",
- ret);
- diag("(owner: %s type %s)",
- ((test_rrset_t *)n)->owner->str,
- knot_rrtype_to_string((
- (test_rrset_t *)n)->type));
- errors++;
- }
- knot_packet_free(&response);
- knot_rrset_deep_free(&rrset, 1, 1, 1);
- }
-
- return (errors == 0);
-}
-
-static void test_response_add_rrset(list rrset_list)
-{
- ok(test_response_add_generic(knot_response_add_rrset_answer,
- rrset_list),
- "response: add answer rrset");
- ok(test_response_add_generic(knot_response_add_rrset_authority,
- rrset_list),
- "response: add authority rrset");
- ok(test_response_add_generic(knot_response_add_rrset_additional,
- rrset_list),
- "response: add additional rrset");
-}
-
-static const uint KNOT_response_TEST_COUNT = 4;
-
-static int response_tests_count(int argc, char *argv[])
-{
- return KNOT_response_TEST_COUNT;
-}
-
-static int response_tests_run(int argc, char *argv[])
-{
- const test_data_t *data = data_for_knot_tests;
-
-// int res = 0;
- ok(test_response_init_from_query(data->query_list),
- "response: init from query");
- test_response_add_rrset(data->rrset_list);
- return 1;
-}
diff --git a/src/tests/libknot/realdata/libknot/response_tests_realdata.h b/src/tests/libknot/realdata/libknot/response_tests_realdata.h
deleted file mode 100644
index 731604b..0000000
--- a/src/tests/libknot/realdata/libknot/response_tests_realdata.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_PACKET_response_TESTS_H_
-#define _KNOTD_PACKET_response_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api response_tests_api;
-
-#endif /* _KNOTD_PACKET_response_TESTS_H_ */
diff --git a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.c b/src/tests/libknot/realdata/libknot/rrset_tests_realdata.c
deleted file mode 100644
index cb59f4c..0000000
--- a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.c
+++ /dev/null
@@ -1,289 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "tests/libknot/realdata/libknot/rrset_tests_realdata.h"
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "libknot/common.h"
-#include "libknot/util/descriptor.h"
-#include "libknot/rrset.h"
-#include "libknot/dname.h"
-#include "libknot/rdata.h"
-#include "libknot/util/utils.h"
-#include "libknot/zone/node.h"
-#include "libknot/util/debug.h"
-
-static int knot_rrset_tests_count(int argc, char *argv[]);
-static int knot_rrset_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api rrset_tests_api = {
- "DNS library - rrset", //! Unit name
- &knot_rrset_tests_count, //! Count scheduled tests
- &knot_rrset_tests_run //! Run scheduled tests
-};
-
-/*----------------------------------------------------------------------------*/
-/*
- * Unit implementation.
- */
-
-/* count1 == count2 */
-int compare_wires_simple(uint8_t *wire1, uint8_t *wire2, uint count)
-{
- int i = 0;
- while (i < count &&
- wire1[i] == wire2[i]) {
- i++;
- }
- return (!(count == i));
-}
-
-
-knot_rrset_t *rrset_from_test_rrset(const test_rrset_t *test_rrset)
-{
-// diag("owner: %s\n", test_rrset->owner->str);
- knot_dname_t *owner =
- knot_dname_new_from_wire(test_rrset->owner->wire,
- test_rrset->owner->size, NULL);
-
-// diag("Created owner: %s (%p) from %p\n", knot_dname_to_str(owner),
-// owner, test_rrset->owner);
-
- if (!owner) {
- return NULL;
- }
-
- knot_rrset_t *ret = knot_rrset_new(owner, test_rrset->type,
- test_rrset->rclass,
- test_rrset->ttl);
-
- /* Add rdata to rrset. */
- knot_rdata_t *rdata = knot_rdata_new();
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(test_rrset->type);
-
- node *n = NULL;
- WALK_LIST(n, test_rrset->rdata_list) {
- test_rdata_t *test_rdata = (test_rdata_t *)n;
- if (test_rdata->count != desc->length) {
- diag("Malformed RRSet data!");
- knot_rdata_free(&rdata);
- return ret;
- }
- assert(test_rdata->type == test_rrset->type);
- /* Add items to the actual rdata. */
- rdata->items = malloc(sizeof(knot_rdata_item_t) * desc->length);
- if (rdata->items == NULL) {
- return NULL;
- }
-// diag("Rdata type: %s\n", knot_rrtype_to_string(test_rrset->type));
- for (int i = 0; i < desc->length; i++) {
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME) {
-// diag("%p\n", test_rdata->items[i].raw_data);
- assert(test_rdata->items[i].type == TEST_ITEM_DNAME);
- rdata->items[i].dname =
- knot_dname_new_from_wire(test_rdata->items[i].dname->wire,
- test_rdata->items[i].dname->size,
- NULL);
- } else {
-// diag("%p\n", test_rdata->items[i].dname);
- assert(test_rdata->items[i].type == TEST_ITEM_RAW_DATA);
- assert(test_rdata->items[i].raw_data != NULL);
- rdata->items[i].raw_data = test_rdata->items[i].raw_data;
- }
- }
- }
-
- rdata->next = rdata;
-
- ret->rdata = rdata;
-
- return ret;
-}
-
-extern int check_domain_name(knot_dname_t *dname, test_dname_t *test_dname);
-
-int check_rrset(const knot_rrset_t *rrset,
- const test_rrset_t *test_rrset,
- int check_rdata, int check_items,
- int check_rrsigs)
-{
- /* following implementation should be self-explanatory */
- int errors = 0;
-
- if (rrset == NULL) {
- diag("RRSet not created!");
- return 1;
- }
-
- errors += check_domain_name(rrset->owner, test_rrset->owner);
-
- if (rrset->type != test_rrset->type) {
- diag("TYPE wrong: %u (should be: %u)", rrset->type,
- test_rrset->type);
- ++errors;
- }
-
- if (rrset->rclass != test_rrset->rclass) {
- diag("CLASS wrong: %u (should be: %u)", rrset->rclass,
- test_rrset->rclass);
- ++errors;
- }
-
- if (rrset->ttl != test_rrset->ttl) {
- diag("TTL wrong: %u (should be: %u)", rrset->ttl,
- test_rrset->ttl);
- ++errors;
- }
-
- if (check_rdata) {
- /* TODO use rdata_compare */
- knot_rdata_t *rdata = rrset->rdata;
-
- if (rdata == NULL) {
- diag("There are no RDATAs in the RRSet");
- ++errors;
- }
-
- if (rdata != NULL) {
- while (rdata->next != NULL &&
- rdata->next != rrset->rdata) {
- rdata = rdata->next;
- }
- if (rdata->next == NULL) {
- diag("The list of RDATAs is not cyclic!");
- ++errors;
- } else {
- assert(rdata->next == rrset->rdata);
- }
- }
- }
-
- /* Iterate rrset rdata list and compare items. */
- if (check_items && rrset->rdata != NULL) {
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(rrset->type);
- node *n = NULL;
- knot_rdata_t *tmp_rdata = rrset->rdata;
- WALK_LIST(n, test_rrset->rdata_list) {
- test_rdata_t *test_rdata = (test_rdata_t *)n;
- for (int i = 0; i < desc->length; i++) {
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME) {
- errors += check_domain_name(tmp_rdata->items[i].dname,
- test_rdata->items[i].dname);
- } else {
- assert(tmp_rdata != NULL);
- errors += compare_wires_simple((uint8_t *)tmp_rdata->items[i].raw_data,
- (uint8_t *)test_rdata->items[i].raw_data,
- test_rdata->items[i].raw_data[0]);
- }
- }
- }
- } else if (check_items && rrset->rdata == NULL) {
- diag("Could not test items, since rdata is empty!");
- }
-
- if (check_rrsigs) {
- /* there are currently no rrsigs */
- }
- return errors;
-}
-
-extern knot_dname_t *dname_from_test_dname(test_dname_t *test_dname);
-
-static int test_rrset_create(const list rrset_list)
-{
- int errors = 0;
-
- /* Test with real data. */
- node *n = NULL;
- WALK_LIST(n, rrset_list) {
- test_rrset_t *test_rrset = (test_rrset_t *)n;
- knot_rrset_t *rrset =
- knot_rrset_new(dname_from_test_dname
- (test_rrset->owner),
- test_rrset->type,
- test_rrset->rclass,
- test_rrset->ttl);
- assert(rrset);
- errors += check_rrset(rrset, test_rrset, 0, 0, 0);
- knot_rrset_deep_free(&rrset, 1, 0, 0);
- }
-
- return (errors == 0);
-}
-
-static int test_rrset_add_rdata(list rrset_list)
-{
- int errors = 0;
- node *n = NULL;
- WALK_LIST(n, rrset_list) {
- test_rrset_t *test_rrset = (test_rrset_t *)n;
- knot_rrset_t *tmp_rrset = rrset_from_test_rrset(test_rrset);
- /* TODO use all the rdata */
- assert(tmp_rrset->rdata->next = tmp_rrset->rdata);
- knot_rrset_t *rrset =
- knot_rrset_new(dname_from_test_dname
- (test_rrset->owner),
- test_rrset->type,
- test_rrset->rclass,
- test_rrset->ttl);
- assert(rrset);
- knot_rrset_add_rdata(rrset, tmp_rrset->rdata);
- errors += check_rrset(rrset, test_rrset, 1, 1, 1);
- knot_rrset_free(&tmp_rrset);
- knot_rrset_deep_free(&rrset, 1, 1, 0);
-
- }
- return (errors == 0);
-}
-
-static const int KNOT_RRSET_TEST_COUNT = 2;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_rrset_tests_count(int argc, char *argv[])
-{
- return KNOT_RRSET_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_rrset_tests_run(int argc, char *argv[])
-{
- test_data_t *data = data_for_knot_tests;
-
- int res = 0,
- res_final = 1;
-
- res = test_rrset_create(data->rrset_list);
- ok(res, "rrset: create");
- res_final *= res;
-
- ok(res = test_rrset_add_rdata(data->rrset_list), "rrset: add_rdata");
- res_final *= res;
-
- return res_final;
-}
diff --git a/src/tests/libknot/realdata/libknot/zone_tests_realdata.c b/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
deleted file mode 100644
index 9c92b72..0000000
--- a/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "tests/libknot/realdata/libknot/zone_tests_realdata.h"
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "libknot/common.h"
-#include "libknot/zone/zone.h"
-#include "libknot/zone/node.h"
-
-static int knot_zone_tests_count(int argc, char *argv[]);
-static int knot_zone_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api zone_tests_api = {
- "DNS library - zone", //! Unit name
- &knot_zone_tests_count, //! Count scheduled tests
- &knot_zone_tests_run //! Run scheduled tests
-};
-
-/*
- * Unit implementation.
- */
-
-extern knot_dname_t *dname_from_test_dname(test_dname_t *test_dname);
-extern knot_rrset_t *rrset_from_test_rrset(test_rrset_t *test_rrset);
-
-static knot_node_t *node_from_test_node(const test_node_t *test_node)
-{
- knot_dname_t *owner = dname_from_test_dname(test_node->owner);
- /* TODO parent? */
- knot_node_t *new_node = knot_node_new(owner, NULL, 0);
- node *n = NULL;
- WALK_LIST(n, test_node->rrset_list) {
- test_rrset_t *test_rrset = (test_rrset_t *)n;
- knot_rrset_t *rrset = rrset_from_test_rrset(test_rrset);
- assert(rrset);
- assert(knot_node_add_rrset(new_node, rrset, 0) == 0);
- }
-
- return new_node;
-}
-
-static int test_zone_create(list node_list)
-{
-// knot_dname_t *dname = knot_dname_new_from_wire(
-// test_apex.owner.name, test_apex.owner.size, NULL);
-// assert(dname);
- int errors = 0;
-
- node *n = NULL;
- WALK_LIST(n, node_list) {
- test_node_t *test_node = (test_node_t *)n;
- knot_node_t *node = node_from_test_node(test_node);
- assert(node);
-
- knot_zone_t *zone = knot_zone_new(node, 0, 0);
- if (zone == NULL) {
- diag("Could not create zone with owner: %s\n",
- test_node->owner->str);
- errors++;
- }
- knot_node_free_rrsets(node, 1);
- knot_node_free(&node);
- }
-
- return (errors == 0);
-}
-
-//static int test_zone_add_node(knot_zone_t *zone, int nsec3)
-//{
-// /*
-// * NSEC3 nodes are de facto identical to normal nodes, so there is no
-// * need for separate tests. The only difference is where are they stored
-// * in the zone structure.
-// */
-
-// int errors = 0;
-// int res = 0;
-
-// //note("Good nodes");
-
-// for (int i = 0; i < TEST_NODES_GOOD; ++i) {
-// knot_node_t *node = knot_node_new(&test_nodes_good[i].owner,
-// test_nodes_good[i].parent);
-// if (node == NULL) {
-// diag("zone: Could not create node.");
-// return 0;
-// }
-
-// if ((res = ((nsec3) ? knot_zone_add_nsec3_node(zone, node)
-// : knot_zone_add_node(zone, node))) != 0) {
-// diag("zone: Failed to insert node into zone (returned"
-// " %d).", res);
-// knot_node_free(&node, 0);
-// ++errors;
-// }
-// /* TODO check values in the node as well */
-// }
-
-// //note("Bad nodes");
-
-// for (int i = 0; i < TEST_NODES_BAD; ++i) {
-// knot_node_t *node = knot_node_new(&test_nodes_bad[i].owner,
-// test_nodes_bad[i].parent);
-// if (node == NULL) {
-// diag("zone: Could not create node.");
-// return 0;
-// }
-
-// if ((res = ((nsec3) ? knot_zone_add_nsec3_node(zone, node)
-// : knot_zone_add_node(zone, node))) !=
-// KNOT_EBADZONE) {
-// diag("zone: Inserting wrong node did not result in"
-// "proper return value (%d instead of %d).", res,
-// KNOT_EBADZONE);
-// ++errors;
-// }
-// knot_node_free(&node, 0);
-// }
-
-// // check if all nodes are inserted
-// //int nodes = 0;
-// if (!nsec3
-// && !test_zone_check_node(knot_zone_apex(zone), &test_apex)) {
-// diag("zone: Apex of zone not right.");
-//// diag("Apex owner: %s (%p), apex parent: %p\n",
-//// knot_dname_to_str(knot_zone_apex(zone)->owner),
-//// knot_zone_apex(zone)->owner,
-//// knot_zone_apex(zone)->parent);
-//// diag("Should be: owner: %s (%p), parent: %p\n",
-//// knot_dname_to_str(&test_apex.owner),
-//// &test_apex.owner,
-//// test_apex.parent);
-// ++errors;
-// }
-// //++nodes;
-// for (int i = 0; i < TEST_NODES_GOOD; ++i) {
-// const knot_node_t *n = ((nsec3) ? knot_zone_find_nsec3_node(
-// zone, &test_nodes_good[i].owner) :
-// knot_zone_find_node(zone, &test_nodes_good[i].owner));
-// if (n == NULL) {
-// diag("zone: Missing node with owner %s",
-// test_nodes_good[i].owner.name);
-// ++errors;
-// continue;
-// }
-
-// if (!test_zone_check_node(n, &test_nodes_good[i])) {
-// diag("zone: Node does not match: owner: %s (should be "
-// "%s), parent: %p (should be %p)",
-// node->owner->name, test_nodes_good[i].owner.name,
-// node->parent, test_nodes_good[i].parent);
-// ++errors;
-// }
-// //++nodes;
-// }
-
-// //note("zone: %d nodes in the zone (including apex)", nodes);
-
-// return (errors == 0);
-//}
-
-//static int test_zone_get_node(knot_zone_t *zone, int nsec3)
-//{
-// int errors = 0;
-
-// for (int i = 0; i < TEST_NODES_GOOD; ++i) {
-// if (((nsec3) ? knot_zone_get_nsec3_node(
-// zone, &test_nodes_good[i].owner)
-// : knot_zone_get_node(zone, &test_nodes_good[i].owner))
-// == NULL) {
-// diag("zone: Node (%s) not found in zone.",
-// (char *)test_nodes_good[i].owner.name);
-// ++errors;
-// }
-// }
-
-// for (int i = 0; i < TEST_NODES_BAD; ++i) {
-// if (((nsec3) ? knot_zone_get_nsec3_node(
-// zone, &test_nodes_bad[i].owner)
-// : knot_zone_get_node(zone, &test_nodes_bad[i].owner))
-// != NULL) {
-// diag("zone: Node (%s) found in zone even if it should"
-// "not be there.",
-// (char *)test_nodes_bad[i].owner.name);
-// ++errors;
-// }
-// }
-
-// if (((nsec3)
-// ? knot_zone_get_nsec3_node(NULL, &test_nodes_good[0].owner)
-// : knot_zone_get_node(NULL, &test_nodes_good[0].owner)) != NULL) {
-// diag("zone: Getting node from NULL zone did not result in"
-// "proper return value (NULL)");
-// ++errors;
-// }
-
-// if (((nsec3) ? knot_zone_get_nsec3_node(zone, NULL)
-// : knot_zone_get_node(zone, NULL)) != NULL) {
-// diag("zone: Getting node with NULL owner from zone did not "
-// "result in proper return value (NULL)");
-// ++errors;
-// }
-
-// if (!nsec3 && knot_zone_get_node(zone, &test_apex.owner) == NULL) {
-// diag("zone: Getting zone apex from the zone failed");
-// ++errors;
-// }
-
-// return (errors == 0);
-//}
-
-//static int test_zone_find_node(knot_zone_t *zone, int nsec3)
-//{
-// int errors = 0;
-
-// for (int i = 0; i < TEST_NODES_GOOD; ++i) {
-// if (((nsec3) ? knot_zone_find_nsec3_node(
-// zone, &test_nodes_good[i].owner)
-// : knot_zone_find_node(zone, &test_nodes_good[i].owner))
-// == NULL) {
-// diag("zone: Node (%s) not found in zone.",
-// (char *)test_nodes_good[i].owner.name);
-// ++errors;
-// }
-// }
-
-// for (int i = 0; i < TEST_NODES_BAD; ++i) {
-// if (((nsec3) ? knot_zone_find_nsec3_node(
-// zone, &test_nodes_bad[i].owner)
-// : knot_zone_find_node(zone, &test_nodes_bad[i].owner))
-// != NULL) {
-// diag("zone: Node (%s) found in zone even if it should"
-// "not be there.",
-// (char *)test_nodes_bad[i].owner.name);
-// ++errors;
-// }
-// }
-
-// if (((nsec3)
-// ? knot_zone_find_nsec3_node(NULL, &test_nodes_good[0].owner)
-// : knot_zone_find_node(NULL, &test_nodes_good[0].owner)) != NULL) {
-// diag("zone: Finding node from NULL zone did not result in"
-// "proper return value (NULL)");
-// ++errors;
-// }
-
-// if (((nsec3) ? knot_zone_find_nsec3_node(zone, NULL)
-// : knot_zone_find_node(zone, NULL)) != NULL) {
-// diag("zone: Finding node with NULL owner from zone did not "
-// "result in proper return value (NULL)");
-// ++errors;
-// }
-
-// if (!nsec3 && knot_zone_find_node(zone, &test_apex.owner) == NULL) {
-// diag("zone: Finding zone apex from the zone failed");
-// ++errors;
-// }
-
-// return (errors == 0);
-//}
-
-static const int KNOT_ZONE_TEST_COUNT = 1;
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int knot_zone_tests_count(int argc, char *argv[])
-{
- return KNOT_ZONE_TEST_COUNT;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int knot_zone_tests_run(int argc, char *argv[])
-{
- int res = 0,
- res_final = 0;
-
- test_data_t *data = data_for_knot_tests;
-
- ok((res = test_zone_create(data->node_list)), "zone: create");
- res_final *= res;
-
-// skip(!res, 6);
-
-// ok((res = test_zone_add_node(zone, 0)), "zone: add node");
-// res_final *= res;
-
-// skip(!res, 2);
-
-// skip(!res, 1);
-
-// ok((res = test_zone_find_node(zone, 0)), "zone: find node");
-// res_final *= res;
-
-// endskip; // get node failed
-
-// endskip; // add node failed
-
-// ok((res = test_zone_add_node(zone, 1)), "zone: add nsec3 node");
-// res_final *= res;
-
-// skip(!res, 2);
-
-// skip(!res, 1);
-
-// ok((res = test_zone_find_node(zone, 1)), "zone: find nsec3 node");
-// res_final *= res;
-
-// endskip; // get nsec3 node failed
-
-// endskip; // add nsec3 node failed
-
-// endskip; // create failed
-
- return res_final;
-}
diff --git a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c b/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c
deleted file mode 100644
index 96d1517..0000000
--- a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright (C) 2011 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 "tests/libknot/realdata/libknot/zonedb_tests_realdata.h"
-
-
-static int zonedb_tests_count(int argc, char *argv[]);
-static int zonedb_tests_run(int argc, char *argv[]);
-
-/*! Exported unit API.
- */
-unit_api zonedb_tests_api = {
- "Zone database", //! Unit name
- &zonedb_tests_count, //! Count scheduled tests
- &zonedb_tests_run //! Run scheduled tests
-};
-
-/*! This helper routine should report number of
- * scheduled tests for given parameters.
- */
-static int zonedb_tests_count(int argc, char *argv[])
-{
- return 0;
-}
-
-/*! Run all scheduled tests for given parameters.
- */
-static int zonedb_tests_run(int argc, char *argv[])
-{
- return 0;
-}
diff --git a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h b/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h
deleted file mode 100644
index 0c4f8ef..0000000
--- a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_ZONEDB_TESTS_H_
-#define _KNOTD_ZONEDB_TESTS_H_
-
-#include "common/libtap/tap_unit.h"
-
-/* Unit API. */
-unit_api zonedb_tests_api;
-
-#endif /* _KNOTD_ZONEDB_TESTS_H_ */
diff --git a/src/tests/libknot/realdata/libknot_tests_loader_realdata.c b/src/tests/libknot/realdata/libknot_tests_loader_realdata.c
deleted file mode 100644
index e972855..0000000
--- a/src/tests/libknot/realdata/libknot_tests_loader_realdata.c
+++ /dev/null
@@ -1,1297 +0,0 @@
-/* Copyright (C) 2011 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 <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "common/libtap/tap.h"
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-#include "libknot/util/descriptor.h"
-
-#include "tests/libknot/realdata/parsed_data.rc"
-#include "tests/libknot/realdata/raw_data.rc"
-TREE_DEFINE(test_node, avl);
-
-/* Virtual I/O over memory. */
-static int mem_read(void *dst, size_t n, const char **src,
- unsigned *remaining)
-{
-// printf("reading %u\n", n);
- if (n > *remaining) {
- return 0;
- }
-
-
- memcpy(dst, *src, n);
- *src += n;
- *remaining -= n;
-// printf("remaining %u\n", *remaining);
- return 1;
-}
-
-static int load_raw_packets(test_data_t *data, uint32_t *count,
- const char *src, unsigned src_size)
-{
-
- uint16_t tmp_size = 0;
-
- /* Packets are stored like this: [size][packet_data]+ */
-
- if(!mem_read(count, sizeof(uint32_t), &src, &src_size)) {
- return -1;
- }
-
- for (int i = 0; i < *count; i++) {
- uint16_t query = 0;
- if (!mem_read(&query, sizeof(query), &src, &src_size)) {
- return -1;
- }
-
- if(!mem_read(&tmp_size, sizeof(uint16_t), &src, &src_size)) {
- return -1;
- }
-
- test_raw_packet_t *packet = malloc(sizeof(test_raw_packet_t));
-
-
- packet->size = tmp_size;
- packet->data = malloc(sizeof(uint8_t) * (tmp_size));
- if(!mem_read(packet->data,
- sizeof(uint8_t) * tmp_size, &src, &src_size)) {
- return -1;
- }
-
- if (query) {
- add_tail(&data->raw_query_list, (void *)packet);
- } else {
- add_tail(&data->raw_response_list, (void *)packet);
- }
-
- test_raw_packet_t *new_packet =
- malloc(sizeof(test_raw_packet_t));
- assert(new_packet);
- new_packet->data = packet->data;
- new_packet->size = packet->size;
-
- add_tail(&data->raw_packet_list, (void *)new_packet);
- }
-
- return 0;
-}
-
-/* Returns size of type where avalailable */
-size_t wireformat_size_load(uint wire_type)
-{
- switch(wire_type) {
- case KNOT_RDATA_WF_BYTE:
- return 1;
- break;
- case KNOT_RDATA_WF_SHORT:
- return 2;
- break;
- case KNOT_RDATA_WF_LONG:
- return 4;
- break;
- case KNOT_RDATA_WF_A:
- return 4;
- break;
- case KNOT_RDATA_WF_AAAA:
- return 16;
- break;
- default: /* unknown size */
- return 0;
- break;
- } /* switch */
-}
-
-static int add_label(uint8_t **labels, const uint8_t label,
- uint *label_count)
-{
- void *ret = realloc(*labels, sizeof(uint8_t) * (*label_count + 1));
- if (ret == NULL) {
- return -1;
- }
-
- *labels = ret;
- (*labels)[(*label_count)++] = label;
-
- return 0;
-}
-/* Dnames are stored label by label in the dump */
-/* TODO STRING AS WELL */
-static test_dname_t *load_test_dname(const char **src,
- unsigned *src_size)
-{
- test_dname_t *ret = malloc(sizeof(test_dname_t));
- CHECK_ALLOC_LOG(ret, NULL);
-
- ret->size = 0;
- ret->str = NULL;
- ret->labels = NULL;
- ret->wire = NULL;
- ret->label_count = 0;
- ret->next = NULL;
- ret->prev = NULL;
-
- uint8_t label_size = 0;
- uint8_t *label_wire = NULL;
- uint8_t *labels = NULL;
- char *dname_str = NULL;
- uint label_count = 0;
- uint dname_length = 0;
- do {
- /* Read label size */
- if (!mem_read(&label_size,
- sizeof(uint8_t),
- src,
- src_size)) {
- fprintf(stderr, "Faulty read\n");
- return NULL;
- }
-
-// diag("%d", label_size);
-
- add_label(&labels, ret->size, &label_count);
-
- dname_length += label_size + 1;
-
- label_wire = malloc(sizeof(uint8_t) * (label_size + 2));
-
- if (label_wire == NULL) {
- ERR_ALLOC_FAILED;
- free(ret);
- return NULL;
- }
-
- label_wire[0] = label_size;
-
- /* Read label wire */
- if (!mem_read(label_wire + 1,
- sizeof(uint8_t) *
- label_size,
- src,
- src_size)) {
- free(label_wire);
- fprintf(stderr, "Faulty read\n");
- return NULL;
- }
-
- label_wire[label_size + 1] = '\0';
-
- dname_str = malloc(sizeof(char) * (label_size + 2));
-
- if (label_size != 0) {
- /* n - 1 : . */
- dname_str[label_size] = '.';
- dname_str[label_size + 1] = '\0';
-
- memcpy(dname_str, label_wire + 1, label_size);
- }
-
- if (ret->size == 0) {
- ret->wire = malloc(sizeof(uint8_t) * (label_size + 2));
- if (ret->wire == NULL) {
- ERR_ALLOC_FAILED;
- free(ret);
- return NULL;
- }
-
- memcpy(ret->wire, label_wire, label_size + 2);
-
- if (label_size != 0) {
-
- ret->str =
- malloc(sizeof(char) * (label_size + 2));
- if (ret->str == NULL) {
- ERR_ALLOC_FAILED;
- free(ret->wire);
- free(ret);
- return NULL;
- }
-
- memcpy(ret->str, dname_str, label_size + 2);
- }
-
- ret->size = label_size + 2;
- } else {
- /* Concatenate */
- void *p = realloc(ret->wire,
- ret->size + (label_size + 2));
- if (p == NULL) {
- ERR_ALLOC_FAILED;
- free(ret->wire);
- free(ret->labels);
- free(ret);
- return NULL;
- }
- ret->wire = p;
-
- /* TODO Safe concat? But I set the values myself, right? */
- /* or maybe memcpy... */
- strcat((char *)ret->wire, (char *)label_wire);
- assert(ret->wire);
-
-
- if (label_size != 0) {
-
- p = realloc(ret->str,
- ret->size + (label_size + 2));
- if (p == NULL) {
- ERR_ALLOC_FAILED;
- free(ret->wire);
- free(ret->str);
- free(ret->labels);
- free(ret);
- return NULL;
- }
- ret->str = p;
-
- strcat(ret->str, dname_str);
- assert(ret->str);
- }
-
- ret->size += label_size + 2;
- }
-
- free(label_wire);
- free(dname_str);
-
- } while (label_size != 0);
-
- /*!< \warning even wireformat is ended with 0 every time !!! */
-
- /* Root domain */
-// if (ret->size == 0) {
-// assert(ret->wire == NULL);
-
-// ret->wire = malloc(sizeof(uint8_t) * 1);
-// if (ret->wire == NULL) {
-// ERR_ALLOC_FAILED;
-// free(ret);
-// return NULL;
-// }
-
-// ret->wire[0] = '\0';
-
-// ret->labels = malloc(sizeof(uint8_t) * 1);
-// if (ret->labels == NULL) {
-// ERR_ALLOC_FAILED;
-// free(ret->wire);
-// free(ret);
-// return NULL;
-// }
-
-// ret->labels[0] = '\0';
-// ret->label_count = 1;
-// }
-
-// printf("OK: %s (%d)\n",ret->str, ret->size);
-
- ret->labels = labels;
- ret->size = ret->size - (label_count);
- ret->label_count = --label_count;
- ret->next = NULL;
- ret->prev = NULL;
-
- assert(ret != NULL);
-
- return ret;
-}
-
-/*!
- * \brief Reads dname label by label
- */
-static test_rdata_t *load_response_rdata(uint16_t type,
- const char **src,
- unsigned *src_size)
-{
-
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr, "reading rdata for type: %s\n",
- knot_rrtype_to_string(type));
-#endif
- /*
- * Binary format of rdata is as following:
- * [total_length(except for some types) - see below][rdata_item]+
- * Dname items are read label by label
- */
-
- test_rdata_t *rdata = malloc(sizeof(test_rdata_t));
-
- CHECK_ALLOC_LOG(rdata, NULL);
-
- rdata->count = 0;
- rdata->items = NULL;
- rdata->type = 0;
-
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- assert(desc != NULL);
-
- rdata->type = type;
-
- test_item_t *items =
- malloc(sizeof(test_item_t) * desc->length);
-
- if (items == NULL) {
- ERR_ALLOC_FAILED;
- free(rdata);
- return NULL;
- }
-
- /* TODO consider realloc */
-
- uint16_t total_raw_data_length = 0;
- uint8_t raw_data_length;
-
- /*
- * These types have no length, unfortunatelly (python library
- * does not provide this)
- */
- /* TODO the are more types with no length for sure ... */
-
- if (type != KNOT_RRTYPE_A &&
- type != KNOT_RRTYPE_NS &&
- type != KNOT_RRTYPE_AAAA) {
- if (!mem_read(&total_raw_data_length,
- sizeof(total_raw_data_length), src, src_size)) {
- free(rdata);
- free(items);
- fprintf(stderr, "Faulty read\n");
- return NULL;
- }
- }
-
- size_t total_read = 0;
-
- int i;
-
- /*
- * TODO save number of items
- * in the dump - of minor importance, however
- */
- for (i = 0; i < desc->length; i++) {
- if ((desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME)) {
- unsigned tmp_remaining = *src_size;
- items[i].dname = load_test_dname(src, src_size);
-
- if (items[i].dname == NULL) {
- fprintf(stderr, "Could not load DNAME!\n");
- free(rdata);
- free(items);
-
- /* TODO something like Marek's purge */
-
- return NULL;
- }
-
-// diag("Created DNAME %p item: %d %s %s\n",
-// items[i].dname, i, knot_rrtype_to_string(type),
-// items[i].dname->str);
-
- rdata->count++;
- items[i].type = TEST_ITEM_DNAME;
- items[i].raw_data = NULL;
- total_read += tmp_remaining - *src_size;
- } else {
- if (desc->wireformat[i] ==
- KNOT_RDATA_WF_BINARYWITHLENGTH) {
- if (!mem_read(&raw_data_length,
- sizeof(raw_data_length), src, src_size)) {
- return NULL;
- }
-
- total_read++;
-
- items[i].raw_data =
- malloc(sizeof(uint8_t) *
- (raw_data_length + 3));
-
- items[i].raw_data[0] =
- (uint16_t) raw_data_length + 1;
-
- /* let's store the length again */
-
- ((uint8_t *)items[i].raw_data)[2] =
- raw_data_length;
-
- if (!mem_read(((uint8_t *)
- items[i].raw_data) + 3,
- sizeof(uint8_t) * (raw_data_length),
- src, src_size)) {
- fprintf(stderr, "Wrong read!\n");
- return NULL;
- }
-
- rdata->count++;
- items[i].type = TEST_ITEM_RAW_DATA;
- items[i].dname = NULL;
- total_read += sizeof(uint8_t) * raw_data_length;
-/* printf("read len (from wire): %d\n",
- items[i].raw_data[0]);
- hex_print((char *)items[i].raw_data + 1,
- items[i].raw_data[0]);
- */
- } else {
- /* Other type than dname or BINARYWITHLENGTH */
- /* Set dname to NULL */
- items[i].dname = NULL;
-
- uint16_t size_fr_desc =
- (uint16_t)
- wireformat_size_load(desc->wireformat[i]);
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr, "reading %d\n", size_fr_desc);
-#endif
-
- if (size_fr_desc == 0) { /* unknown length */
-/* size_fr_desc = wireformat_size_n(type,
- items,
- i);
- */
- if ((i != desc->length - 1) &&
- desc->wireformat[i] !=
- KNOT_RDATA_WF_TEXT ) {
- fprintf(stderr,
- "I dont know how "
- "to parse this type: %d\n",
- type);
- return NULL;
- } else {
- size_fr_desc =
- total_raw_data_length -
- total_read;
- if (desc->wireformat[i] ==
- KNOT_RDATA_WF_TEXT) {
- break;
- }
-
-// fprintf(stderr,
-// "Guessed size: %d"
-// " for type: %s"
-// " and index: %d\n",
-// size_fr_desc,
-// knot_rrtype_to_string(type),
-// i);
- }
- }
-
- items[i].raw_data =
- malloc(sizeof(uint8_t) * size_fr_desc + 2);
-
-// diag("creating raw_data for item %d type %s %p\n",
-// i, knot_rrtype_to_string(type),
-// items[i].raw_data);
-
- if (items[i].raw_data == NULL) {
- ERR_ALLOC_FAILED;
- free(rdata);
- free(items);
- return NULL;
- }
-
- items[i].raw_data[0] = size_fr_desc;
-
- if (!mem_read(items[i].raw_data + 1,
- size_fr_desc,
- src, src_size)) {
- fprintf(stderr, "Wrong read\n!");
- return NULL;
- }
-
- rdata->count++;
- items[i].type = TEST_ITEM_RAW_DATA;
- items[i].dname = NULL;
- total_read += size_fr_desc;
-
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr,
- "read len (from descriptor): %d\n",
- items[i].raw_data[0]);
-/* hex_print((char *)items[i].raw_data + 1,
- items[i].raw_data[0]); */
-
- if (desc->zoneformat[i] ==
- KNOT_RDATA_ZF_ALGORITHM) {
- hex_print((char *)items[i].raw_data,
- items[i].raw_data[0] + 2);
- } else {
- hex_print((char *)items[i].raw_data,
- items[i].raw_data[0] + 2);
- }
-#endif
- }
- }
- }
-
-/* if (knot_rdata_set_items(rdata, items, i) != 0) {
- diag("Error: could not set items\n");
- return NULL;
- } */
-
- rdata->items = items;
-
- return rdata;
-}
-
-static test_rrset_t *load_response_rrset(const char **src, unsigned *src_size,
- char is_question)
-{
- test_rrset_t *rrset = NULL;
- uint16_t rrset_type = 0;
- uint16_t rrset_class = 0;
- uint32_t rrset_ttl = 0;
-
- /* Each rrset will only have one rdata entry */
-
- /*
- * RRSIGs will be read as separate RRSets because that's the way they
- * are stored in responses
- */
-
- /* Read owner first */
-
- uint8_t dname_size;
-// uint8_t *dname_wire = NULL;
-
- rrset = malloc(sizeof(test_rrset_t));
-
- rrset->rrsigs = NULL;
-
- CHECK_ALLOC_LOG(rrset, NULL);
-
- init_list(&rrset->rdata_list);
-
- /* TODO change in dump, size is useless now! */
- if (!mem_read(&dname_size, sizeof(dname_size), src, src_size)) {
- free(rrset);
- return NULL;
- }
-
-/* dname_wire = malloc(sizeof(uint8_t) * dname_size);
-
- CHECK_ALLOC_LOG(dname_wire, NULL);
-
- if (!mem_read(dname_wire, sizeof(uint8_t) * dname_size, src,
- src_size)) {
- free(dname_wire);
- return NULL;
- } */
-
- test_dname_t *owner = load_test_dname(src, src_size);
-
- if (owner == NULL) {
- free(rrset);
- return NULL;
- }
-
-#ifdef RESP_TEST_DEBUG
- {
- fprintf(stderr, "Got owner: %s", owner->str);
- }
-#endif
- /* Read other data */
-
- if (!mem_read(&rrset_type, sizeof(rrset_type), src, src_size)) {
- return NULL;
- }
-
- if (!mem_read(&rrset_class, sizeof(rrset_class), src, src_size)) {
- return NULL;
- }
-
- if (!is_question) {
- if (!mem_read(&rrset_ttl, sizeof(rrset_ttl), src, src_size)) {
- return NULL;
- }
- } else {
- rrset_ttl = 0;
- }
-
-// rrset = knot_rrset_new(owner, rrset_type, rrset_class, rrset_ttl);
-
- rrset->owner = owner;
- rrset->type = rrset_type;
- rrset->rclass = rrset_class;
- rrset->ttl = rrset_ttl;
-
- /* Question rrsets have no rdata */
-
- if (!is_question) {
- test_rdata_t *tmp_rdata;
-
- tmp_rdata = load_response_rdata(rrset->type, src, src_size);
-
- if (tmp_rdata == NULL) {
- fprintf(stderr,
- "Could not load rrset rdata - type: %d",
- rrset->type);
- free(rrset);
- return NULL;
- }
-
- assert(tmp_rdata->type == rrset->type);
-
- add_tail(&rrset->rdata_list, (node *)tmp_rdata);
- }
-
- return rrset;
-}
-
-static test_response_t *load_parsed_response(const char **src,
- unsigned *src_size)
-{
- /* Loads parsed response/query from binary format,
- * which is as following:
- * [id][qdcount][ancount][nscount][arcount]
- * [question_rrset+][answer_rrset+][authority_rrset+]
- * [additional_rrset]+
- */
-
- test_response_t *resp = malloc(sizeof(test_response_t));
-
- CHECK_ALLOC_LOG(resp, NULL);
-
- if (!mem_read(&resp->id, sizeof(resp->id), src, src_size)) {
- free(resp);
- return NULL;
- }
-
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr, "id %d\n", resp->id);
-#endif
-
- if (!mem_read(&resp->qdcount, sizeof(resp->qdcount), src, src_size)) {
- free(resp);
- return NULL;
- }
-
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr, "qdcount: %d\n", resp->qdcount);
-#endif
-
- if (!mem_read(&resp->ancount, sizeof(resp->ancount), src, src_size)) {
- free(resp);
- return NULL;
- }
-
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr, "ancount: %d\n", resp->ancount);
-#endif
-
- if (!mem_read(&resp->nscount, sizeof(resp->nscount), src, src_size)) {
- free(resp);
- return NULL;
- }
-
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr, "nscount: %d\n", resp->nscount);
-#endif
-
- if (!mem_read(&resp->arcount, sizeof(resp->arcount), src, src_size)) {
- free(resp);
- return NULL;
- }
-
-#ifdef RESP_TEST_DEBUG
- fprintf(stderr, "arcount: %d\n", resp->arcount);
-#endif
-
- if (!mem_read(&resp->query, sizeof(resp->query), src, src_size)) {
- free(resp);
- return NULL;
- }
-
- test_rrset_t **question_rrsets;
-
- question_rrsets = malloc(sizeof(test_rrset_t *) * resp->qdcount);
-
- for (int i = 0; i < resp->qdcount; i++) {
- question_rrsets[i] = load_response_rrset(src, src_size, 1);
- if (question_rrsets[i] == NULL) {
- fprintf(stderr, "Could not load question rrsets\n");
-
- for (int j = 0; j < i; j++) {
- free(question_rrsets[i]);
- }
- free(question_rrsets);
- free(resp);
- return NULL;
- }
- }
-
- /* only one question in our case */
-
- resp->qname = question_rrsets[0]->owner;
- resp->qtype = question_rrsets[0]->type;
- resp->qclass = question_rrsets[0]->rclass;
-
- resp->question = NULL;
-
-/* for (int i = 0; i < resp->qdcount; i++) {
- knot_rrset_free(&(question_rrsets[i]));
- } */
-
- free(question_rrsets);
-
- test_rrset_t *tmp_rrset = NULL;
-
- if (resp->ancount > 0) {
- resp->answer =
- malloc(sizeof(test_rrset_t *) * resp->ancount);
- } else {
- resp->answer = NULL;
- }
-
- for (int i = 0; i < resp->ancount; i++) {
- tmp_rrset = load_response_rrset(src, src_size, 0);
- resp->answer[i] = tmp_rrset;
- if (resp->answer[i] == NULL) {
- fprintf(stderr, "Could not load answer rrsets\n");
- free(resp->answer);
- free(resp);
- return NULL;
- }
- }
-
- if (resp->nscount > 0) {
- resp->authority =
- malloc(sizeof(test_rrset_t *) * resp->nscount);
- } else {
- resp->authority = NULL;
- }
-
- for (int i = 0; i < resp->nscount; i++) {
- tmp_rrset = load_response_rrset(src, src_size, 0);
- resp->authority[i] = tmp_rrset;
- if (resp->authority[i] == NULL) {
- fprintf(stderr, "Could not load authority rrsets\n");
- free(resp->authority);
- free(resp->answer);
- free(resp);
- return NULL;
- }
- }
-
- if (resp->arcount > 0) {
- resp->additional =
- malloc(sizeof(test_rrset_t *) * resp->arcount);
- } else {
- resp->additional = NULL;
- }
-
- for (int i = 0; i < resp->arcount; i++) {
- tmp_rrset = load_response_rrset(src, src_size, 0);
- if (tmp_rrset == NULL) {
- fprintf(stderr, "Could not load rrset (additional)\n");
- free(resp->additional);
- free(resp->authority);
- free(resp->answer);
- free(resp);
- return NULL;
- }
-
- resp->additional[i] = tmp_rrset;
- }
-
- /* this will never be used */
-
- resp->flags1 = 0;
- resp->flags2 = 0;
-
- return resp;
-}
-
-static void test_dname_free(test_dname_t **dname)
-{
- assert(dname != NULL && *dname != NULL);
- free((*dname)->labels);
-// free((*dname)->str);
- free((*dname)->wire);
-
- free(*dname);
- *dname = NULL;
-}
-
-static int wire_is_dname(uint type)
-{
- return (type == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- type == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- type == KNOT_RDATA_WF_LITERAL_DNAME);
-}
-
-static void test_rdata_free(test_rdata_t **rdata)
-{
- assert(rdata != NULL && *rdata != NULL);
-
- /* Free all the items */
- const knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type((*rdata)->type);
-
- for (int i = 0; i < (*rdata)->count; i++) {
- if ((wire_is_dname(desc->wireformat[i])) &&
- ((*rdata)->items[i].dname != NULL)) {
- test_dname_free(&(*rdata)->items[i].dname);
- } else if ((*rdata)->items[i].raw_data != NULL) {
- free((*rdata)->items[i].raw_data);
- (*rdata)->items[i].raw_data = NULL;
- }
- }
-// free((*rdata)->items);
-// free(*rdata);
- *rdata = NULL;
-}
-
-static void test_rrset_free(test_rrset_t **rrset)
-{
- assert(rrset && *rrset);
-
- test_dname_free(&(*rrset)->owner);
- /* Free all the rdatas */
- node *n = NULL, *nxt = NULL;
- WALK_LIST_DELSAFE(n, nxt, (*rrset)->rdata_list) {
- test_rdata_t *tmp_rdata = (test_rdata_t *)n;
- assert(tmp_rdata);
- if (tmp_rdata != NULL) {
- test_rdata_free(&tmp_rdata);
- }
- }
-
- free(*rrset);
- *rrset = NULL;
-}
-
-static void test_response_free(test_response_t **response)
-{
- assert(response && *response);
- if ((*response)->qname != NULL) {
- test_dname_free(&(*response)->qname);
- }
-
- if ((*response)->additional != NULL) {
- for (int j = 0; j < (*response)->arcount; j++) {
- test_rrset_free(&((*response)->additional[j]));
- }
-
- free((*response)->additional);
- }
-
- if ((*response)->answer != NULL) {
- for (int j = 0; j < (*response)->ancount; j++) {
- test_rrset_free(&((*response)->answer[j]));
- }
-
- free((*response)->answer);
- }
-
- if ((*response)->authority != NULL) {
- for (int j = 0; j < (*response)->nscount; j++) {
- test_rrset_free(&((*response)->authority[j]));
- }
-
- free((*response)->authority);
- }
-
- free((*response));
- *response = NULL;
-}
-
-static void get_and_save_data_from_rdata(test_rdata_t *rdata,
- test_data_t *data, uint16_t type)
-{
- /* We only want to extract dnames */
- const knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
-
- if (rdata->count == 0) {
-// diag("Rdata count not set!\n");
- rdata->count = desc->length;
- }
-
- for(int i = 0; i < rdata->count; i++) {
- if ((desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME)) {
- add_tail(&data->dname_list,
- (node *)rdata->items[i].dname);
- test_item_t *temp_item = malloc(sizeof(test_item_t));
- temp_item->dname = rdata->items[i].dname;
- temp_item->type = TEST_ITEM_DNAME;
- temp_item->raw_data = NULL;
- add_tail(&data->item_list, (node *)temp_item);
- } else {
- test_item_t *temp_item = malloc(sizeof(test_item_t));
- temp_item->dname = NULL;
- temp_item->type = TEST_ITEM_RAW_DATA;
- temp_item->raw_data = rdata->items[i].raw_data;
- add_tail(&data->item_list, (node *)temp_item);
- }
- }
-}
-
-static void get_and_save_data_from_rrset(const test_rrset_t *rrset,
- test_data_t *data)
-{
-// knot_rrtype_descriptor_t *desc =
-// knot_rrtype_descriptor_by_type(rrset->type);
- /* RDATA are in a list. */
- node *n = NULL;
- int i = 0;
- WALK_LIST(n, rrset->rdata_list) {
- test_rdata_t *tmp_rdata = (test_rdata_t *)n;
- assert(tmp_rdata);
- assert(&data->rdata_list);
- assert(&data->rdata_list != &rrset->rdata_list);
- assert(tmp_rdata->type == rrset->type);
-
- test_rdata_t *new_rdata = malloc(sizeof(test_rdata_t));
- new_rdata->count = tmp_rdata->count;
- new_rdata->items = tmp_rdata->items;
- new_rdata->type = tmp_rdata->type;
-
- add_tail(&data->rdata_list, (node *)new_rdata);
- get_and_save_data_from_rdata(tmp_rdata, data, rrset->type);
- i++;
- }
- assert(i == 1);
-}
-
-static int add_rrset_to_node(const test_rrset_t *rrset, test_data_t *data)
-{
- /* First, create node from rrset */
- test_node_t *tmp_node = malloc(sizeof(test_node_t));
- memset(tmp_node, 0, sizeof(test_node_t));
- CHECK_ALLOC_LOG(tmp_node, -1);
-
- tmp_node->owner = rrset->owner;
- tmp_node->parent = NULL;
- tmp_node->rrset_count = 0;
-
- /* Will not be used in list now */
- tmp_node->prev = NULL;
- tmp_node->next = NULL;
-
-
-/* tmp_node->avl_left = NULL;
- tmp_node->avl_right = NULL;
- tmp_node->avl_height = 0; */
-
- test_node_t *found_node =
- TREE_FIND(data->node_tree, test_node, avl, tmp_node);
-
- if (found_node == NULL) {
- /* Insert new node with current rrset */
- init_list(&tmp_node->rrset_list);
- add_tail(&tmp_node->rrset_list, (node *)rrset);
- tmp_node->rrset_count++;
-
- TREE_INSERT(data->node_tree, test_node, avl, tmp_node);
- } else {
- free(tmp_node);
- /* append rrset */
-
- add_tail(&found_node->rrset_list, (node *)rrset);
- found_node->rrset_count++;
- }
-
- return 0;
-}
-
-static void get_and_save_data_from_response(const test_response_t *response,
- test_data_t *data)
-{
- /* Go through all the rrsets in the response */
-
- for (int i = 0; i < response->ancount; i++) {
- assert(response->answer[i]);
- /* Add rrset to the list of rrsets - there will be duplicates
- * But not the same pointers */
- add_tail(&data->rrset_list, (node *)response->answer[i]);
- get_and_save_data_from_rrset(response->answer[i], data);
- if (add_rrset_to_node(response->answer[i], data) != 0) {
- return;
- }
- }
-
- for (int i = 0; i < response->arcount; i++) {
- /* Add rrset to the list of rrsets - there will be duplicates */
- assert(response->additional[i]);
- add_tail(&data->rrset_list, (node *)response->additional[i]);
- get_and_save_data_from_rrset(response->additional[i], data);
- if (add_rrset_to_node(response->additional[i], data) != 0) {
- return;
- }
- }
-
- for (int i = 0; i < response->nscount; i++) {
- assert(response->authority[i]);
- /* Add rrset to the list of rrsets - there will be duplicates */
- add_tail(&data->rrset_list, (node *)response->authority[i]);
- get_and_save_data_from_rrset(response->authority[i], data);
- if (add_rrset_to_node(response->authority[i], data) != 0) {
- return;
- }
- }
-
-// for (int i = 0; i < response->qdcount; i++) {
-// /* Add rrset to the list of rrsets - there will be duplicates */
-// add_tail(&data->rrset_list, (node *)response->question[i]);
-// get_and_save_data_from_rrset(response->question[i], data);
-// }
-}
-
-static int load_parsed_responses(test_data_t *data, uint32_t *count,
- const char* src, unsigned src_size)
-{
- if (!mem_read(count, sizeof(*count), &src, &src_size)) {
- fprintf(stderr, "Wrong read\n");
- return -1;
- }
-
-// *responses = malloc(sizeof(test_response_t *) * *count);
-
- for (int i = 0; i < *count; i++) {
- test_response_t *tmp_response =
- load_parsed_response(&src, &src_size);
-
- if (tmp_response == NULL) {
- fprintf(stderr, "Could not load response - %d"
- "- returned NULL\n",
- i);
- return -1;
- }
-
- if (tmp_response->query) {
- add_tail(&data->query_list, (node *)tmp_response);
- } else {
- add_tail(&data->response_list, (node *)tmp_response);
- }
-
- /* Create new node */
- test_response_t *resp = malloc(sizeof(test_response_t));
- assert(resp);
- memcpy(resp, tmp_response, sizeof(test_response_t));
- add_tail(&data->packet_list,
- (node *)resp);
- }
-
- return 0;
-}
-
-//void free_parsed_responses(test_response_t ***responses, uint32_t *count)
-//{
-// if (*responses != NULL) {
-// for (int i = 0; i < *count; i++) {
-// free_parsed_response((*responses)[i]);
-// }
-// free(*responses);
-// }
-//}
-
-static int compare_nodes(test_node_t *node1, test_node_t *node2)
-{
- assert(node1->owner && node2->owner);
- /*!< \warning Wires have to be \0 terminated. */
- return (strcmp((char *)node1->owner->wire, (char *)node2->owner->wire));
-}
-
-static int init_data(test_data_t *data)
-{
- if (data == NULL) {
- return 0;
- }
-
- /* Initialize all the lists */
- init_list(&data->dname_list);
- init_list(&data->edns_list);
- init_list(&data->node_list);
- init_list(&data->response_list);
- init_list(&data->rdata_list);
- init_list(&data->rrset_list);
- init_list(&data->item_list);
- init_list(&data->raw_response_list);
- init_list(&data->raw_query_list);
- init_list(&data->raw_packet_list);
- init_list(&data->query_list);
- init_list(&data->packet_list);
-
- data->node_tree = malloc(sizeof(avl_tree_test_t));
- CHECK_ALLOC_LOG(data->node_tree, 0);
-
- TREE_INIT(data->node_tree, compare_nodes);
-
- return 1;
-}
-
-static void print_stats(test_data_t *data)
-{
- uint resp_count = 0, dname_count = 0, node_count = 0,
- rdata_count = 0, rrset_count = 0, item_count = 0, query_count = 0,
- raw_query_count = 0, response_count = 0, packet_count = 0,
- raw_packet_count = 0, raw_response_count = 0;
-
- node *n = NULL; /* Will not be used */
-
- WALK_LIST(n, data->response_list) {
- resp_count++;
- }
-
- WALK_LIST(n, data->rrset_list) {
-// node *tmp = NULL;
-// assert(((test_rrset_t *)n)->owner);
-// WALK_LIST(tmp, ((test_rrset_t *)n)->rdata_list) {
-// test_rdata_t *rdata = (test_rdata_t *)tmp;
-// assert(rdata->type == ((test_rrset_t *)n)->type);
-// }
- rrset_count++;
- }
-
- WALK_LIST(n, data->rdata_list) {
- rdata_count++;
- }
-
- WALK_LIST(n, data->dname_list) {
- dname_count++;
- }
-
- WALK_LIST(n, data->node_list) {
- node_count++;
- }
-
- WALK_LIST(n, data->item_list) {
- item_count++;
- }
-
- WALK_LIST(n, data->raw_response_list) {
- raw_response_count++;
- }
-
- WALK_LIST(n, data->query_list) {
- query_count++;
- }
-
- WALK_LIST(n, data->response_list) {
- response_count++;
- }
-
- WALK_LIST(n, data->raw_query_list) {
- raw_query_count++;
- }
-
- WALK_LIST(n, data->packet_list) {
- packet_count++;
- }
-
- WALK_LIST(n, data->raw_packet_list) {
- raw_packet_count++;
- }
-
- printf("Loaded: Responses: %d RRSets: %d RDATAs: %d Dnames: %d "
- "Nodes: %d Items: %d Raw_responses: %d Queries: %d \n"
- "Raw_queries; %d Total packets: %d Total_raw_packets: %d\n", resp_count, rrset_count,
- rdata_count, dname_count, node_count, item_count,
- raw_response_count, query_count, raw_query_count, packet_count,
- raw_packet_count);
-}
-
-static void save_node_to_list(test_node_t *n, void *p)
-{
- test_data_t *data = (test_data_t *)p;
-
- add_tail(&data->node_list, (node *)n);
-}
-
-static void del_node(test_node_t *n, void *p)
-{
-// test_data_t *data = (test_data_t *)p;
- free(n);
-}
-
-
-void free_data(test_data_t **data)
-{
- assert(data && *data);
- /* We will free all the data using responses
- * (others are just references )*/
- node *n = NULL, *nxt = NULL;
- WALK_LIST_DELSAFE(n, nxt, (*data)->response_list) {
- test_response_t *tmp_response = (test_response_t *)n;
- if (tmp_response != NULL) {
- test_response_free(&tmp_response);
- }
- }
-
- TREE_POST_ORDER_APPLY((*data)->node_tree, test_node, avl, del_node,
- NULL);
-
- free((*data)->node_tree);
-
- free(*data);
- *data = NULL;
-}
-
-test_data_t *create_test_data_from_dump()
-{
- test_data_t *ret = malloc(sizeof(test_data_t));
- CHECK_ALLOC_LOG(ret, NULL);
-
- if (!init_data(ret)) {
- free(ret);
- return NULL;
- }
-
- uint32_t raw_packet_count = 0;
-
- if (load_raw_packets(ret, &raw_packet_count, raw_data_rc,
- raw_data_rc_size) != 0) {
- fprintf(stderr, "Could not load raw_data, quitting");
- /* TODO walk the lists*/
- free(ret);
- return NULL;
- }
-
- uint32_t response_count = 0;
-
- if (load_parsed_responses(ret, &response_count, parsed_data_rc,
- parsed_data_rc_size) != 0) {
- fprintf(stderr, "Could not load responses, quitting");
- /* TODO walk the lists*/
- free(ret);
- return NULL;
- }
-
- /* For each parsed response - create more data from it. */
- /* Probably not the most effective way, but it is better than to
- * rewrite most of the code .*/
-
- node *n = NULL;
-
- WALK_LIST(n , ret->response_list) {
- get_and_save_data_from_response((test_response_t *)n, ret);
- }
-
- /* Create list from AVL tree */
-
- TREE_FORWARD_APPLY(ret->node_tree, test_node, avl,
- save_node_to_list, ret);
-
- print_stats(ret);
-
- return ret;
-}
diff --git a/src/tests/libknot/realdata/libknot_tests_loader_realdata.h b/src/tests/libknot/realdata/libknot_tests_loader_realdata.h
deleted file mode 100644
index 8f57944..0000000
--- a/src/tests/libknot/realdata/libknot_tests_loader_realdata.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef KNOT_TESTS_LOADER_H
-#define KNOT_TESTS_LOADER_H
-
-#include <stdint.h>
-
-#include "libknot/common.h"
-#include "common/lists.h"
-#include "common/tree.h"
-
-
-/* Parsed raw packet*/
-struct test_raw_packet {
- struct node *next, *prev;
- uint size;
- uint8_t *data;
-};
-
-typedef struct test_raw_packet test_raw_packet_t;
-
-/* Test type definitions */
-
-struct test_dname {
- struct node *next, *prev;
- char *str;
- uint8_t *wire;
- uint size;
- uint8_t *labels;
- short label_count;
-};
-
-typedef struct test_dname test_dname_t;
-
-struct test_edns_options {
- struct node *next, *prev;
- uint16_t code;
- uint16_t length;
- uint8_t *data;
-};
-
-struct test_edns {
- struct node *next, *prev;
- struct test_edns_options *options;
- uint16_t payload;
- uint8_t ext_rcode;
- uint8_t version;
- uint16_t flags;
- uint16_t *wire;
- short option_count;
- short options_max;
- short size;
-};
-
-typedef struct test_edns test_edns_t;
-
-typedef TREE_HEAD(avl_tree_test, test_node) avl_tree_test_t;
-
-struct test_node {
- struct node *next, *prev;
- test_dname_t *owner;
- short rrset_count;
- struct test_node *parent;
- list rrset_list;
-
- TREE_ENTRY(test_node) avl;
-};
-
-typedef struct test_node test_node_t;
-
-enum item_type {
- TEST_ITEM_DNAME,
- TEST_ITEM_RAW_DATA
-};
-
-typedef enum item_type item_type_t;
-
-struct test_item {
- uint16_t *raw_data;
- test_dname_t *dname;
- item_type_t type;
-};
-
-typedef struct test_item test_item_t;
-
-struct test_rdata {
- struct node *next, *prev;
- uint count;
- uint type; /*!< Might be handy */
- test_item_t *items;
-};
-
-typedef struct test_rdata test_rdata_t;
-
-struct test_rrset {
- struct node *next, *prev;
- test_dname_t *owner;
- uint16_t type;
- uint16_t rclass;
- uint32_t ttl;
- struct test_rrset *rrsigs;
- uint16_t *wire;
- list rdata_list;
-};
-
-typedef struct test_rrset test_rrset_t;
-
-struct test_response {
- struct node *next, *prev;
- /* This is basically same thing as actual response structure */
- uint16_t query;
- test_dname_t *qname;
- uint16_t qclass;
- uint16_t qtype;
- uint16_t id;
- uint8_t flags1;
- uint8_t flags2;
- uint16_t qdcount;
- uint16_t ancount;
- uint16_t nscount;
- uint16_t arcount;
-
- /* Arrays of rrsets */
-
- test_rrset_t **question;
- test_rrset_t **answer;
- test_rrset_t **authority;
- test_rrset_t **additional;
-
- short size;
-
- /* what about the rest of the values?
- * they cannot be modified from API, but this is probably the best
- * place to test them as well */
-};
-
-typedef struct test_response test_response_t;
-
-/*!< \brief contains lists of all the structures */
-struct test_data {
- list dname_list;
- list edns_list;
- list rdata_list;
- list node_list;
- list rrset_list;
- list response_list;
- list raw_response_list;
- list query_list;
- list raw_query_list;
- list item_list;
- /* responses and queries together */
- list packet_list;
- list raw_packet_list;
-
- avl_tree_test_t *node_tree;
-};
-
-typedef struct test_data test_data_t;
-
-/*!< \brief Parses resource with data and creates all possible structures. */
-test_data_t *create_test_data_from_dump();
-
-test_data_t *data_for_knot_tests;
-
-#endif // KNOT_TESTS_LOADER_H
diff --git a/src/tests/libknot/realdata/unittests_libknot_realdata.c b/src/tests/libknot/realdata/unittests_libknot_realdata.c
deleted file mode 100644
index e557c43..0000000
--- a/src/tests/libknot/realdata/unittests_libknot_realdata.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-//#include "knot/common.h"
-#include "common/libtap/tap_unit.h"
-
-#include "tests/libknot/realdata/libknot_tests_loader_realdata.h"
-
-// Units to test
-#include "tests/libknot/realdata/libknot/dname_tests_realdata.h"
-#include "tests/libknot/realdata/libknot/response_tests_realdata.h"
-//#include "libknot/edns_tests.h"
-#include "tests/libknot/realdata/libknot/node_tests_realdata.h"
-#include "tests/libknot/realdata/libknot/rdata_tests_realdata.h"
-//#include "libknot/response_tests_realdata.h"
-#include "tests/libknot/realdata/libknot/rrset_tests_realdata.h"
-//#include "libknot/zone_tests_realdata.h"
-#include "tests/libknot/realdata/libknot/zonedb_tests_realdata.h"
-#include "tests/libknot/realdata/libknot/packet_tests_realdata.h"
-
-#include "common/lists.h"
-// Run all loaded units
-int main(int argc, char *argv[])
-{
- data_for_knot_tests = create_test_data_from_dump();
-
- if (data_for_knot_tests == NULL) {
- diag("Data could not be loaded!");
- return 0;
- }
-
- // Open log
-// log_init(LOG_UPTO(LOG_ERR), LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING));
-
- // Build test set
- unit_api *tests[] = {
-
- /* DNS units */
-// &cuckoo_tests_api, //! Cuckoo hashing unit
- &dname_tests_api, //! DNS library (dname) unit
-// &edns_tests_api, //! DNS library (EDNS0) unit
- &node_tests_api, //! DNS library (node) unit
- &rdata_tests_api, //! DNS library (rdata) unit
- &packet_tests_api,
-// &response_tests_api, //! DNS library (response) unit
- &response_tests_api, //! DNS library (response) unit
- &rrset_tests_api, //! DNS library (rrset) unit
-// &zone_tests_api, //! DNS library (zone) unit
-// &zonedb_tests_api, //! DNS library (zonedb) unit
- NULL
- };
-
- // Plan number of tests
- int id = 0;
- int test_count = 0;
- note("Units:");
- while (tests[id] != NULL) {
- note("- %s : %d tests", tests[id]->name,
- tests[id]->count(argc, argv));
- test_count += tests[id]->count(argc, argv);
- ++id;
- }
-
- plan(test_count);
-
- // Run tests
- id = 0;
- while (tests[id] != NULL) {
- diag("Testing unit: %s", tests[id]->name);
- tests[id]->run(argc, argv);
- ++id;
- }
-
-// log_close();
-
- // Evaluate
- return exit_status();
-}
-
diff --git a/src/tests/libknot/rrset_tests.c b/src/tests/libknot/rrset_tests.c
new file mode 100644
index 0000000..d140681
--- /dev/null
+++ b/src/tests/libknot/rrset_tests.c
@@ -0,0 +1,1467 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <assert.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "tests/libknot/rrset_tests.h"
+#include "common/descriptor.h"
+#include "common/errcode.h"
+#include "common/print.h"
+#include "libknot/rrset.h"
+#include "libknot/util/wire.h"
+#include "common/mempattern.h"
+
+static int knot_rrset_tests_count(int argc, char *argv[]);
+static int knot_rrset_tests_run(int argc, char *argv[]);
+
+/*! Exported unit API.
+ */
+unit_api rrset_tests_api = {
+ "libknot/rrset", //! Unit name
+ &knot_rrset_tests_count, //! Count scheduled tests
+ &knot_rrset_tests_run //! Run scheduled tests
+};
+
+/*
+ * Unit implementation.
+ */
+
+enum rrset_test_const {
+ TEST_RRSET_COUNT = 14,
+ TEST_RDATA_COUNT = 10,
+ TEST_DNAME_COUNT = 11,
+
+ TEST_RDATA_A_LESS = 0,
+ TEST_RDATA_A_GT = 1,
+ TEST_RDATA_NS_LESS = 2,
+ TEST_RDATA_NS_GT = 3,
+ TEST_RDATA_MX_DNAME_LESS = 4,
+ TEST_RDATA_MX_DNAME_GT = 5,
+ TEST_RDATA_MX_BIN_LESS = 6,
+ TEST_RDATA_MX_BIN_GT = 7,
+ TEST_RDATA_MINFO1 = 8,
+ TEST_RDATA_MINFO2 = 9,
+
+ TEST_RRSET_A_LESS = 0,
+ TEST_RRSET_A_GT = 1,
+ TEST_RRSET_MERGE_UNIQUE1 = 0,
+ TEST_RRSET_MERGE_UNIQUE2 = 1,
+ TEST_RRSET_MERGE_RESULT1 = 10,
+ TEST_RRSET_NS_LESS = 2,
+ TEST_RRSET_NS_GT = 3,
+ TEST_RRSET_MX_BIN_LESS = 4,
+ TEST_RRSET_MX_BIN_GT = 5,
+ TEST_RRSET_MX_DNAME_LESS = 6,
+ TEST_RRSET_MX_DNAME_GT = 7,
+ TEST_RRSET_MINFO = 8,
+ TEST_RRSET_MINFO_MULTIPLE1 = 9,
+ TEST_RRSET_MINFO_MULTIPLE2 = 13,
+ TEST_RRSET_OWNER_LESS = 11,
+ TEST_RRSET_OWNER_GT = 12,
+
+ CHECK_LAST_INDEX = 0,
+ OMMIT_LAST_INDEX = 1,
+ TEST_DNAME_GENERIC = 0,
+ TEST_DNAME_LESS = 1,
+ TEST_DNAME_GREATER = 2
+};
+
+static char *test_dname_strings[TEST_DNAME_COUNT] = {
+ "a.dname.com.",
+ "b.dname.com.",
+ "c.dname.com.",
+ "d.dname.com.",
+ "e.dname.com.",
+ "f.dname.com.",
+ "ns1.nic.cz.",
+ "ns2.nic.cz.",
+ "ns3.nic.cz.",
+ "ns4.nic.cz.",
+ "ns5.nic.cz."
+};
+
+static knot_dname_t *test_dnames[TEST_DNAME_COUNT];
+
+struct test_rdata {
+ uint8_t *rdata; // RDATA in knot internal format
+ uint8_t *wire; // RDATA in wireformat
+ uint16_t size; // RDATA internal size
+ uint16_t wire_size; // Wireformat size
+};
+
+typedef struct test_rdata test_rdata_t;
+
+struct test_rrset {
+ int owner_id; // Owners have to be dynamically allocated, IDs used to connect.
+ knot_rrset_t rrset; // Dynamically created knot_rrset_t structure.
+ uint8_t *header_wire; // Owner, class, TTL.
+ size_t header_wire_size; // Header size.
+ size_t rr_count; // RR count.
+ int test_rdata_ids[16]; // RDATA IDs - will be used to assign RDATA.
+ test_rdata_t **test_rdata; // Dynamically created test RDATA.
+};
+
+typedef struct test_rrset test_rrset_t;
+
+/* Artificial RDATA definitions: */
+static test_rdata_t test_rdata_array[TEST_RDATA_COUNT] = {
+ [TEST_RDATA_A_LESS] = {(uint8_t *)"\x1\x1\x1\0", (uint8_t *)"\x1\x1\x1\0", 4, 4},
+ [TEST_RDATA_A_GT] = {(uint8_t *)"\x1\x1\x1\1", (uint8_t *)"\x1\x1\x1\1", 4, 4},
+ [TEST_RDATA_NS_LESS] = {NULL, NULL, sizeof(knot_dname_t *), 0},
+ [TEST_RDATA_NS_GT] = {NULL, NULL, sizeof(knot_dname_t *), 0},
+ [TEST_RDATA_MX_DNAME_LESS] = {NULL, NULL, sizeof(knot_dname_t *) + 2, 0},
+ [TEST_RDATA_MX_DNAME_GT] = {NULL, NULL, sizeof(knot_dname_t *) + 2, 0},
+ [TEST_RDATA_MX_BIN_LESS] = {NULL, NULL, sizeof(knot_dname_t *) + 2, 0},
+ [TEST_RDATA_MX_BIN_GT] = {NULL, NULL, sizeof(knot_dname_t *) + 2, 0},
+ [TEST_RDATA_MINFO1] = {NULL, NULL, sizeof(knot_dname_t *) * 2, 0},
+ [TEST_RDATA_MINFO2] = {NULL, NULL, sizeof(knot_dname_t *) * 2, 0},
+};
+
+
+test_rrset_t test_rrset_array[TEST_RRSET_COUNT] = {
+ [TEST_RRSET_A_LESS] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_A, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_A_LESS}, NULL},
+ [TEST_RRSET_A_GT] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_A, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_A_GT}, NULL},
+ [TEST_RRSET_NS_LESS] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_NS, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_NS_LESS}, NULL},
+ [TEST_RRSET_NS_GT] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_NS, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_NS_GT}, NULL},
+ [TEST_RRSET_MX_DNAME_LESS] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_MX, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_MX_DNAME_LESS}, NULL},
+ [TEST_RRSET_MX_DNAME_GT] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_MX, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_MX_DNAME_GT}, NULL},
+ [TEST_RRSET_MX_BIN_LESS] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_MX, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_MX_BIN_LESS}, NULL},
+ [TEST_RRSET_MX_BIN_GT] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_MX, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_MX_BIN_GT}, NULL},
+ [TEST_RRSET_MINFO] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_MINFO, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_MINFO1}, NULL},
+ [TEST_RRSET_MINFO_MULTIPLE1] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_MINFO, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 2, {TEST_RDATA_MINFO1, TEST_RDATA_MINFO2}, NULL},
+ [TEST_RRSET_MINFO_MULTIPLE2] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_MINFO, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 2, {TEST_RDATA_MINFO2, TEST_RDATA_MINFO1}, NULL},
+ [TEST_RRSET_MERGE_RESULT1] = {TEST_DNAME_GENERIC, {NULL, KNOT_RRTYPE_A, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 2, {TEST_RDATA_A_LESS, TEST_RDATA_A_GT}, NULL},
+ [TEST_RRSET_OWNER_LESS] = {TEST_DNAME_LESS, {NULL, KNOT_RRTYPE_A, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_A_LESS}, NULL},
+ [TEST_RRSET_OWNER_GT] = {TEST_DNAME_GREATER, {NULL, KNOT_RRTYPE_A, KNOT_CLASS_IN, 3600, NULL, NULL, 0, NULL},
+ NULL, 0, 1, {TEST_RDATA_A_LESS}, NULL}
+};
+
+static void create_test_dnames()
+{
+ for (int i = 0; i < TEST_DNAME_COUNT; i++) {
+ test_dnames[i] =
+ knot_dname_new_from_str(test_dname_strings[i],
+ strlen(test_dname_strings[i]),
+ NULL);
+ }
+}
+
+static void init_test_rdata_with_dname(uint8_t **rdata, uint16_t *rdata_size,
+ uint8_t **wire, uint16_t *wire_size,
+ size_t pos, size_t wire_pos,
+ size_t alloc_size,
+ size_t wire_alloc_size,
+ knot_dname_t *dname)
+{
+ if (pos == 0) {
+ *rdata = xmalloc(alloc_size);
+ *rdata_size = 0;
+ *wire = xmalloc(wire_alloc_size);
+ *wire_size = 0;
+ }
+ memcpy(*rdata + pos, &dname, sizeof(knot_dname_t *));
+ *rdata_size += sizeof(knot_dname_t *);
+ memcpy(*wire + wire_pos, dname->name, dname->size);
+ *wire_size += dname->size;
+
+ knot_dname_retain(dname);
+}
+
+static void init_test_rdata_with_binary(uint8_t **rdata, uint16_t *rdata_size,
+ uint8_t **wire, uint16_t *wire_size,
+ size_t pos, size_t wire_pos,
+ size_t alloc_size,
+ size_t wire_alloc_size,
+ const void *data, size_t data_size)
+{
+ if (pos == 0) {
+ // New structure, allocate.
+ *rdata = xmalloc(alloc_size);
+ *rdata_size = 0;
+ *wire = xmalloc(wire_alloc_size);
+ *wire_size = 0;
+ }
+ memcpy(*rdata + pos, data, data_size);
+ *rdata_size += data_size;
+ memcpy(*wire + wire_pos, data, data_size);
+ *wire_size += data_size;
+}
+
+static void create_test_rdata()
+{
+ /* NS, MX and MINFO types need an init. */
+
+ /* NS RDATA DNAME = a.dname.com. */
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_NS_LESS].rdata,
+ &test_rdata_array[TEST_RDATA_NS_LESS].size,
+ &test_rdata_array[TEST_RDATA_NS_LESS].wire,
+ &test_rdata_array[TEST_RDATA_NS_LESS].wire_size,
+ 0, 0, sizeof(knot_dname_t *),
+ test_dnames[0]->size, test_dnames[0]);
+
+ /* NS RDATA DNAME = b.dname.com. */
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_NS_GT].rdata,
+ &test_rdata_array[TEST_RDATA_NS_GT].size,
+ &test_rdata_array[TEST_RDATA_NS_GT].wire,
+ &test_rdata_array[TEST_RDATA_NS_GT].wire_size,
+ 0, 0, sizeof(knot_dname_t *),
+ test_dnames[1]->size, test_dnames[1]);
+
+ /* MX RDATA - short = 10 DNAME = a.dname.com. */
+ uint16_t id = htobe16(10);
+ init_test_rdata_with_binary(&test_rdata_array[TEST_RDATA_MX_DNAME_LESS].rdata,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_LESS].size,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_LESS].wire,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_LESS].wire_size,
+ 0, 0, sizeof(knot_dname_t *) + 2,
+ test_dnames[1]->size + 2, &id, 2);
+
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_MX_DNAME_LESS].rdata,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_LESS].size,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_LESS].wire,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_LESS].wire_size,
+ 2, 2, sizeof(knot_dname_t *),
+ test_dnames[1]->size, test_dnames[0]);
+
+ /* MX RDATA - short = 10 DNAME = b.dname.com. */
+ init_test_rdata_with_binary(&test_rdata_array[TEST_RDATA_MX_DNAME_GT].rdata,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_GT].size,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_GT].wire,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_GT].wire_size,
+ 0, 0, sizeof(knot_dname_t *) + 2,
+ test_dnames[1]->size + 2, &id, 2);
+
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_MX_DNAME_GT].rdata,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_GT].size,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_GT].wire,
+ &test_rdata_array[TEST_RDATA_MX_DNAME_GT].wire_size,
+ 2, 2, sizeof(knot_dname_t *),
+ test_dnames[1]->size, test_dnames[1]);
+
+ test_rdata_array[TEST_RDATA_MX_BIN_LESS] = test_rdata_array[TEST_RDATA_MX_DNAME_LESS];
+ knot_dname_retain(test_dnames[1]);
+
+ /* MX RDATA - short = 20 DNAME = b.dname.com. */
+ id = htobe16(20);
+ init_test_rdata_with_binary(&test_rdata_array[TEST_RDATA_MX_BIN_GT].rdata,
+ &test_rdata_array[TEST_RDATA_MX_BIN_GT].size,
+ &test_rdata_array[TEST_RDATA_MX_BIN_GT].wire,
+ &test_rdata_array[TEST_RDATA_MX_BIN_GT].wire_size,
+ 0, 0, sizeof(knot_dname_t *) + 2,
+ test_dnames[1]->size + 2, &id, 2);
+
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_MX_BIN_GT].rdata,
+ &test_rdata_array[TEST_RDATA_MX_BIN_GT].size,
+ &test_rdata_array[TEST_RDATA_MX_BIN_GT].wire,
+ &test_rdata_array[TEST_RDATA_MX_BIN_GT].wire_size,
+ 2, 2, sizeof(knot_dname_t *),
+ test_dnames[1]->size, test_dnames[1]);
+
+ /* MINFO RRs. */
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_MINFO1].rdata,
+ &test_rdata_array[TEST_RDATA_MINFO1].size,
+ &test_rdata_array[TEST_RDATA_MINFO1].wire,
+ &test_rdata_array[TEST_RDATA_MINFO1].wire_size,
+ 0, 0, sizeof(knot_dname_t *) * 2,
+ test_dnames[0]->size + test_dnames[1]->size,
+ test_dnames[0]);
+
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_MINFO1].rdata,
+ &test_rdata_array[TEST_RDATA_MINFO1].size,
+ &test_rdata_array[TEST_RDATA_MINFO1].wire,
+ &test_rdata_array[TEST_RDATA_MINFO1].wire_size,
+ sizeof(knot_dname_t *), test_dnames[0]->size,
+ sizeof(knot_dname_t *),
+ test_dnames[1]->size, test_dnames[1]);
+
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_MINFO2].rdata,
+ &test_rdata_array[TEST_RDATA_MINFO2].size,
+ &test_rdata_array[TEST_RDATA_MINFO2].wire,
+ &test_rdata_array[TEST_RDATA_MINFO2].wire_size,
+ 0, 0, sizeof(knot_dname_t *) * 2,
+ test_dnames[2]->size + test_dnames[3]->size,
+ test_dnames[2]);
+
+ init_test_rdata_with_dname(&test_rdata_array[TEST_RDATA_MINFO2].rdata,
+ &test_rdata_array[TEST_RDATA_MINFO2].size,
+ &test_rdata_array[TEST_RDATA_MINFO2].wire,
+ &test_rdata_array[TEST_RDATA_MINFO2].wire_size,
+ sizeof(knot_dname_t *), test_dnames[2]->size,
+ sizeof(knot_dname_t *),
+ test_dnames[3]->size, test_dnames[3]);
+}
+
+static void create_test_rrsets()
+{
+ for (int i = 0; i < TEST_RRSET_COUNT; i++) {
+ /* Create memory representation. */
+ test_rrset_t *test_rrset = &test_rrset_array[i];
+ /* Assign owner. */
+ test_rrset->rrset.owner = test_dnames[test_rrset->owner_id];
+
+ /* Create wire representation. */
+
+ /* Create header wire. */
+ test_rrset->header_wire_size = test_rrset->rrset.owner->size + 8;
+ test_rrset->header_wire =
+ xmalloc(test_rrset->header_wire_size);
+ /* Copy owner wire to header wire. */
+ memcpy(test_rrset->header_wire, test_rrset->rrset.owner->name,
+ test_rrset->rrset.owner->size);
+ /* Copy type to wire. */
+ size_t offset = test_rrset->rrset.owner->size;
+ knot_wire_write_u16(test_rrset->header_wire + offset,
+ test_rrset->rrset.type);
+ offset += sizeof(uint16_t);
+ /* Copy class to wire. */
+ knot_wire_write_u16(test_rrset->header_wire + offset,
+ test_rrset->rrset.rclass);
+ offset += sizeof(uint16_t);
+ /* Copy TTL to wire. */
+ knot_wire_write_u32(test_rrset->header_wire + offset,
+ test_rrset->rrset.ttl);
+
+ /* Create RDATA. */
+ test_rrset->test_rdata =
+ xmalloc(sizeof(void *) * test_rrset->rr_count);
+ size_t actual_length = 0;
+ size_t rdlength = 0;
+ test_rrset->rrset.rdata_count = test_rrset->rr_count;
+ for (int j = 0; j < test_rrset->rr_count; j++) {
+ test_rrset->test_rdata[j] =
+ &test_rdata_array[test_rrset->test_rdata_ids[j]];
+ rdlength += test_rrset->test_rdata[j]->wire_size;
+ actual_length += test_rrset->test_rdata[j]->size;
+ }
+ /* Assign RDATA (including indices). */
+ offset = 0;
+ test_rrset->rrset.rdata = xmalloc(actual_length);
+ test_rrset->rrset.rdata_indices =
+ xmalloc(sizeof(uint32_t) * test_rrset->rr_count);
+ for (int j = 0; j < test_rrset->rr_count; j++) {
+ if (j > 0) {
+ test_rrset->rrset.rdata_indices[j - 1] =
+ test_rrset->test_rdata[j]->size;
+ }
+
+ memcpy(test_rrset->rrset.rdata + offset,
+ test_rrset->test_rdata[j]->rdata,
+ test_rrset->test_rdata[j]->size);
+ offset += test_rrset->test_rdata[j]->size;
+ }
+ /* Store sum of indices to the last index. */
+ test_rrset->rrset.rdata_indices[test_rrset->rr_count - 1] =
+ offset;
+ }
+}
+
+static int check_rrset_values(const knot_rrset_t *rrset,
+ knot_dname_t *dname, uint16_t type,
+ uint16_t rclass, uint16_t ttl, uint16_t rr_count)
+{
+ int errors = 0;
+
+ if (knot_dname_compare_non_canon(rrset->owner, dname)) {
+ diag("Wrong DNAME in the created RRSet.\n");
+ ++errors;
+ }
+
+ if (rrset->type != type) {
+ diag("Wrong type in the created RRSet.\n");
+ ++errors;
+ }
+
+ if (rrset->rclass != rclass) {
+ diag("Wrong class in the created RRSet.\n");
+ ++errors;
+ }
+
+ if (rrset->ttl != ttl) {
+ diag("Wrong TTL in the created RRSet.\n");
+ ++errors;
+ }
+
+ if (rrset->rdata_count!= rr_count) {
+ diag("Wrong RR count in the created RRSet.\n");
+ ++errors;
+ }
+
+ return errors;
+}
+
+static int test_rrset_new()
+{
+ /* Actual values don't matter in this case. */
+ knot_dname_t *dname = test_dnames[0];
+ uint16_t type = 1;
+ uint16_t rclass = 1;
+ uint32_t ttl = 1;
+
+ knot_rrset_t *rrset = knot_rrset_new(dname, type, rclass, ttl);
+ if (rrset == NULL) {
+ diag("Failed to create new RRSet.\n");
+ return 0;
+ }
+
+ int check_errors = check_rrset_values(rrset, dname, type, rclass, ttl,
+ 0);
+ free(rrset);
+
+ return (check_errors == 0);
+}
+
+static int test_rrset_create_rdata()
+{
+ /* Two cases need to be tested - empty RRSet and non-empty RRSet. */
+
+
+ knot_rrset_t *rrset = knot_rrset_new(test_dnames[0], 0, 0, 0);
+ assert(rrset);
+
+ /*
+ * Again, actual data are not crutial, we need to see if indices
+ * are changed accordingly and so on, but the data are not important.
+ */
+ uint8_t *write_pointer =
+ knot_rrset_create_rdata(rrset,
+ test_rdata_array[0].size);
+ if (write_pointer == NULL) {
+ diag("Could not create data of size %d\n",
+ test_rdata_array[0].size);
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Write dummy data. */
+ memcpy(write_pointer, test_rdata_array[0].rdata,
+ test_rdata_array[0].size);
+
+ /* Check that indices are set right. */
+ if (rrset->rdata_indices[0] != test_rdata_array[0].size) {
+ diag("Wrong RDATA index after inserting RDATA to RRSet.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Rdata count must be equal to one. */
+ if (rrset->rdata_count != 1) {
+ diag("Wrong RDATA count after inserting RDATA to RRSet.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Make sure that the data in the RRSet are the same. */
+ int ret = memcmp(rrset->rdata, test_rdata_array[0].rdata,
+ test_rdata_array[0].size);
+ if (ret) {
+ diag("Wrong data inserted into RRSet.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Insert second item - all other inserts will do the same thing. */
+ write_pointer = knot_rrset_create_rdata(rrset,
+ test_rdata_array[1].size);
+ if (write_pointer == NULL) {
+ diag("Could not create data of size %d\n",
+ test_rdata_array[1].size);
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Write dummy data. */
+ memcpy(write_pointer, test_rdata_array[1].rdata,
+ test_rdata_array[1].size);
+
+ /* Check that indices are set right. */
+ if (rrset->rdata_indices[0] != test_rdata_array[1].size) {
+ diag("Wrong RDATA first index after "
+ "inserting RDATA to RRSet.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ if (rrset->rdata_indices[1] !=
+ test_rdata_array[0].size + test_rdata_array[1].size) {
+ diag("Wrong RDATA last index after "
+ "inserting RDATA to RRSet.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Rdata count must be equal to two. */
+ if (rrset->rdata_count != 2) {
+ diag("Wrong RDATA count after inserting second "
+ "RDATA to RRSet.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Make sure that the data in the RRSet are the same. */
+ ret = memcmp(rrset->rdata + test_rdata_array[0].size,
+ test_rdata_array[1].rdata, test_rdata_array[1].size);
+ if (ret) {
+ diag("Wrong data inserted into RRSet.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ /* Test that data of length 0 are not inserted. */
+ void *ret_ptr = knot_rrset_create_rdata(rrset, 0);
+ if (ret_ptr != NULL) {
+ diag("Empty RDATA inserted.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 1;
+}
+
+static int test_rrset_rdata_item_size()
+{
+ /* Test that types containing DNAMEs only return OK values. */
+ knot_rrset_t *rrset =
+ &test_rrset_array[TEST_RRSET_MINFO_MULTIPLE1].rrset;
+ if (rrset_rdata_item_size(rrset, 0) != sizeof(knot_dname_t *) * 2) {
+ diag("Wrong item length read from RRSet (first item).\n");
+ return 0;
+ }
+
+ if (rrset_rdata_item_size(rrset, 1) != sizeof(knot_dname_t *) * 2) {
+ diag("Wrong item length read from RRSet (last item).\n");
+ return 0;
+ }
+
+ if (rrset_rdata_size_total(rrset) != sizeof(knot_dname_t *) * 4) {
+ diag("Wrong total size returned (MINFO RRSet)\n");
+ return 0;
+ }
+
+ rrset = &test_rrset_array[TEST_RRSET_A_GT].rrset;
+ if (rrset_rdata_item_size(rrset, 0) != 4) {
+ diag("Wrong item length read from A RRSet.\n");
+ return 0;
+ }
+
+ rrset = &test_rrset_array[TEST_RRSET_MX_BIN_GT].rrset;
+ if (rrset_rdata_item_size(rrset, 0) != 2 + sizeof(knot_dname_t *)) {
+ diag("Wrong item length read from A RRSet.\n");
+ return 0;
+ }
+
+ knot_rrset_t *rrset1 = knot_rrset_new(rrset->owner,
+ KNOT_RRTYPE_TXT, KNOT_CLASS_IN,
+ 3600);
+
+ knot_rrset_create_rdata(rrset1, 16);
+ knot_rrset_add_rdata(rrset1,
+ (uint8_t *)"thesearesomedatathatdonotmatter", 25);
+ knot_rrset_create_rdata(rrset1, 38);
+
+ if (rrset_rdata_item_size(rrset1, 0) != 16) {
+ diag("Wrong item lenght in read (first).\n");
+ knot_rrset_deep_free(&rrset1, 1, 1);
+ return 0;
+ }
+
+ if (rrset_rdata_item_size(rrset1, 1) != 25) {
+ diag("Wrong item lenght in read (middle).\n");
+ knot_rrset_deep_free(&rrset1, 1, 1);
+ return 0;
+ }
+
+ if (rrset_rdata_item_size(rrset1, 2) != 38) {
+ diag("Wrong item lenght in read (last).\n");
+ knot_rrset_deep_free(&rrset1, 1, 1);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&rrset1, 1, 1);
+ return 1;
+}
+
+static int test_rrset_get_rdata()
+{
+ knot_rrset_t *rrset = knot_rrset_new(test_dnames[0],
+ KNOT_RRTYPE_TXT, KNOT_CLASS_IN, 3600);
+ assert(rrset);
+ uint8_t *ref_pointer = knot_rrset_create_rdata(rrset, 16);
+ memcpy(ref_pointer, "badcafecafebabee", 16);
+ uint8_t *pointer = knot_rrset_get_rdata(rrset, 0);
+ if (pointer != ref_pointer) {
+ diag("Could not get RDATA from RRSet (%p vs %p).\n",
+ pointer, ref_pointer);
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ int ret = memcmp(pointer, ref_pointer, 16);
+ if (ret) {
+ diag("Got bad RDATA from RRSet (comparison failed).\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ uint8_t *ref_pointer2 = knot_rrset_create_rdata(rrset, 16);
+ memcpy(ref_pointer2, "foobarfoobarfoob", 16);
+ pointer = knot_rrset_get_rdata(rrset, 1);
+ if (pointer != ref_pointer2) {
+ diag("Could not ger RDATA from RRSet (%p vs %p).\n",
+ pointer, ref_pointer2);
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ ret = memcmp(pointer, ref_pointer2, 16);
+ if (ret) {
+ diag("Got bad RDATA from RRSet (comparison failed).\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 1;
+}
+
+static int test_rrset_shallow_copy()
+{
+ for (int i = 0; i < TEST_RRSET_COUNT; i++) {
+ knot_rrset_t *rrset_copy = NULL;
+ knot_rrset_t *rrset = &test_rrset_array[i].rrset;
+ int ret = knot_rrset_shallow_copy(rrset,
+ &rrset_copy);
+ if (ret != KNOT_EOK) {
+ knot_rrset_free(&rrset_copy);
+ diag("Could not copy RRSet.\n");
+ return 0;
+ }
+
+ /* Check that created RRSet has the same as the old one. */
+ int errors = check_rrset_values(rrset_copy, rrset->owner, rrset->type,
+ rrset->rclass, rrset->ttl,
+ rrset->rdata_count);
+ if (errors) {
+ knot_rrset_free(&rrset_copy);
+ return 0;
+ }
+
+ /* Check that created RRSet has the same RDATA. */
+ if (rrset->rdata != rrset_copy->rdata) {
+ diag("RDATA in the new RRSet do not match.\n");
+ knot_rrset_free(&rrset_copy);
+ return 0;
+ }
+
+ /* Check that RDATA indices are the same. */
+ if (rrset->rdata_indices != rrset_copy->rdata_indices) {
+ diag("RDATA indices in the new RRSet do not match.\n");
+ knot_rrset_free(&rrset_copy);
+ return 0;
+ }
+
+ knot_rrset_free(&rrset_copy);
+ }
+
+ return 1;
+}
+
+static int test_rrset_deep_copy()
+{
+ for (int i = 0; i < TEST_RRSET_COUNT; i++) {
+ knot_rrset_t *rrset_copy = NULL;
+ knot_rrset_t *rrset = &test_rrset_array[i].rrset;
+ int ret = knot_rrset_deep_copy(rrset, &rrset_copy, 1);
+ if (ret != KNOT_EOK) {
+ diag("Could not copy RRSet.\n");
+ return 0;
+ }
+
+ /* Check that created RRSet has the same as the old one. */
+ int errors = check_rrset_values(rrset_copy, rrset->owner, rrset->type,
+ rrset->rclass, rrset->ttl,
+ rrset->rdata_count);
+ if (errors) {
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
+ return 0;
+ }
+
+ /* Check that RDATA indices contain the same data. */
+ ret = memcmp(rrset->rdata_indices, rrset_copy->rdata_indices,
+ rrset->rdata_count);
+ if (ret) {
+ diag("Copied RRSet has different RDATA indices.\n");
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
+ return 0;
+ }
+
+ /*
+ * Go through RDATA and compare blocks. Cannot compare the whole thing
+ * since DNAMEs are copied as well and will have different address.
+ */
+ ret = knot_rrset_rdata_equal(rrset, rrset_copy);
+ if (!ret) {
+ diag("Copied RRSet has different RDATA.\n");
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
+ return 0;
+ }
+ knot_rrset_deep_free(&rrset_copy, 1, 1);
+ }
+
+ return 1;
+}
+
+static int test_rrset_to_wire()
+{
+ size_t wire_size = 65535;
+ uint8_t wire[wire_size];
+ uint16_t rr_count = 0;
+
+ /* Test correct conversions. */
+ for (int i = 0; i < TEST_RRSET_COUNT; i++) {
+ memset(wire, 0, wire_size);
+ wire_size = 65535;
+ /* Convert to wire. */
+ int ret = knot_rrset_to_wire(&test_rrset_array[i].rrset, wire,
+ &wire_size, 65535, &rr_count, NULL);
+ if (ret != KNOT_EOK) {
+ diag("Could not convert RRSet to wire (%s).\n",
+ knot_strerror(ret));
+ return 0;
+ }
+
+ if (rr_count != test_rrset_array[i].rrset.rdata_count) {
+ diag("Wrong number of RRs converted.\n");
+ return 0;
+ }
+
+ size_t offset = 0;
+ for (int j = 0; j < rr_count; ++j) {
+ /* Check that header is OK. */
+ ret = memcmp(wire + offset,
+ test_rrset_array[i].header_wire,
+ test_rrset_array[i].header_wire_size);
+ if (ret) {
+ diag("Header of RRSet %d, RR %d is wrongly converted.\n",
+ i, j);
+ return 0;
+ }
+
+ offset += test_rrset_array[i].header_wire_size;
+ /* Check RDLENGTH. */
+ uint16_t rdlength = knot_wire_read_u16(wire + offset);
+ if (rdlength != test_rrset_array[i].test_rdata[j]->wire_size) {
+ diag("Wrong RDLENGTH\n");
+ return 0;
+ }
+ offset += sizeof(uint16_t);
+
+ /* Check that the RDATA are OK. */
+ ret = memcmp(wire + offset,
+ test_rrset_array[i].test_rdata[j]->wire,
+ rdlength);
+ if (ret) {
+ diag("RDATA of RRSet %d, RR %d, "
+ "are wrongly converted. Type=%"PRIu16"\n",
+ i, j, test_rrset_array[i].rrset.type);
+ return 0;
+ }
+ offset += rdlength;
+ }
+
+ if (offset != wire_size) {
+ diag("Wrong wire size, in RRSet=%d "
+ "(should be=%d, is=%d).\n", i,
+ offset, wire_size);
+ return 0;
+ }
+ }
+
+ /* Check that function does not crash if given small wire. */
+ int ret = knot_rrset_to_wire(&test_rrset_array[0].rrset, wire,
+ &wire_size, 5, &rr_count, NULL);
+ if (ret != KNOT_ESPACE) {
+ diag("RRSet was converted to wire even though twe wire was"
+ " not big enough.\n");
+ return 0;
+ }
+ /* RDATA do not fit. */
+ ret = knot_rrset_to_wire(&test_rrset_array[0].rrset, wire,
+ &wire_size, 25, &rr_count, NULL);
+ if (ret != KNOT_ESPACE) {
+ diag("RRSet was converted to wire even though twe wire was"
+ " not big enough.\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_rrset_merge()
+{
+ knot_rrset_t *merge_to;
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset,
+ &merge_to, 1);
+ knot_rrset_t *merge_from;
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE2].rrset,
+ &merge_from, 1);
+ assert(merge_to);
+ assert(merge_from);
+ int ret = knot_rrset_merge(merge_to, merge_from);
+ if (ret != KNOT_EOK) {
+ diag("Could not merge RRSets.\n");
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+ return 0;
+ }
+
+ //TODO check that merge operation does not change second rr
+ //TODO check that two RRSet that are not mergable will not merge
+ if (!knot_rrset_equal(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE2].rrset,
+ merge_from,
+ KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Merge corrupted second RRSet.\n");
+ return 0;
+ }
+
+ if (merge_to->rdata_count !=
+ test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset.rdata_count +
+ merge_from->rdata_count) {
+ diag("Not all RDATA were merged.\n");
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+ return 0;
+ }
+
+ /* Check that the first RRSet now contains RDATA from the second. */
+ /* Indices first. */
+ ret = memcmp(merge_to->rdata_indices,
+ test_rrset_array[TEST_RRSET_MERGE_RESULT1].rrset.rdata_indices,
+ merge_to->rdata_count);
+ if (ret) {
+ diag("Merge operation corrupted the first RRSet's indices.\n");
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+ return 0;
+ }
+
+ /* Check actual RDATA. */
+ ret = knot_rrset_rdata_equal(merge_to,
+ &test_rrset_array[TEST_RRSET_MERGE_RESULT1].rrset);
+ if (!ret) {
+ diag("Merged RDATA are wrong.\n");
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+
+ return 1;
+}
+
+static int test_rrset_merge_no_dupl()
+{
+ /* Test that merge of two identical RRSets results in no-op. */
+ knot_rrset_t *merge_to = NULL;
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset,
+ &merge_to, 1);
+ knot_rrset_t *merge_from = NULL;
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset,
+ &merge_from, 1);
+ int merged, removed_rrs;
+ int ret = knot_rrset_merge_no_dupl(merge_to, merge_from, &merged, &removed_rrs);
+ if (ret != KNOT_EOK) {
+ diag("Merge of identical RRSets failed.\n");
+ return 0;
+ }
+
+ if (!knot_rrset_equal(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset,
+ merge_to, KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Merge corrupted first RRSet.\n");
+ return 0;
+ }
+
+ if (!knot_rrset_equal(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset,
+ merge_from, KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Merge corrupted second RRSet.\n");
+ return 0;
+ }
+
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+
+ /* Merge normal, non-duplicated RRSets. */
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset,
+ &merge_to, 1);
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE2].rrset,
+ &merge_from, 1);
+ assert(merge_to);
+ assert(merge_from);
+
+ ret = knot_rrset_merge_no_dupl(merge_to, merge_from, &merged,
+ &removed_rrs);
+ if (ret != KNOT_EOK) {
+ diag("Merge of identical RRSets failed.\n");
+ return 0;
+ }
+
+ if (!knot_rrset_equal(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE2].rrset,
+ merge_from,
+ KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Merge corrupted second RRSet.\n");
+ return 0;
+ }
+
+ if (!knot_rrset_equal(&test_rrset_array[TEST_RRSET_MERGE_RESULT1].rrset,
+ merge_to,
+ KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Merge did not create correct RDATA.\n");
+ return 0;
+ }
+
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+
+ /* Merge RRSets with both duplicated and unique RDATAs. */
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_UNIQUE1].rrset,
+ &merge_to, 1);
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MERGE_RESULT1].rrset,
+ &merge_from, 1);
+ assert(merge_to);
+ assert(merge_from);
+
+ ret = knot_rrset_merge_no_dupl(merge_to, merge_from, &merged,
+ &removed_rrs);
+ if (ret != KNOT_EOK) {
+ diag("Merge of identical RRSets failed.\n");
+ return 0;
+ }
+
+ if (!knot_rrset_equal(&test_rrset_array[TEST_RRSET_MERGE_RESULT1].rrset,
+ merge_from,
+ KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Merge corrupted second RRSet.\n");
+ return 0;
+ }
+
+ if (!knot_rrset_equal(&test_rrset_array[TEST_RRSET_MERGE_RESULT1].rrset,
+ merge_to,
+ KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Merge did not create correct RDATA.\n");
+ return 0;
+ }
+
+ knot_rrset_deep_free(&merge_to, 1, 1);
+ knot_rrset_deep_free(&merge_from, 1, 1);
+
+ return 1;
+}
+
+static int test_rrset_equal()
+{
+ /* Test pointer comparison. */
+ int ret = knot_rrset_equal((knot_rrset_t *)0xdeadbeef,
+ (knot_rrset_t *)0xdeadbeef,
+ KNOT_RRSET_COMPARE_PTR);
+ if (!ret) {
+ diag("Pointer comparison failed (1).\n");
+ return 0;
+ }
+
+ ret = knot_rrset_equal((knot_rrset_t *)0xdeadbeef,
+ (knot_rrset_t *)0xcafebabe,
+ KNOT_RRSET_COMPARE_PTR);
+ if (ret) {
+ diag("Pointer comparison failed (0).\n");
+ return 0;
+ }
+
+ /* Create equal RRSets. */
+ knot_rrset_t *rrs1 = NULL;
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_A_GT].rrset,
+ &rrs1, 1);
+ knot_rrset_t *rrs2 = &test_rrset_array[TEST_RRSET_A_GT].rrset;
+ /* Test header comparison. */
+ ret = knot_rrset_equal(rrs1, rrs2, KNOT_RRSET_COMPARE_HEADER);
+ if (!ret) {
+ diag("Header comparison failed (Header equal).\n");
+ knot_rrset_deep_free(&rrs1, 1, 1);
+ return 0;
+ }
+ /* Change DNAME. */
+ knot_rrset_set_owner(rrs1, test_dnames[4]);
+ ret = knot_rrset_equal(rrs1, rrs2, KNOT_RRSET_COMPARE_HEADER);
+ if (ret) {
+ char *owner1 = knot_dname_to_str(rrs1->owner);
+ char *owner2 = knot_dname_to_str(rrs2->owner);
+ diag("Header comparison failed "
+ "(DNAMEs different (%s %s), but ret=%d).\n", owner1,
+ owner2, ret);
+ rrs1->owner = test_dnames[0];
+ knot_rrset_deep_free(&rrs1, 1, 1);
+ free(owner1);
+ free(owner2);
+ return 0;
+ }
+ rrs1->owner = test_dnames[0];
+ /* Change CLASS. */
+ rrs1->rclass = KNOT_CLASS_CH;
+ ret = knot_rrset_equal(rrs1, rrs2, KNOT_RRSET_COMPARE_HEADER);
+ if (ret) {
+ diag("Header comparison failed (CLASSEs different).\n");
+ knot_rrset_deep_free(&rrs1, 1, 1);
+ return 0;
+ }
+ rrs1->rclass = KNOT_CLASS_IN;
+
+ /* Test whole comparison. */
+ ret = knot_rrset_equal(rrs1, rrs2, KNOT_RRSET_COMPARE_WHOLE);
+ if (!ret) {
+ diag("Whole comparison failed (Same RRSets).\n");
+ knot_rrset_deep_free(&rrs1, 1, 1);
+ return 0;
+ }
+
+ rrs2 = &test_rrset_array[TEST_RRSET_A_LESS].rrset;
+ ret = knot_rrset_equal(rrs1, rrs2, KNOT_RRSET_COMPARE_WHOLE);
+ if (ret) {
+ diag("Whole comparison failed (Different RRSets).\n");
+ knot_rrset_deep_free(&rrs1, 1, 1);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&rrs1, 1, 1);
+
+ return 1;
+}
+
+static int test_rrset_rdata_equal()
+{
+ /* Equal - raw data only. */
+ knot_rrset_t *rrset1 = &test_rrset_array[TEST_RRSET_A_LESS].rrset;
+ knot_rrset_t *rrset2 = &test_rrset_array[TEST_RRSET_A_LESS].rrset;
+ if (!knot_rrset_rdata_equal(rrset1, rrset2)) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 1. (raw data) %d %d\n",
+ rrset1->type, rrset2->type);
+ return 0;
+ }
+
+ /* Equal - DNAME only. */
+ rrset1 = &test_rrset_array[TEST_RRSET_NS_LESS].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_NS_LESS].rrset;
+ if (!knot_rrset_rdata_equal(rrset1, rrset2)) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 1. (DNAME only)\n");
+ return 0;
+ }
+
+ /* Equal - combination. */
+ rrset1 = &test_rrset_array[TEST_RRSET_MX_BIN_LESS].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_MX_BIN_LESS].rrset;
+ if (!knot_rrset_rdata_equal(rrset1, rrset2)) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 1. (MX combination)\n");
+ return 0;
+ }
+
+ /* Equal - combination, different order. */
+ rrset1 = &test_rrset_array[TEST_RRSET_MINFO_MULTIPLE1].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_MINFO_MULTIPLE2].rrset;
+ if (!knot_rrset_rdata_equal(rrset1, rrset2)) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 1. (MINFO - order, combination)\n");
+ return 0;
+ }
+
+ /* Not equal - second item missing. */
+ rrset1 = &test_rrset_array[TEST_RRSET_MINFO_MULTIPLE1].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_MINFO].rrset;
+ if (knot_rrset_rdata_equal(rrset1, rrset2)) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (MINFO - combination)\n");
+ return 0;
+ }
+
+ /* Other way around. */
+ if (knot_rrset_rdata_equal(rrset2, rrset1)) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (combination)\n");
+ return 0;
+ }
+
+ /* Not equal - second item different. */
+
+ /* Other way around. */
+
+ /* Not equal - raw data only. */
+ rrset1 = &test_rrset_array[TEST_RRSET_A_LESS].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_A_GT].rrset;
+ if (knot_rrset_rdata_equal(rrset1, rrset2) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (raw data only)\n");
+ return 0;
+ }
+
+ /* Not equal - raw data only. */
+ if (knot_rrset_rdata_equal(rrset2, rrset1) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (raw data only)\n");
+ return 0;
+ }
+
+ /* Not equal - DNAME only. */
+ rrset1 = &test_rrset_array[TEST_RRSET_NS_LESS].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_NS_GT].rrset;
+ if (knot_rrset_rdata_equal(rrset1, rrset2) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (DNAME only)\n");
+ return 0;
+ }
+
+ /* Not equal - DNAME only. */
+ if (knot_rrset_rdata_equal(rrset2, rrset1) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (DNAME only)\n");
+ return 0;
+ }
+
+ /* Not equal - combination, difference in binary part. */
+ rrset1 = &test_rrset_array[TEST_RRSET_MX_BIN_LESS].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_MX_BIN_GT].rrset;
+ if (knot_rrset_rdata_equal(rrset1, rrset2) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (combination)\n");
+ return 0;
+ }
+
+ /* Not equal - combination, difference in binary part. */
+ if (knot_rrset_rdata_equal(rrset2, rrset1) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (combination)\n");
+ return 0;
+ }
+
+ /* Not equal - combination, difference in DNAME part. */
+ rrset1 = &test_rrset_array[TEST_RRSET_MX_DNAME_LESS].rrset;
+ rrset2 = &test_rrset_array[TEST_RRSET_MX_DNAME_GT].rrset;
+ if (knot_rrset_rdata_equal(rrset1, rrset2) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0. (combination)\n");
+ return 0;
+ }
+
+ /* Not equal - combination, difference in DNAME part. */
+ if (knot_rrset_rdata_equal(rrset2, rrset1) == 1) {
+ diag("rrset_rdata_equal() returned wrong "
+ "value, should be 0 (combination)\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int test_rrset_next_dname()
+{
+ /* Same test as in above, but we'll use multiple RRs within one SET. */
+ knot_rrset_t *rrset = &test_rrset_array[TEST_RRSET_MINFO_MULTIPLE1].rrset;
+ knot_dname_t *extracted_dnames[4];
+ extracted_dnames[0] = test_dnames[0];
+ extracted_dnames[1] = test_dnames[1];
+ extracted_dnames[2] = test_dnames[2];
+ extracted_dnames[3] = test_dnames[3];
+ knot_dname_t **dname = NULL;
+ int i = 0;
+ while ((dname = knot_rrset_get_next_dname(rrset, dname))) {
+ if (knot_dname_compare_non_canon(extracted_dnames[i], *dname)) {
+ diag("Got wrong DNAME from RDATA. on index %d\n", i);
+ char *ext_name = knot_dname_to_str(extracted_dnames[i]);
+ char *act_name = knot_dname_to_str(*dname);
+ diag("DNAME should be %s, but was %s (%p - %p)\n",
+ ext_name, act_name, extracted_dnames[i], *dname);
+ free(ext_name);
+ free(act_name);
+ return 0;
+ }
+ i++;
+ }
+
+ if (i != 4) {
+ diag("Not all DNAMEs were extracted (%d out of 4).\n",
+ i);
+ return 0;
+ }
+
+ /* Now try NS. */
+ rrset = &test_rrset_array[TEST_RRSET_NS_LESS].rrset;
+ dname = NULL;
+ dname = knot_rrset_get_next_dname(rrset, dname);
+ if (dname == NULL || knot_dname_compare_non_canon(*dname, test_dnames[TEST_DNAME_GENERIC])) {
+ diag("Got wrong DNAME from NS RDATA. Was %p, should be %p \n",
+ dname ? *dname: NULL, test_dnames[TEST_DNAME_GENERIC]);
+ return 0;
+ }
+ dname = knot_rrset_get_next_dname(rrset, dname);
+ if (dname != NULL) {
+ diag("Got DNAME from RRSet even though all had been extracted previously. (NS)\n");
+ return 0;
+ }
+ /* Now try MX. */
+ rrset = &test_rrset_array[TEST_RRSET_MX_BIN_GT].rrset;
+ dname = NULL;
+ dname = knot_rrset_get_next_dname(rrset, dname);
+ if (dname == NULL || knot_dname_compare_non_canon(*dname, test_dnames[1])) {
+ diag("Got wrong DNAME from MX RDATA.\n");
+ return 0;
+ }
+ dname = knot_rrset_get_next_dname(rrset, dname);
+ if (dname != NULL) {
+ diag("Got DNAME from RRSet even though all had been extracted previously. (MX)\n");
+ return 0;
+ }
+
+ /* Try writes into DNAMEs you've gotten. */
+ rrset = NULL;
+ knot_rrset_deep_copy(&test_rrset_array[TEST_RRSET_MINFO_MULTIPLE1].rrset,
+ &rrset, 1);
+ dname = NULL;
+ i = 4;
+ while ((dname = knot_rrset_get_next_dname(rrset, dname))) {
+ knot_dname_free(dname);
+ memcpy(dname, &test_dnames[i], sizeof(knot_dname_t *));
+ i++;
+ }
+
+ if (i != 8) {
+ diag("Not all DNAMEs were traversed (%d).\n", i);
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ knot_dname_t **dname_read = NULL;
+ i = 4;
+ while ((dname_read = knot_rrset_get_next_dname(rrset,
+ dname_read))) {
+ if (*dname_read != test_dnames[i]) {
+ diag("Rewriting of DNAMEs in RDATA was "
+ "not successful.\n");
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+ i++;
+ }
+
+ if (i != 8) {
+ diag("Not all DNAMEs were traversed (%d).\n", i);
+ knot_rrset_deep_free(&rrset, 1, 1);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&rrset, 1, 1);
+
+ return 1;
+}
+
+static int test_rrset_find_pos()
+{
+ /* Create some mockup TXT RRSets. */
+ knot_rrset_t *rrset_source = knot_rrset_new(test_dnames[0], KNOT_RRTYPE_TXT,
+ KNOT_CLASS_IN, 3600);
+ uint8_t *mock_data = (uint8_t *)"cafebabebadcafecafecafecafe";
+ /* Test removal of two exactly same items. */
+ uint8_t *rdata = knot_rrset_create_rdata(rrset_source,
+ strlen((char *)mock_data));
+ memcpy(rdata, mock_data, strlen((char *)mock_data));
+ knot_rrset_t *rrset_find_in = NULL;
+ knot_rrset_deep_copy(rrset_source, &rrset_find_in, 1);
+ rdata = knot_rrset_create_rdata(rrset_source, 10);
+ memcpy(rdata, mock_data ,10);
+ size_t rr_pos = 0;
+ int ret = knot_rrset_find_rr_pos(rrset_source, rrset_find_in, 0, &rr_pos);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&rrset_source, 1, 1);
+ knot_rrset_deep_free(&rrset_find_in, 1, 1);
+ diag("RR was not found, even though it should have been.");
+ return 0;
+ }
+ if (rr_pos != 0) {
+ knot_rrset_deep_free(&rrset_source, 1, 1);
+ knot_rrset_deep_free(&rrset_find_in, 1, 1);
+ diag("Wrong index returned. Should be 0, was %zu", rr_pos);
+ return 0;
+ }
+
+ /* Add second RR. */
+ knot_rrset_deep_free(&rrset_find_in, 1, 1);
+ knot_rrset_shallow_copy(rrset_source, &rrset_find_in);
+ knot_rrset_rdata_reset(rrset_find_in);
+ rdata = knot_rrset_create_rdata(rrset_find_in, 10);
+ memcpy(rdata, mock_data ,10);
+ ret = knot_rrset_find_rr_pos(rrset_source, rrset_find_in, 0, &rr_pos);
+ if (ret != KNOT_EOK) {
+ diag("RR was not found, even though it should have been.");
+ return 0;
+ }
+ if (rr_pos != 1) {
+ diag("Wrong index returned. Should be 1, was %zu", rr_pos);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&rrset_source, 1, 1);
+ knot_rrset_deep_free(&rrset_find_in, 1, 1);
+
+ return 1;
+}
+
+static int test_rrset_remove_rr()
+{
+ /* Remove RR and test that the returned data were OK. */
+
+ /* Create some mockup TXT RRSets. */
+ knot_rrset_t *rrset_source = knot_rrset_new(test_dnames[0], KNOT_RRTYPE_TXT,
+ KNOT_CLASS_IN, 3600);
+ uint8_t *mock_data = (uint8_t *)"cafebabebadcafecafecafecafe";
+ /* Test removal of two exactly same items. */
+ uint8_t *rdata = knot_rrset_create_rdata(rrset_source,
+ strlen((char *)mock_data));
+ memcpy(rdata, mock_data, strlen((char *)mock_data));
+ rdata = knot_rrset_create_rdata(rrset_source, 10);
+ memcpy(rdata, mock_data ,10);
+ knot_rrset_t *rrset_dest = NULL;
+ /* Create copy. */
+ knot_rrset_deep_copy(rrset_source, &rrset_dest, 1);
+ rdata = knot_rrset_create_rdata(rrset_dest, 16);
+ memcpy(rdata, "foobarfoobarfoo", 16);
+ knot_rrset_t *returned_rr = NULL;
+ int ret = knot_rrset_remove_rr_using_rrset(rrset_dest, rrset_source, &returned_rr, 0);
+ if (ret != KNOT_EOK) {
+ diag("Could not remove");
+ knot_rrset_deep_free(&rrset_source, 1, 1);
+ knot_rrset_deep_free(&returned_rr, 1, 1);
+ return 0;
+ }
+
+// diag("Returned\n");
+// knot_rrset_dump(returned_rr);
+// diag("Source\n");
+// knot_rrset_dump(rrset_source);
+// diag("Destinantion\n");
+// knot_rrset_dump(rrset_dest);
+
+ /* Only one RR within RRSet, needs to be the same. */
+ if (!knot_rrset_equal(rrset_source, returned_rr,
+ KNOT_RRSET_COMPARE_WHOLE)) {
+ diag("Got wrong data in return rrset.");
+ knot_rrset_deep_free(&rrset_source, 1, 1);
+ knot_rrset_deep_free(&returned_rr, 1, 1);
+ return 0;
+ }
+
+ knot_rrset_deep_free(&rrset_source, 1, 1);
+ knot_rrset_deep_free(&rrset_dest, 1, 1);
+ knot_rrset_deep_free(&returned_rr, 1, 1);
+
+ return 1;
+}
+
+static int knot_rrset_tests_count(int argc, char *argv[])
+{
+ return 14;
+}
+
+static int knot_rrset_tests_run(int argc, char *argv[])
+{
+ int res = 0,
+ res_final = 1;
+
+ create_test_dnames();
+ create_test_rdata();
+ create_test_rrsets();
+
+ res = test_rrset_new();
+ ok(res, "rrset: create");
+ res_final *= res;
+
+ res = test_rrset_create_rdata();
+ ok(res, "rrset: create_rdata");
+ res_final *= res;
+
+ res = test_rrset_get_rdata();
+ ok(res, "rrset: get rdata");
+ res_final *= res;
+
+ res = test_rrset_equal();
+ ok(res, "rrset: rrset_equal");
+ res_final *= res;
+
+ res = test_rrset_rdata_equal();
+ ok(res, "rrset: rrset_rdata_equal");
+
+ res = test_rrset_shallow_copy();
+ ok(res, "rrset: shallow copy");
+ res_final *= res;
+
+ res = test_rrset_deep_copy();
+ ok(res, "rrset: deep copy");
+ res_final *= res;
+
+ res = test_rrset_to_wire();
+ ok(res, "rrset: to wire");
+ res_final *= res;
+
+ res = test_rrset_rdata_item_size();
+ ok(res, "rrset: rdata_item_size");
+ res_final *= res;
+
+ res = test_rrset_merge();
+ ok(res, "rrset: merge");
+ res_final *= res;
+
+ res = test_rrset_merge_no_dupl();
+ ok(res, "rrset: merge no dupl");
+ res_final *= res;
+
+ res = test_rrset_next_dname();
+ ok(res, "rrset: next dname");
+ res_final *= res;
+
+ res = test_rrset_remove_rr();
+ ok(res, "rrset: remove rr");
+
+ res = test_rrset_find_pos();
+ ok(res, "rrset: find pos");
+ res_final *= res;
+
+ return res_final;
+}
diff --git a/src/tests/libknot/libknot/rrset_tests.h b/src/tests/libknot/rrset_tests.h
index b0787d6..b0787d6 100644
--- a/src/tests/libknot/libknot/rrset_tests.h
+++ b/src/tests/libknot/rrset_tests.h
diff --git a/src/tests/libknot/sign_tests.c b/src/tests/libknot/sign_tests.c
new file mode 100644
index 0000000..6b77218
--- /dev/null
+++ b/src/tests/libknot/sign_tests.c
@@ -0,0 +1,249 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "tests/libknot/sign_tests.h"
+#include "libknot/sign/key.h"
+#include "libknot/sign/key.c" // testing static functions
+
+static int sign_tests_count(int argc, char *argv[]);
+static int sign_tests_run(int argc, char *argv[]);
+
+unit_api sign_tests_api = {
+ "libknot/sign",
+ &sign_tests_count,
+ &sign_tests_run
+};
+
+static int sign_tests_count(int argc, char *argv[])
+{
+ return 25;
+}
+
+static int sign_tests_run(int argc, char *argv[])
+{
+ // 1-3. - strndup_with_suffix()
+ {
+ char *result;
+
+ result = strndup_with_suffix("begin", 5, "end");
+ ok(result && strcmp(result, "beginend") == 0,
+ "strndup_with_suffix(), matching length");
+ free(result);
+
+ result = strndup_with_suffix("begin", 3, "end");
+ ok(result && strcmp(result, "begend") == 0,
+ "strndup_with_suffix(), shorter length");
+ free(result);
+
+ result = strndup_with_suffix("", 0, "end");
+ ok(result && strcmp(result, "end") == 0,
+ "strndup_with_suffix(), empty base string");
+ free(result);
+ }
+
+ // 4.-9. - get_key_filenames()
+ {
+ char *public, *private;
+ int result;
+
+ result = get_key_filenames("Kexample.com.+1.+2.private",
+ &public, &private);
+ ok(result == KNOT_EOK &&
+ strcmp(public, "Kexample.com.+1.+2.key") == 0 &&
+ strcmp(private, "Kexample.com.+1.+2.private") == 0,
+ "get_key_filenames(), from private key");
+ free(public);
+ free(private);
+
+ result = get_key_filenames("Kexample.com.+4.+8.key",
+ &public, &private);
+ ok(result == KNOT_EOK &&
+ strcmp(public, "Kexample.com.+4.+8.key") == 0 &&
+ strcmp(private, "Kexample.com.+4.+8.private") == 0,
+ "get_key_filenames(), from public key");
+ free(public);
+ free(private);
+
+ result = get_key_filenames("nic.cz.+4.+8",
+ &public, &private);
+ ok(result == KNOT_EOK &&
+ strcmp(public, "nic.cz.+4.+8.key") == 0 &&
+ strcmp(private, "nic.cz.+4.+8.private") == 0,
+ "get_key_filenames(), without extension");
+ free(public);
+ free(private);
+
+ result = get_key_filenames("nic.cz.+0.+1.",
+ &public, &private);
+ ok(result == KNOT_EOK &&
+ strcmp(public, "nic.cz.+0.+1.key") == 0 &&
+ strcmp(private, "nic.cz.+0.+1.private") == 0,
+ "get_key_filenames(), empty extension");
+ free(public);
+ free(private);
+
+ result = get_key_filenames("../keys/Kfoo.bar.+5.+10.private",
+ &public, &private);
+ ok(result == KNOT_EOK &&
+ strcmp(public, "../keys/Kfoo.bar.+5.+10.key") == 0 &&
+ strcmp(private, "../keys/Kfoo.bar.+5.+10.private") == 0,
+ "get_key_filenames(), with path");
+ free(public);
+ free(private);
+
+ result = get_key_filenames("keys/something.txt",
+ &public, &private);
+ ok(result == KNOT_EOK &&
+ strcmp(public, "keys/something.txt.key") == 0 &&
+ strcmp(private, "keys/something.txt.private") == 0,
+ "get_key_filenames(), nonstandard name");
+ free(public);
+ free(private);
+ }
+
+ // 10. - key_param_string()
+ {
+ char *output = NULL;
+ int result;
+
+ result = key_param_string(&output, "ahoj DNS svete");
+ ok(result == KNOT_EOK && strcmp(output, "ahoj DNS svete") == 0,
+ "key_param_string(), correct usage");
+ free(output);
+ }
+
+ // 11-16. - key_param_int()
+ {
+ int output = 0;
+ int result;
+
+ result = key_param_int(&output, "12345");
+ ok(result == KNOT_EOK && output == 12345,
+ "key_param_int(), correct number");
+
+ result = key_param_int(&output, "6789 whatever");
+ ok(result == KNOT_EOK && output == 6789,
+ "key_param_int(), number, space, and text");
+
+ result = key_param_int(&output, "24680\n");
+ ok(result == KNOT_EOK && output == 24680,
+ "key_param_int(), number and new line");
+
+ result = key_param_int(&output, "0");
+ ok(result == KNOT_EOK && output == 0,
+ "key_param_int(), zero");
+
+ result = key_param_int(&output, "");
+ ok(result == KNOT_EINVAL,
+ "key_param_int(), empty string");
+
+ result = key_param_int(&output, "\t \n");
+ ok(result == KNOT_EINVAL,
+ "key_param_int(), only white spaces");
+
+ result = key_param_int(&output, "4444abc");
+ ok(result == KNOT_EINVAL,
+ "key_param_int(), number and text");
+ }
+
+ // 17-20. - parse_keyfile_line()
+ {
+ knot_key_params_t key = { 0 };
+ int result;
+ char *line;
+
+ line = strdup("Algorithm: 123 ABC");
+ result = parse_keyfile_line(&key, line, strlen(line));
+ ok(result == KNOT_EOK && key.algorithm == 123,
+ "parse_keyfile_line(), simple line with algorithm");
+ free(line);
+
+ line = strdup("Key: secret\n");
+ result = parse_keyfile_line(&key, line, strlen(line));
+ ok(result == KNOT_EOK && strcmp(key.secret, "secret") == 0,
+ "parse_keyfile_line(), new line terminated line with key");
+ free(key.secret);
+ free(line);
+
+ line = strdup("Cool: Knot DNS");
+ result = parse_keyfile_line(&key, line, strlen(line));
+ ok(result == KNOT_EOK,
+ "parse_keyfile_line(), unknown parameter");
+ free(line);
+ }
+
+ // 21. - knot_free_key_params()
+ {
+ int result;
+ knot_key_params_t params = { 0 };
+ knot_key_params_t empty_params = { 0 };
+
+ params.algorithm = 42;
+ params.public_exponent = strdup("AQAB");
+
+ result = knot_free_key_params(&params);
+ ok(result == KNOT_EOK
+ && memcmp(&params, &empty_params, sizeof(params)) == 0,
+ "knot_free_key_params(), regular free");
+ }
+
+ // 22-25. - knot_tsig_key_from_params()
+ {
+ int result;
+ knot_key_params_t params = { 0 };
+ knot_tsig_key_t tsig_key;
+ const char *owner = "shared.example.com.";
+ knot_dname_t *name = knot_dname_new_from_str(owner,
+ strlen(owner),
+ NULL);
+
+ result = knot_tsig_key_from_params(&params, &tsig_key);
+ ok(result == KNOT_EINVAL,
+ "knot_tsig_key_from_params(), empty parameters");
+
+ params.secret = "Ok6NmA==";
+ result = knot_tsig_key_from_params(&params, &tsig_key);
+ ok(result == KNOT_EINVAL,
+ "knot_tsig_key_from_params(), no key name");
+
+ params.name = name;
+ params.secret = NULL;
+ result = knot_tsig_key_from_params(&params, &tsig_key);
+ ok(result == KNOT_EINVAL,
+ "knot_tsig_key_from_params(), no shared secret");
+
+ params.name = name;
+ params.secret = "Ok6NmA==";
+ uint8_t decoded_secret[] = { 0x3a, 0x4e, 0x8d, 0x98 };
+ result = knot_tsig_key_from_params(&params, &tsig_key);
+ ok(result == KNOT_EOK
+ && tsig_key.secret.size == sizeof(decoded_secret)
+ && memcmp(tsig_key.secret.data, decoded_secret,
+ sizeof(decoded_secret)) == 0,
+ "knot_tsig_key_from_params(), secret set properly");
+
+ knot_dname_release(name);
+ knot_tsig_key_free(&tsig_key);
+ }
+
+ //! \todo knot_keytag()
+ //! \todo get_key_info_from_public_key() -- working with files required
+ //! \todo knot_load_key_params() -- working with files required
+ //! \todo knot_get_key_type()
+
+ return 0;
+}
diff --git a/src/tests/libknot/libknot/zone_tests.h b/src/tests/libknot/sign_tests.h
index 5539709..177f9e6 100644
--- a/src/tests/libknot/libknot/zone_tests.h
+++ b/src/tests/libknot/sign_tests.h
@@ -14,12 +14,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_ZONE_TESTS_H_
-#define _KNOTD_ZONE_TESTS_H_
+#ifndef _KNOTD_SIGN_TESTS_
+#define _KNOTD_SIGN_TESTS_
#include "common/libtap/tap_unit.h"
-/* Unit API. */
-unit_api zone_tests_api;
+unit_api sign_tests_api;
-#endif /* _KNOTD_ZONE_TESTS_H_ */
+#endif
diff --git a/src/tests/libknot/unittests_libknot.c b/src/tests/libknot/unittests_libknot.c
deleted file mode 100644
index d522e1d..0000000
--- a/src/tests/libknot/unittests_libknot.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-#include "knot/common.h"
-#include "common/libtap/tap_unit.h"
-
-// Units to test
-#include "tests/libknot/libknot/cuckoo_tests.h"
-#include "tests/libknot/libknot/dname_tests.h"
-#include "tests/libknot/libknot/edns_tests.h"
-#include "tests/libknot/libknot/node_tests.h"
-#include "tests/libknot/libknot/rdata_tests.h"
-#include "tests/libknot/libknot/response_tests.h"
-#include "tests/libknot/libknot/rrset_tests.h"
-#include "tests/libknot/libknot/zone_tests.h"
-#include "tests/libknot/libknot/dname_table_tests.h"
-#include "tests/libknot/libknot/nsec3_tests.h"
-#include "tests/libknot/libknot/packet_tests.h"
-#include "tests/libknot/libknot/query_tests.h"
-#include "tests/libknot/libknot/zonedb_tests.h"
-#include "tests/libknot/libknot/zone_tree_tests.h"
-#include "tests/libknot/libknot/tsig_tests.h"
-
-// Run all loaded units
-int main(int argc, char *argv[])
-{
- // Open log
-// log_init(LOG_UPTO(LOG_ERR), LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING));
-
- // Build test set
- unit_api *tests[] = {
-
- /* DNS units */
- &cuckoo_tests_api, //! Cuckoo hashing unit
- &dname_tests_api, //! DNS library (dname) unit
- &edns_tests_api, //! DNS library (EDNS0) unit
- &zone_tests_api, //! DNS library (zone) unit
- &node_tests_api, //! DNS library (node) unit
- &rdata_tests_api, //! DNS library (rdata) unit
- &response_tests_api, //! DNS library (response) unit
- &rrset_tests_api, //! DNS library (rrset) unit
- &dname_table_tests_api,
- &nsec3_tests_api,
- &packet_tests_api,
- &query_tests_api,
- &zonedb_tests_api, //! DNS library (zonedb) unit
- &zone_tree_tests_api,
- &tsig_tests_api,
- NULL
- };
-
- // Plan number of tests
- int id = 0;
- int test_count = 0;
- note("Units:");
- while (tests[id] != NULL) {
- note("- %s : %d tests", tests[id]->name,
- tests[id]->count(argc, argv));
- test_count += tests[id]->count(argc, argv);
- ++id;
- }
-
- plan(test_count);
-
- // Run tests
- id = 0;
- while (tests[id] != NULL) {
- diag("Testing unit: %s", tests[id]->name);
- tests[id]->run(argc, argv);
- ++id;
- }
-
-// log_close();
-
- // Evaluate
- return exit_status();
-}
-
diff --git a/src/tests/libknot/wire_tests.c b/src/tests/libknot/wire_tests.c
new file mode 100644
index 0000000..7e4d001
--- /dev/null
+++ b/src/tests/libknot/wire_tests.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "tests/libknot/wire_tests.h"
+#include "libknot/util/utils.h"
+
+static int wire_tests_count(int argc, char *argv[]);
+static int wire_tests_run(int argc, char *argv[]);
+
+unit_api wire_tests_api = {
+ "Wire",
+ &wire_tests_count,
+ &wire_tests_run
+};
+
+static int wire_tests_count(int argc, char *argv[])
+{
+ return 8;
+}
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ #define ENDIAN_MATCH(expression, match_little, match_big) \
+ ((expression) == (match_little))
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ #define ENDIAN_MATCH(expression, match_little, match_big) \
+ ((expression) == (match_big))
+#else
+ #error Unsupported byte order.
+#endif
+
+static int wire_tests_run(int argc, char *argv[])
+{
+ // 1. - 16-bit read
+ {
+ uint16_t data = 0xAABB;
+ ok(ENDIAN_MATCH(knot_wire_read_u16((uint8_t *)&data),
+ 0xBBAA, 0xAABB), "16-bit read");
+ }
+
+ // 2. - 16-bit read
+ {
+ uint16_t data_in = 0xAABB;
+ uint64_t data_out = 0xFF0000;
+ knot_wire_write_u16((uint8_t *)&data_out, data_in);
+ ok(ENDIAN_MATCH(data_out,
+ 0xFFBBAA, 0xFFAABB), "16-bit write");
+ }
+
+ // 3. - 32-bit read
+ {
+ uint32_t data = 0xAABBCCDD;
+ ok(ENDIAN_MATCH(knot_wire_read_u32((uint8_t *)&data),
+ 0xDDCCBBAA, 0xAABBCCDD), "32-bit read");
+ }
+
+ // 4. - 32-bit write
+ {
+ uint32_t data_in = 0xAABBCCDD;
+ uint64_t data_out = 0xFF00000000;
+ knot_wire_write_u32((uint8_t *)&data_out, data_in);
+ ok(ENDIAN_MATCH(data_out,
+ 0xFFDDCCBBAA, 0xFFAABBCCDD), "32-bit write");
+
+ }
+
+ // 5. - 48-bit read
+ {
+ uint64_t data = 0x81AABBCCDDEEFF;
+ ok(ENDIAN_MATCH(knot_wire_read_u48((uint8_t *)&data),
+ 0xFFEEDDCCBBAA, 0xAABBCCDDEEFF), "48-bit read");
+ }
+
+ // 6. - 48-bit write
+ {
+ uint64_t data_in = 0x81AABBCCDDEEFF;
+ uint64_t data_out = 0xDD000000000000;
+ knot_wire_write_u48((uint8_t *)&data_out, data_in);
+ ok(ENDIAN_MATCH(data_out,
+ 0xDDFFEEDDCCBBAA, 0xDDAABBCCDDEEFF), "48-bit write");
+ }
+
+ // 7. - 64-bit read
+ {
+ uint64_t data = 0x8899AABBCCDDEEFF;
+ ok(ENDIAN_MATCH(knot_wire_read_u64((uint8_t *)&data),
+ 0xFFEEDDCCBBAA9988, 0x8899AABBCCDDEEFF), "64-bit read");
+ }
+
+ // 8. - 64-bit write
+ {
+ uint64_t data_in = 0x8899AABBCCDDEEFF;
+ uint64_t data_out = 0x0;
+ knot_wire_write_u64((uint8_t *)&data_out, data_in);
+ ok(ENDIAN_MATCH(data_out,
+ 0xFFEEDDCCBBAA9988, 0x8899AABBCCDDEEFF), "64-bit write");
+ }
+
+ return 0;
+}
diff --git a/src/tests/libknot/realdata/libknot/zone_tests_realdata.h b/src/tests/libknot/wire_tests.h
index 5539709..37e038d 100644
--- a/src/tests/libknot/realdata/libknot/zone_tests_realdata.h
+++ b/src/tests/libknot/wire_tests.h
@@ -14,12 +14,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_ZONE_TESTS_H_
-#define _KNOTD_ZONE_TESTS_H_
+#ifndef _KNOTD_WIRE_TESTS_
+#define _KNOTD_WIRE_TESTS_
#include "common/libtap/tap_unit.h"
-/* Unit API. */
-unit_api zone_tests_api;
+unit_api wire_tests_api;
-#endif /* _KNOTD_ZONE_TESTS_H_ */
+#endif
diff --git a/src/tests/libknot/ztree_tests.c b/src/tests/libknot/ztree_tests.c
new file mode 100644
index 0000000..53506af
--- /dev/null
+++ b/src/tests/libknot/ztree_tests.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "tests/libknot/ztree_tests.h"
+#include "libknot/zone/zone-tree.h"
+
+#define NCOUNT 4
+static knot_dname_t* NAME[NCOUNT];
+static knot_node_t NODE[NCOUNT];
+static knot_dname_t* ORDER[NCOUNT];
+static void ztree_init_data()
+{
+ NAME[0] = knot_dname_new_from_str(".", 1, NULL);
+ NAME[1] = knot_dname_new_from_str("master.ac.", 10, NULL);
+ NAME[2] = knot_dname_new_from_str("ac.", 3, NULL);
+ NAME[3] = knot_dname_new_from_str("ns.", 3, NULL);
+
+ knot_dname_t *order[NCOUNT] = {
+ NAME[0], NAME[2], NAME[1], NAME[3]
+ };
+ memcpy(ORDER, order, NCOUNT * sizeof(knot_dname_t*));
+
+ for (unsigned i = 0; i < NCOUNT; ++i) {
+ memset(NODE + i, 0, sizeof(knot_node_t));
+ NODE[i].owner = NAME[i];
+ NAME[i]->node = NODE + i;
+ NODE[i].prev = NODE + ((NCOUNT + i - 1) % NCOUNT);
+ NODE[i].rrset_count = 1; /* required for ordered search */
+ }
+}
+
+static void ztree_free_data()
+{
+ for (unsigned i = 0; i < NCOUNT; ++i)
+ knot_dname_free(NAME + i);
+}
+
+struct ztree_iter {
+ int ret;
+ unsigned i;
+};
+
+static void ztree_iter_data(knot_node_t **node, void *data)
+{
+ struct ztree_iter *it = (struct ztree_iter*)data;
+ knot_dname_t *owner = (*node)->owner;
+ if (owner != ORDER[it->i]) {
+ it->ret = KNOT_ERROR;
+ char *exp_s = knot_dname_to_str(ORDER[it->i]);
+ char *owner_s = knot_dname_to_str(owner);
+ diag("ztree: at index: %u expected '%s' got '%s'\n", it->i, exp_s, owner_s);
+ free(exp_s);
+ free(owner_s);
+ }
+ ++it->i;
+}
+
+static int ztree_tests_count(int argc, char *argv[]);
+static int ztree_tests_run(int argc, char *argv[]);
+
+unit_api ztree_tests_api = {
+ "zone tree",
+ &ztree_tests_count,
+ &ztree_tests_run
+};
+
+static int ztree_tests_count(int argc, char *argv[])
+{
+ return 5;
+}
+
+static int ztree_tests_run(int argc, char *argv[])
+{
+ ztree_init_data();
+
+ /* 1. create test */
+ knot_zone_tree_t* t = knot_zone_tree_create();
+ ok(t != NULL, "ztree: created");
+
+ /* 2. insert test */
+ unsigned passed = 1;
+ for (unsigned i = 0; i < NCOUNT; ++i) {
+ if (knot_zone_tree_insert(t, NODE + i) != KNOT_EOK) {
+ passed = 0;
+ break;
+ }
+ }
+ ok(passed, "ztree: insertion");
+
+ /* 3. check data test */
+ passed = 1;
+ const knot_node_t *node = NULL;
+ for (unsigned i = 0; i < NCOUNT; ++i) {
+ int r = knot_zone_tree_find(t, NAME[i], &node);
+ if (r != KNOT_EOK || node != NODE + i) {
+ passed = 0;
+ break;
+ }
+ }
+ ok(passed, "ztree: lookup");
+
+ /* heal index for ordered lookup */
+ hattrie_build_index(t);
+
+ /* 4. ordered lookup */
+ passed = 1;
+ node = NULL;
+ const knot_node_t *prev = NULL;
+ knot_dname_t *tmp_dn = knot_dname_new_from_str("z.ac.", 5, NULL);
+ knot_zone_tree_find_less_or_equal(t, tmp_dn, &node, &prev);
+ knot_dname_free(&tmp_dn);
+ ok(prev == NODE + 1, "ztree: ordered lookup");
+
+ /* 5. ordered traversal */
+ struct ztree_iter it = { KNOT_EOK, 0 };
+ knot_zone_tree_apply_inorder(t, ztree_iter_data, &it);
+ ok (it.ret == KNOT_EOK, "ztree: ordered traversal");
+
+ knot_zone_tree_free(&t);
+ ztree_free_data();
+ return 0;
+}
diff --git a/src/tests/libknot/libknot/node_tests.h b/src/tests/libknot/ztree_tests.h
index a90179f..5362eeb 100644
--- a/src/tests/libknot/libknot/node_tests.h
+++ b/src/tests/libknot/ztree_tests.h
@@ -14,12 +14,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_NODE_TESTS_H_
-#define _KNOTD_NODE_TESTS_H_
+#ifndef _KNOT_ZTREE_TESTS_
+#define _KNOT_ZTREE_TESTS_
#include "common/libtap/tap_unit.h"
-/* Unit API. */
-unit_api node_tests_api;
+unit_api ztree_tests_api;
-#endif /* _KNOTD_NODE_TESTS_H_ */
+#endif
diff --git a/src/tests/unittests_main.c b/src/tests/unittests_main.c
index aee4bf9..d0bef81 100644
--- a/src/tests/unittests_main.c
+++ b/src/tests/unittests_main.c
@@ -15,22 +15,30 @@
*/
#include <config.h>
-#include "knot/common.h"
+#include "knot/knot.h"
#include "common/libtap/tap_unit.h"
// Units to test
#include "tests/common/slab_tests.h"
#include "tests/common/skiplist_tests.h"
+#include "tests/common/hattrie_tests.h"
#include "tests/common/events_tests.h"
#include "tests/common/acl_tests.h"
#include "tests/common/fdset_tests.h"
#include "tests/common/base64_tests.h"
#include "tests/common/base32hex_tests.h"
+#include "tests/common/descriptor_tests.h"
#include "tests/knot/dthreads_tests.h"
#include "tests/knot/journal_tests.h"
#include "tests/knot/server_tests.h"
#include "tests/knot/conf_tests.h"
#include "tests/knot/rrl_tests.h"
+#include "tests/zscanner/zscanner_tests.h"
+#include "tests/libknot/wire_tests.h"
+#include "tests/libknot/dname_tests.h"
+#include "tests/libknot/ztree_tests.h"
+#include "tests/libknot/sign_tests.h"
+#include "tests/libknot/rrset_tests.h"
// Run all loaded units
int main(int argc, char *argv[])
@@ -43,22 +51,35 @@ int main(int argc, char *argv[])
// Build test set
unit_api *tests[] = {
- /* Core data structures. */
- &journal_tests_api, //! Journal unit
- &slab_tests_api, //! SLAB allocator unit
- &skiplist_tests_api, //! Skip list unit
- &dthreads_tests_api, //! DThreads testing unit
- &events_tests_api, //! Events testing unit
- &acl_tests_api, //! ACLs
- &fdset_tests_api, //! FDSET polling wrapper
- &base64_tests_api, //! Base64 encoding
- &base32hex_tests_api, //! Base32hex encoding
-
- /* Server parts. */
- &conf_tests_api, //! Configuration parser tests
- &server_tests_api, //! Server unit
- &rrl_tests_api, //! RRL tests
- NULL
+ /* Core data structures. */
+ &journal_tests_api, //! Journal unit
+ &slab_tests_api, //! SLAB allocator unit
+ &skiplist_tests_api, //! Skip list unit
+ &hattrie_tests_api, //! HAT trie unit
+ &dthreads_tests_api, //! DThreads testing unit
+ &events_tests_api, //! Events testing unit
+ &acl_tests_api, //! ACLs
+ &fdset_tests_api, //! FDSET polling wrapper
+ &base64_tests_api, //! Base64 encoding
+ &base32hex_tests_api, //! Base32hex encoding
+ &descriptor_tests_api, //! RR descriptors
+
+ /* Server parts. */
+ &conf_tests_api, //! Configuration parser tests
+ &server_tests_api, //! Server unit
+ &rrl_tests_api, //! RRL tests
+
+ /* Zone scanner. */
+ &zscanner_tests_api, //! Wrapper for external unittests
+
+ /* Libknot library. */
+ &wire_tests_api,
+ &dname_tests_api,
+ &ztree_tests_api,
+ &sign_tests_api, //! Key manipulation.
+ &rrset_tests_api,
+
+ NULL
};
// Plan number of tests
@@ -87,4 +108,3 @@ int main(int argc, char *argv[])
// Evaluate
return exit_status();
}
-
diff --git a/src/tests/xfr_tests.c b/src/tests/xfr_tests.c
index db6c486..fee09f2 100644
--- a/src/tests/xfr_tests.c
+++ b/src/tests/xfr_tests.c
@@ -21,14 +21,15 @@
* binary that an integrity check should be done
*/
-#include <time.h>
#include <config.h>
+#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
+#include <assert.h>
-#include "knot/common.h"
+#include "knot/knot.h"
#include "knot/server/server.h"
#include "knot/ctl/process.h"
#include "knot/conf/conf.h"
@@ -64,7 +65,7 @@ void interrupt_handle(int s)
exit(1);
}
}
-
+
// Start zone integrity check
if (s == SIGUSR1) {
sig_integrity_check = 1;
@@ -93,9 +94,9 @@ int main(int argc, char **argv)
int c = 0, li = 0;
int verbose = 0;
int daemonize = 0;
- char* config_fn = NULL;
+ char *config_fn = NULL;
char *zone = NULL;
-
+
/* Long options. */
struct option opts[] = {
{"config", required_argument, 0, 'c'},
@@ -106,7 +107,7 @@ int main(int argc, char **argv)
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
-
+
while ((c = getopt_long(argc, argv, "c:z:dvVh", opts, &li)) != -1) {
switch (c)
{
@@ -123,7 +124,11 @@ int main(int argc, char **argv)
printf("%s, version %s\n", "Knot DNS", PACKAGE_VERSION);
return 0;
case 'z':
- zone = strdup(optarg);
+ if (optarg[strlen(optarg) - 1] != '.') {
+ zone = strcdup(optarg, ".");
+ } else {
+ zone = strdup(optarg);
+ }
break;
case 'h':
case '?':
@@ -135,7 +140,7 @@ int main(int argc, char **argv)
// Now check if we want to daemonize
if (daemonize) {
- if (daemon(1, 0) != 0) {
+ if (daemon(1, 0) != 0) {
free(zone);
free(config_fn);
fprintf(stderr, "Daemonization failed, "
@@ -315,6 +320,7 @@ int main(int argc, char **argv)
if (sig_integrity_check) {
log_server_info("Starting integrity check of zone: %s\n", zone);
knot_dname_t* zdn = knot_dname_new_from_str(zone, strlen(zone), NULL);
+ assert(zdn);
knot_zone_t *z = knot_zonedb_find_zone(server->nameserver->zone_db, zdn);
int ic_ret = knot_zone_contents_integrity_check(z->contents);
log_server_info("Integrity check: %d errors discovered.\n", ic_ret);
@@ -376,4 +382,3 @@ int main(int argc, char **argv)
return res;
}
-
diff --git a/src/tests/zscanner/zscanner_tests.c b/src/tests/zscanner/zscanner_tests.c
new file mode 100644
index 0000000..112c928
--- /dev/null
+++ b/src/tests/zscanner/zscanner_tests.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "tests/zscanner/zscanner_tests.h"
+
+#include <stdlib.h>
+
+static int zscanner_tests_count(int argc, char *argv[]);
+static int zscanner_tests_run(int argc, char *argv[]);
+
+unit_api zscanner_tests_api = {
+ "Zone scanner",
+ &zscanner_tests_count,
+ &zscanner_tests_run
+};
+
+static int zscanner_tests_count(int argc, char *argv[])
+{
+ return 1;
+}
+
+static int zscanner_tests_run(int argc, char *argv[])
+{
+ int ret;
+
+ ret = system("/bin/sh ../zscanner/test/run_tests.sh test");
+ cmp_ok(ret, "==", 0, "zscanner unittests");
+
+ return 0;
+}
diff --git a/src/tests/libknot/realdata/libknot/node_tests_realdata.h b/src/tests/zscanner/zscanner_tests.h
index a90179f..eae23ca 100644
--- a/src/tests/libknot/realdata/libknot/node_tests_realdata.h
+++ b/src/tests/zscanner/zscanner_tests.h
@@ -14,12 +14,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_NODE_TESTS_H_
-#define _KNOTD_NODE_TESTS_H_
+#ifndef _ZSCANNER_TESTS_H_
+#define _ZSCANNER_TESTS_H_
#include "common/libtap/tap_unit.h"
/* Unit API. */
-unit_api node_tests_api;
+unit_api zscanner_tests_api;
-#endif /* _KNOTD_NODE_TESTS_H_ */
+#endif /* _ZSCANNER_TESTS_H_ */
diff --git a/src/utils/common/exec.c b/src/utils/common/exec.c
new file mode 100644
index 0000000..0a9c1a9
--- /dev/null
+++ b/src/utils/common/exec.c
@@ -0,0 +1,671 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/common/exec.h"
+
+#include <stdlib.h> // free
+#include <time.h> // localtime_r
+
+#include "libknot/libknot.h"
+#include "common/lists.h" // list
+#include "common/print.h" // txt_print
+#include "common/errcode.h" // KNOT_EOK
+#include "common/descriptor.h" // KNOT_RRTYPE_
+#include "utils/common/msg.h" // WARN
+#include "utils/common/params.h" // params_t
+#include "utils/common/netio.h" // send_msg
+
+static knot_lookup_table_t rtypes[] = {
+ { KNOT_RRTYPE_A, "has IPv4 address" },
+ { KNOT_RRTYPE_NS, "nameserver is" },
+ { KNOT_RRTYPE_CNAME, "is an alias for" },
+ { KNOT_RRTYPE_SOA, "start of authority is" },
+ { KNOT_RRTYPE_PTR, "points to" },
+ { KNOT_RRTYPE_MX, "mail is handled by" },
+ { KNOT_RRTYPE_TXT, "description is" },
+ { KNOT_RRTYPE_AAAA, "has IPv6 address" },
+ { KNOT_RRTYPE_LOC, "location is" },
+ { KNOT_RRTYPE_DS, "delegation signature is" },
+ { KNOT_RRTYPE_SSHFP, "SSH fingerprint is" },
+ { KNOT_RRTYPE_RRSIG, "RR set signature is" },
+ { KNOT_RRTYPE_DNSKEY, "DNSSEC key is" },
+ { KNOT_RRTYPE_TLSA, "has TLS certificate" },
+ { 0, NULL }
+};
+
+static void print_header(const knot_packet_t *packet, const style_t *style)
+{
+ char flags[64] = "";
+ uint8_t rcode_id, opcode_id;
+ const char *rcode_str = "NULL";
+ const char *opcode_str = "NULL";
+ knot_lookup_table_t *rcode, *opcode;
+
+ // Get codes.
+ rcode_id = knot_wire_get_rcode(packet->wireformat);
+ rcode = knot_lookup_by_id(knot_rcode_names, rcode_id);
+ if (rcode != NULL) {
+ rcode_str = rcode->name;
+ }
+
+ opcode_id = knot_wire_get_opcode(packet->wireformat);
+ opcode = knot_lookup_by_id(knot_opcode_names, opcode_id);
+ if (opcode != NULL) {
+ opcode_str = opcode->name;
+ }
+
+ // Get flags.
+ if (knot_wire_get_qr(packet->wireformat) != 0) {
+ strcat(flags, " qr");
+ }
+ if (knot_wire_get_aa(packet->wireformat) != 0) {
+ strcat(flags, " aa");
+ }
+ if (knot_wire_get_tc(packet->wireformat) != 0) {
+ strcat(flags, " tc");
+ }
+ if (knot_wire_get_rd(packet->wireformat) != 0) {
+ strcat(flags, " rd");
+ }
+ if (knot_wire_get_ra(packet->wireformat) != 0) {
+ strcat(flags, " ra");
+ }
+ if (knot_wire_get_z(packet->wireformat) != 0) {
+ strcat(flags, " z");
+ }
+ if (knot_wire_get_ad(packet->wireformat) != 0) {
+ strcat(flags, " ad");
+ }
+ if (knot_wire_get_cd(packet->wireformat) != 0) {
+ strcat(flags, " cd");
+ }
+
+ // Print formated info.
+ switch (style->format) {
+ case FORMAT_NSUPDATE:
+ printf("\n;; ->>HEADER<<- opcode: %s; status: %s; id: %u\n"
+ ";; Flags:%1s; "
+ "ZONE: %u; PREREQ: %u; UPDATE: %u; ADDITIONAL: %u\n",
+ opcode_str, rcode_str, knot_packet_id(packet),
+ flags, packet->header.qdcount, packet->header.ancount,
+ packet->header.nscount, packet->header.arcount);
+
+ break;
+ default:
+ printf("\n;; ->>HEADER<<- opcode: %s; status: %s; id: %u\n"
+ ";; Flags:%1s; "
+ "QUERY: %u; ANSWER: %u; AUTHORITY: %u; ADDITIONAL: %u\n",
+ opcode_str, rcode_str, knot_packet_id(packet),
+ flags, packet->header.qdcount, packet->header.ancount,
+ packet->header.nscount, packet->header.arcount);
+ break;
+ }
+}
+
+static void print_footer(const size_t total_len,
+ const size_t msg_count,
+ const size_t rr_count,
+ const net_t *net,
+ const float elapsed,
+ const bool incoming)
+{
+ struct tm tm;
+ char date[64];
+
+ // Get current timestamp.
+ time_t now = time(NULL);
+ localtime_r(&now, &tm);
+
+ // Create formated date-time string.
+ strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S %Z", &tm);
+
+ // Print messages statistics.
+ if (incoming) {
+ printf("\n;; Received %zu B", total_len);
+ } else {
+ printf("\n;; Sent %zu B", total_len);
+ }
+
+ // If multimessage (XFR) print additional statistics.
+ if (msg_count > 0) {
+ printf(" (%zu messages, %zu records)\n", msg_count, rr_count);
+ } else {
+ printf("\n");
+ }
+ // Print date.
+ printf(";; Time %s\n", date);
+
+ // Print connection statistics.
+ if (net != NULL) {
+ if (incoming) {
+ printf(";; From %s", net->remote_str);
+ } else {
+ printf(";; To %s", net->remote_str);
+ }
+
+ if (elapsed >= 0) {
+ printf(" in %.1f ms\n", elapsed);
+
+ } else {
+ printf("\n");
+
+ }
+ }
+}
+
+static void print_opt_section(const knot_opt_rr_t *rr)
+{
+ printf("Version: %u; flags: %s; UDP size: %u B\n",
+ knot_edns_get_version(rr),
+ (knot_edns_do(rr) != 0) ? "do" : "",
+ knot_edns_get_payload(rr));
+
+ for (int i = 0; i < rr->option_count; i++) {
+ knot_opt_option_t *opt = &(rr->options[i]);
+
+ if (opt->code == EDNS_OPTION_NSID) {
+ printf(";; NSID: ");
+ short_hex_print(opt->data, opt->length);
+ printf(";; : ");
+ txt_print(opt->data, opt->length);
+ } else {
+ printf(";; Option (%u): ", opt->code);
+ short_hex_print(opt->data, opt->length);
+ }
+ }
+}
+
+static void print_section_question(const knot_dname_t *owner,
+ const uint16_t qclass,
+ const uint16_t qtype,
+ const style_t *style)
+{
+ size_t buflen = 8192;
+ char *buf = calloc(buflen, 1);
+
+ knot_rrset_t *question = knot_rrset_new((knot_dname_t *)owner, qtype,
+ qclass, 0);
+
+ if (knot_rrset_txt_dump_header(question, 0, buf, buflen,
+ &(style->style)) < 0) {
+ WARN("can't print whole question section\n");
+ }
+
+ printf("%s\n", buf);
+
+ knot_rrset_free(&question);
+ free(buf);
+}
+
+static void print_section_full(const knot_rrset_t **rrsets,
+ const uint16_t count,
+ const style_t *style)
+{
+ size_t buflen = 8192;
+ char *buf = calloc(buflen, 1);
+
+ for (size_t i = 0; i < count; i++) {
+ if (rrsets[i]->type == KNOT_RRTYPE_OPT) {
+ continue;
+ }
+
+ while (knot_rrset_txt_dump(rrsets[i], buf, buflen,
+ &(style->style)) < 0)
+ {
+ buflen += 4096;
+ buf = realloc(buf, buflen);
+
+ // Oversize protection.
+ if (buflen > 1000000) {
+ WARN("can't print whole section\n");
+ break;
+ }
+ }
+ printf("%s", buf);
+ }
+
+ free(buf);
+}
+
+static void print_section_dig(const knot_rrset_t **rrsets,
+ const uint16_t count,
+ const style_t *style)
+{
+ size_t buflen = 8192;
+ char *buf = calloc(buflen, 1);
+
+ for (size_t i = 0; i < count; i++) {
+ const knot_rrset_t *rrset = rrsets[i];
+
+ for (size_t j = 0; j < rrset->rdata_count; j++) {
+ while (knot_rrset_txt_dump_data(rrset, j, buf, buflen,
+ &(style->style)) < 0) {
+ buflen += 4096;
+ buf = realloc(buf, buflen);
+
+ // Oversize protection.
+ if (buflen > 1000000) {
+ WARN("can't print whole section\n");
+ break;
+ }
+ }
+ printf("%s\n", buf);
+ }
+ }
+
+ free(buf);
+}
+
+static void print_section_host(const knot_rrset_t **rrsets,
+ const uint16_t count,
+ const style_t *style)
+{
+ size_t buflen = 8192;
+ char *buf = calloc(buflen, 1);
+
+ for (size_t i = 0; i < count; i++) {
+ const knot_rrset_t *rrset = rrsets[i];
+ knot_lookup_table_t *descr;
+ char type[32] = "NULL";
+ char *owner;
+
+ owner = knot_dname_to_str(rrset->owner);
+ descr = knot_lookup_by_id(rtypes, rrset->type);
+
+ for (size_t j = 0; j < rrset->rdata_count; j++) {
+ while (knot_rrset_txt_dump_data(rrset, j, buf, buflen,
+ &(style->style)) < 0) {
+ buflen += 4096;
+ buf = realloc(buf, buflen);
+
+ // Oversize protection.
+ if (buflen > 1000000) {
+ WARN("can't print whole RR set\n");
+ break;
+ }
+ }
+
+ if (descr != NULL) {
+ printf("%s %s %s\n", owner, descr->name, buf);
+ } else {
+ knot_rrtype_to_string(rrset->type, type,
+ sizeof(type));
+ printf("%s has %s record %s\n",
+ owner, type, buf);
+ }
+ }
+
+ free(owner);
+ }
+
+ free(buf);
+}
+
+static void print_error_host(const uint8_t code,
+ const knot_question_t *question)
+{
+ const char *rcode_str = "NULL";
+ char type[32] = "NULL";
+ char *owner;
+
+ knot_lookup_table_t *rcode;
+
+ owner = knot_dname_to_str(question->qname);
+ rcode = knot_lookup_by_id(knot_rcode_names, code);
+ if (rcode != NULL) {
+ rcode_str = rcode->name;
+ }
+ knot_rrtype_to_string(question->qtype, type, sizeof(type));
+
+ if (code == KNOT_RCODE_NOERROR) {
+ printf("Host %s has no %s record\n", owner, type);
+ } else {
+ printf("Host %s type %s error: %s\n", owner, type, rcode_str);
+ }
+
+ free(owner);
+}
+
+knot_packet_t* create_empty_packet(const knot_packet_prealloc_type_t type,
+ const size_t max_size)
+{
+ // Create packet skeleton.
+ knot_packet_t *packet = knot_packet_new(type);
+ if (packet == NULL) {
+ DBG_NULL;
+ return NULL;
+ }
+
+ // Set packet buffer size.
+ knot_packet_set_max_size(packet, max_size);
+
+ // Set random sequence id.
+ knot_packet_set_random_id(packet);
+
+ // Initialize query packet.
+ knot_query_init(packet);
+
+ return packet;
+}
+
+void print_header_xfr(const knot_question_t *question, const style_t *style)
+{
+ if (style == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ char xfr[16] = "AXFR";
+
+ switch (question->qtype) {
+ case KNOT_RRTYPE_AXFR:
+ break;
+ case KNOT_RRTYPE_IXFR:
+ xfr[0] = 'I';
+ break;
+ default:
+ return;
+ }
+
+ if (style->show_header) {
+ char *owner = knot_dname_to_str(question->qname);
+ if (owner != NULL) {
+ printf("\n;; %s for %s\n", xfr, owner);
+ free(owner);
+ }
+ }
+}
+
+void print_data_xfr(const knot_packet_t *packet,
+ const style_t *style)
+{
+ if (packet == NULL || style == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ switch (style->format) {
+ case FORMAT_DIG:
+ print_section_dig(packet->answer, packet->header.ancount,style);
+ break;
+ case FORMAT_HOST:
+ print_section_host(packet->answer, packet->header.ancount, style);
+ break;
+ case FORMAT_FULL:
+ print_section_full(packet->answer, packet->header.ancount, style);
+
+ // Print TSIG record if any.
+ if (style->show_additional) {
+ print_section_full(packet->additional,
+ packet->header.arcount,
+ style);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void print_footer_xfr(const size_t total_len,
+ const size_t msg_count,
+ const size_t rr_count,
+ const net_t *net,
+ const float elapsed,
+ const style_t *style)
+{
+ if (style == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ if (style->show_footer) {
+ print_footer(total_len, msg_count, rr_count, net, elapsed, true);
+ }
+}
+
+void print_packet(const knot_packet_t *packet,
+ const size_t total_len,
+ const net_t *net,
+ const float elapsed,
+ const bool incoming,
+ const style_t *style)
+{
+ if (packet == NULL || style == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ uint16_t additionals = packet->header.arcount;
+
+ // Print packet information header.
+ if (style->show_header) {
+ print_header(packet, style);
+ }
+
+ // Print EDNS section.
+ if (knot_edns_get_version(&packet->opt_rr) != EDNS_NOT_SUPPORTED) {
+ if (style->show_edns) {
+ printf("\n;; EDNS PSEUDOSECTION:\n;; ");
+ print_opt_section(&packet->opt_rr);
+ }
+
+ additionals--;
+ }
+
+ // Print DNS sections.
+ switch (style->format) {
+ case FORMAT_DIG:
+ if (packet->header.ancount > 0) {
+ print_section_dig(packet->answer, packet->header.ancount,
+ style);
+ }
+ break;
+ case FORMAT_HOST:
+ if (packet->header.ancount > 0) {
+ print_section_host(packet->answer, packet->header.ancount,
+ style);
+ } else {
+ uint8_t rcode = knot_wire_get_rcode(packet->wireformat);
+ print_error_host(rcode, &packet->question);
+ }
+ break;
+ case FORMAT_NSUPDATE:
+ if (style->show_question && packet->header.qdcount > 0) {
+ printf("\n;; ZONE SECTION:\n;; ");
+ print_section_question(packet->question.qname,
+ packet->question.qclass,
+ packet->question.qtype,
+ style);
+ }
+
+ if (style->show_answer && packet->header.ancount > 0) {
+ printf("\n;; PREREQUISITE SECTION:\n");
+ print_section_full(packet->answer,
+ packet->header.ancount,
+ style);
+ }
+
+ if (style->show_authority && packet->header.nscount > 0) {
+ printf("\n;; UPDATE SECTION:\n");
+ print_section_full(packet->authority,
+ packet->header.nscount,
+ style);
+ }
+
+ if (style->show_additional && additionals > 0) {
+ printf("\n;; ADDITIONAL DATA:\n");
+ print_section_full(packet->additional,
+ packet->header.arcount,
+ style);
+ }
+ break;
+ case FORMAT_FULL:
+ if (style->show_question && packet->header.qdcount > 0) {
+ printf("\n;; QUESTION SECTION:\n;; ");
+ print_section_question(packet->question.qname,
+ packet->question.qclass,
+ packet->question.qtype,
+ style);
+ }
+
+ if (style->show_answer && packet->header.ancount > 0) {
+ printf("\n;; ANSWER SECTION:\n");
+ print_section_full(packet->answer,
+ packet->header.ancount,
+ style);
+ }
+
+ if (style->show_authority && packet->header.nscount > 0) {
+ printf("\n;; AUTHORITY SECTION:\n");
+ print_section_full(packet->authority,
+ packet->header.nscount,
+ style);
+ }
+
+ if (style->show_additional && additionals > 0) {
+ printf("\n;; ADDITIONAL SECTION:\n");
+ print_section_full(packet->additional,
+ packet->header.arcount,
+ style);
+ }
+ break;
+ default:
+ break;
+ }
+
+ // Print packet statistics.
+ if (style->show_footer) {
+ print_footer(total_len, 0, 0, net, elapsed, incoming);
+ }
+}
+
+void free_sign_context(sign_context_t *ctx)
+{
+ if (ctx == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ if (ctx->tsig_key.name) {
+ knot_tsig_key_free(&ctx->tsig_key);
+ }
+
+ if (ctx->dnssec_key.name) {
+ knot_dnssec_key_free(&ctx->dnssec_key);
+ }
+
+ free(ctx->digest);
+
+ memset(ctx, '\0', sizeof(sign_context_t));
+}
+
+int sign_packet(knot_packet_t *pkt,
+ sign_context_t *sign_ctx,
+ const knot_key_params_t *key_params)
+{
+ int result;
+
+ if (pkt == NULL || sign_ctx == NULL || key_params == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ uint8_t *wire = pkt->wireformat;
+ size_t *wire_size = &pkt->size;
+ size_t max_size = knot_packet_max_size(pkt);
+
+ switch (knot_get_key_type(key_params)) {
+ case KNOT_KEY_TSIG:
+ {
+ result = knot_tsig_key_from_params(key_params,
+ &sign_ctx->tsig_key);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ knot_tsig_key_t *key = &sign_ctx->tsig_key;
+
+ sign_ctx->digest_size = knot_tsig_digest_length(key->algorithm);
+ sign_ctx->digest = malloc(sign_ctx->digest_size);
+
+ size_t tsig_size = tsig_wire_maxsize(key);
+ knot_packet_set_tsig_size(pkt, tsig_size);
+
+ result = knot_tsig_sign(wire, wire_size, max_size, NULL, 0,
+ sign_ctx->digest, &sign_ctx->digest_size,
+ key, 0, 0);
+
+ return result;
+ }
+ case KNOT_KEY_DNSSEC:
+ {
+ result = knot_dnssec_key_from_params(key_params,
+ &sign_ctx->dnssec_key);
+ if (result != KNOT_EOK) {
+ return result;
+ }
+
+ knot_dnssec_key_t *key = &sign_ctx->dnssec_key;
+ result = knot_sig0_sign(wire, wire_size, max_size, key);
+
+ return result;
+ }
+ default:
+ return KNOT_DNSSEC_EINVALID_KEY;
+ }
+}
+
+int verify_packet(const knot_packet_t *pkt,
+ const sign_context_t *sign_ctx,
+ const knot_key_params_t *key_params)
+{
+ int result;
+
+ if (pkt == NULL || sign_ctx == NULL || key_params == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ const uint8_t *wire = pkt->wireformat;
+ const size_t *wire_size = &pkt->size;
+
+ switch (knot_get_key_type(key_params)) {
+ case KNOT_KEY_TSIG:
+ {
+ const knot_rrset_t *tsig_rr = knot_packet_tsig(pkt);
+ if (tsig_rr == NULL) {
+ return KNOT_ENOTSIG;
+ }
+
+ result = knot_tsig_client_check(tsig_rr, wire, *wire_size,
+ sign_ctx->digest,
+ sign_ctx->digest_size,
+ &sign_ctx->tsig_key, 0);
+
+ return result;
+ }
+ case KNOT_KEY_DNSSEC:
+ {
+ // Uses public key cryptography, server cannot sign the
+ // response, because the private key should be known only
+ // to the client.
+ return KNOT_EOK;
+ }
+ default:
+ return KNOT_EINVAL;
+ }
+}
diff --git a/src/utils/common/exec.h b/src/utils/common/exec.h
new file mode 100644
index 0000000..63189e1
--- /dev/null
+++ b/src/utils/common/exec.h
@@ -0,0 +1,142 @@
+/* Copyright (C) 2011 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 exec.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Common executives for utils.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _UTILS__EXEC_H_
+#define _UTILS__EXEC_H_
+
+#include "utils/common/netio.h" // net_t
+#include "utils/common/params.h" // style_t
+#include "libknot/libknot.h"
+
+/*! \brief Holds data required between signing and signature verification. */
+typedef struct {
+ knot_tsig_key_t tsig_key;
+ knot_dnssec_key_t dnssec_key;
+ uint8_t *digest;
+ size_t digest_size;
+} sign_context_t;
+
+/*!
+ * \brief Allocates empty packet and sets packet size and random id.
+ *
+ * \param type Packet preallocation type.
+ * \param max_size Maximal packet size.
+ *
+ * \retval packet if success.
+ * \retval NULL if error.
+ */
+knot_packet_t* create_empty_packet(const knot_packet_prealloc_type_t type,
+ const size_t max_size);
+
+/*!
+ * \brief Prints information header for transfer.
+ *
+ * \param question Packet question section.
+ * \param style Style of the output.
+ */
+void print_header_xfr(const knot_question_t *question, const style_t *style);
+
+/*!
+ * \brief Prints answer section for 1 transfer message.
+ *
+ * \param packet Response packet.
+ * \param style Style of the output.
+ */
+void print_data_xfr(const knot_packet_t *packet,
+ const style_t *style);
+
+/*!
+ * \brief Prints trailing statistics for transfer.
+ *
+ * \param total_len Total reply size (all messages).
+ * \param msg_count Number of messages.
+ * \param rr_count Total number of answer records.
+ * \param net Connection information.
+ * \param elapse Total elapsed time.
+ * \param style Style of the otput.
+ */
+void print_footer_xfr(const size_t total_len,
+ const size_t msg_count,
+ const size_t rr_count,
+ const net_t *net,
+ const float elapsed,
+ const style_t *style);
+
+/*!
+ * \brief Prints one response packet.
+ *
+ * \param packet Response packet.
+ * \param total_len Total reply size (all messages).
+ * \param net Connection information.
+ * \param elapse Total elapsed time.
+ * \param incoming Indicates if the packet is input.
+ * \param style Style of the otput.
+ */
+void print_packet(const knot_packet_t *packet,
+ const size_t total_len,
+ const net_t *net,
+ const float elapsed,
+ const bool incoming,
+ const style_t *style);
+
+/*!
+ * \brief Cleans up sign context.
+ *
+ * \param ctx Sign context.
+ */
+void free_sign_context(sign_context_t *ctx);
+
+/*!
+ * \brief Signs outgoing DNS packet.
+ *
+ * \param pkt Packet to sign.
+ * \param sign_ctx Sign context.
+ * \param key_params Key parameters.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval error code if error.
+ */
+int sign_packet(knot_packet_t *pkt,
+ sign_context_t *sign_ctx,
+ const knot_key_params_t *key_params);
+
+/*!
+ * \brief Verifies signature for incoming DNS packet.
+ *
+ * \param pkt Packet verify sign.
+ * \param sign_ctx Sign context.
+ * \param key_params Key parameters.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval error code if error.
+ */
+int verify_packet(const knot_packet_t *pkt,
+ const sign_context_t *sign_ctx,
+ const knot_key_params_t *key_params);
+
+#endif // _UTILS__EXEC_H_
+
+/*! @} */
diff --git a/src/tests/libknot/libknot/dname_table_tests.h b/src/utils/common/msg.c
index f3088e9..412bee8 100644
--- a/src/tests/libknot/libknot/dname_table_tests.h
+++ b/src/utils/common/msg.c
@@ -12,14 +12,30 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
+*/
-#ifndef _KNOTD_DNAME_TABLE_TESTS_H_
-#define _KNOTD_DNAME_TABLE_TESTS_H_
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
-#include "common/libtap/tap_unit.h"
+#include "utils/common/msg.h"
-/* Unit API. */
-unit_api dname_table_tests_api;
+static volatile int MSG_DBG_STATE = 0; /* True if debugging is enabled. */
-#endif /* _KNOTD_DNAME_TABLE_TESTS_H_ */
+int msg_enable_debug(int val)
+{
+ return MSG_DBG_STATE = val;
+}
+
+int msg_debug(const char *fmt, ...)
+{
+ int n = 0;
+ if (MSG_DBG_STATE) {
+ va_list ap;
+ va_start(ap, fmt);
+ n = vprintf(fmt, ap);
+ va_end(ap);
+ }
+ return n;
+}
diff --git a/src/utils/common/msg.h b/src/utils/common/msg.h
new file mode 100644
index 0000000..7e32f4e
--- /dev/null
+++ b/src/utils/common/msg.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2011 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 msg.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Simple output formatting framework.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _UTILS__MSG_H_
+#define _UTILS__MSG_H_
+
+#include <stdio.h> // printf
+
+#define ERROR_ "; Error: "
+#define INFO_ "; Info: "
+#define WARNING_ "; Warning: "
+#define DEBUG_ "; Debug: "
+
+#define ERR(m...) { printf(ERROR_ m); fflush(stdout); }
+#define INFO(m...) { printf(INFO_ m); fflush(stdout); }
+#define WARN(m...) { printf(WARNING_ m); fflush(stdout); }
+
+/*! \brief Enable/disable debugging. */
+int msg_enable_debug(int val);
+
+/*! \brief Print debug message. */
+int msg_debug(const char *fmt, ...);
+
+#ifndef NDEBUG
+ #define DBG(m...) msg_debug(DEBUG_ m)
+#else
+ #define DBG(m...)
+#endif
+
+/*! \brief Debug message for null input. */
+#define DBG_NULL DBG("%s: null parameter\n", __func__)
+
+#endif // _UTILS__MSG_H_
+
+/*! @} */
diff --git a/src/utils/common/netio.c b/src/utils/common/netio.c
new file mode 100644
index 0000000..7ac251d
--- /dev/null
+++ b/src/utils/common/netio.c
@@ -0,0 +1,465 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/common/netio.h"
+
+#include <stdlib.h> // free
+#include <netdb.h> // addrinfo
+#include <poll.h> // poll
+#include <fcntl.h> // fcntl
+#include <sys/socket.h> // AF_INET (BSD)
+#include <netinet/in.h> // ntohl (BSD)
+#include <arpa/inet.h> // inet_ntop
+#include <unistd.h> // close
+#ifdef HAVE_SYS_UIO_H // struct iovec (OpenBSD)
+#include <sys/uio.h>
+#endif // HAVE_SYS_UIO_H
+
+#include "utils/common/msg.h" // WARN
+#include "common/descriptor.h" // KNOT_CLASS_IN
+#include "common/errcode.h" // KNOT_E
+
+server_t* server_create(const char *name, const char *service)
+{
+ if (name == NULL || service == NULL) {
+ DBG_NULL;
+ return NULL;
+ }
+
+ // Create output structure.
+ server_t *server = calloc(1, sizeof(server_t));
+
+ // Check output.
+ if (server == NULL) {
+ return NULL;
+ }
+
+ // Fill output.
+ server->name = strdup(name);
+ server->service = strdup(service);
+
+ if (server->name == NULL || server->service == NULL) {
+ server_free(server);
+ return NULL;
+ }
+
+ // Return result.
+ return server;
+}
+
+void server_free(server_t *server)
+{
+ if (server == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ free(server->name);
+ free(server->service);
+ free(server);
+}
+
+int get_iptype(const ip_t ip)
+{
+ switch (ip) {
+ case IP_4:
+ return AF_INET;
+ case IP_6:
+ return AF_INET6;
+ default:
+ return AF_UNSPEC;
+ }
+}
+
+int get_socktype(const protocol_t proto, const uint16_t type)
+{
+ switch (proto) {
+ case PROTO_TCP:
+ return SOCK_STREAM;
+ case PROTO_UDP:
+ return SOCK_DGRAM;
+ default:
+ if (type == KNOT_RRTYPE_AXFR || type == KNOT_RRTYPE_IXFR) {
+ return SOCK_STREAM;
+ } else {
+ return SOCK_DGRAM;
+ }
+ }
+}
+
+const char* get_sockname(const int socktype)
+{
+ const char *proto;
+
+ switch (socktype) {
+ case SOCK_STREAM:
+ proto = "TCP";
+ break;
+ case SOCK_DGRAM:
+ proto = "UDP";
+ break;
+ default:
+ proto = "UNKNOWN";
+ break;
+ }
+
+ return proto;
+}
+
+static int get_addr(const server_t *server,
+ const int iptype,
+ const int socktype,
+ struct addrinfo **info)
+{
+ struct addrinfo hints;
+
+ // Set connection hints.
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = iptype;
+ hints.ai_socktype = socktype;
+
+ // Get connection parameters.
+ if (getaddrinfo(server->name, server->service, &hints, info) != 0) {
+ ERR("can't resolve address %s#%s\n",
+ server->name, server->service);
+ return -1;
+ }
+
+ return 0;
+}
+
+static void get_addr_str(const struct sockaddr_storage *ss,
+ const int socktype,
+ char **dst)
+{
+ char addr[INET6_ADDRSTRLEN] = "NULL";
+ char buf[128] = "NULL";
+ uint16_t port;
+
+ // Get network address string and port number.
+ if (ss->ss_family == AF_INET) {
+ struct sockaddr_in *s = (struct sockaddr_in *)ss;
+ inet_ntop(ss->ss_family, &s->sin_addr, addr, sizeof(addr));
+ port = ntohs(s->sin_port);
+ } else {
+ struct sockaddr_in6 *s = (struct sockaddr_in6 *)ss;
+ inet_ntop(ss->ss_family, &s->sin6_addr, addr, sizeof(addr));
+ port = ntohs(s->sin6_port);
+ }
+
+ // Free previous string if any.
+ free(*dst);
+ *dst = NULL;
+
+ // Write formated information string.
+ int ret = snprintf(buf, sizeof(buf), "%s#%u(%s)", addr, port,
+ get_sockname(socktype));
+ if (ret > 0) {
+ *dst = strdup(buf);
+ } else {
+ *dst = strdup("NULL");
+ }
+}
+
+int net_init(const server_t *local,
+ const server_t *remote,
+ const int iptype,
+ const int socktype,
+ const int wait,
+ net_t *net)
+{
+ if (remote == NULL || net == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Clean network structure.
+ memset(net, 0, sizeof(*net));
+
+ // Get remote address list.
+ if (get_addr(remote, iptype, socktype, &net->remote_info) != 0) {
+ return KNOT_NET_EADDR;
+ }
+
+ // Set current remote address.
+ net->srv = net->remote_info;
+
+ // Get local address if specified.
+ if (local != NULL) {
+ if (get_addr(local, iptype, socktype, &net->local_info) != 0) {
+ return KNOT_NET_EADDR;
+ }
+ }
+
+ // Store network parameters.
+ net->iptype = iptype;
+ net->socktype = socktype;
+ net->wait = wait;
+ net->local = local;
+ net->remote = remote;
+
+ return KNOT_EOK;
+}
+
+int net_connect(net_t *net)
+{
+ struct pollfd pfd;
+ int sockfd, cs, err = 0;
+ socklen_t err_len = sizeof(err);
+
+ if (net == NULL || net->srv == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Set remote information string.
+ get_addr_str((struct sockaddr_storage *)net->srv->ai_addr,
+ net->socktype, &net->remote_str);
+
+ // Create socket.
+ sockfd = socket(net->srv->ai_family, net->socktype, 0);
+ if (sockfd == -1) {
+ WARN("can't create socket for %s\n", net->remote_str);
+ return KNOT_NET_ESOCKET;
+ }
+
+ // Initialize poll descriptor structure.
+ pfd.fd = sockfd;
+ pfd.events = POLLOUT;
+ pfd.revents = 0;
+
+ // Set non-blocking socket.
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == -1) {
+ WARN("can't set non-blocking socket for %s\n", net->remote_str);
+ return KNOT_NET_ESOCKET;
+ }
+
+ // Bind address to socket if specified.
+ if (net->local_info != NULL) {
+ // Set local information string.
+ get_addr_str((struct sockaddr_storage *)net->local_info->ai_addr,
+ net->socktype, &net->local_str);
+
+ if (bind(sockfd, net->local_info->ai_addr,
+ net->local_info->ai_addrlen) == -1) {
+ WARN("can't assign address %s\n", net->local_str);
+ return KNOT_NET_ESOCKET;
+ }
+ }
+
+ if (net->socktype == SOCK_STREAM) {
+ // Connect using socket.
+ if (connect(sockfd, net->srv->ai_addr, net->srv->ai_addrlen)
+ == -1 && errno != EINPROGRESS) {
+ WARN("can't connect to %s\n", net->remote_str);
+ close(sockfd);
+ return KNOT_NET_ECONNECT;
+ }
+
+ // Check for connection timeout.
+ if (poll(&pfd, 1, 1000 * net->wait) != 1) {
+ WARN("connection timeout for %s\n", net->remote_str);
+ close(sockfd);
+ return KNOT_NET_ECONNECT;
+ }
+
+ // Check if NB socket is writeable.
+ cs = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &err_len);
+ if (cs < 0 || err != 0) {
+ WARN("can't connect to %s\n", net->remote_str);
+ close(sockfd);
+ return KNOT_NET_ECONNECT;
+ }
+ }
+
+ // Store socket descriptor.
+ net->sockfd = sockfd;
+
+ return KNOT_EOK;
+}
+
+int net_send(const net_t *net, const uint8_t *buf, const size_t buf_len)
+{
+ if (net == NULL || buf == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ if (net->socktype == SOCK_STREAM) {
+ struct iovec iov[2];
+
+ // Leading packet length bytes.
+ uint16_t pktsize = htons(buf_len);
+
+ iov[0].iov_base = &pktsize;
+ iov[0].iov_len = sizeof(pktsize);
+ iov[1].iov_base = (uint8_t *)buf;
+ iov[1].iov_len = buf_len;
+
+ // Compute packet total length.
+ ssize_t total = iov[0].iov_len + iov[1].iov_len;
+
+ // Send data.
+ if (writev(net->sockfd, iov, 2) != total) {
+ WARN("can't send query to %s\n", net->remote_str);
+ return KNOT_NET_ESEND;
+ }
+ } else {
+ // Send data.
+ if (sendto(net->sockfd, buf, buf_len, 0, net->srv->ai_addr,
+ net->srv->ai_addrlen) != (ssize_t)buf_len) {
+ WARN("can't send query to %s\n", net->remote_str);
+ return KNOT_NET_ESEND;
+ }
+ }
+
+ return KNOT_EOK;
+}
+
+int net_receive(const net_t *net, uint8_t *buf, const size_t buf_len)
+{
+ ssize_t ret;
+ struct pollfd pfd;
+
+ if (net == NULL || buf == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Initialize poll descriptor structure.
+ pfd.fd = net->sockfd;
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ if (net->socktype == SOCK_STREAM) {
+ uint16_t msg_len;
+ uint32_t total = 0;
+
+ // Receive TCP message header.
+ while (total < sizeof(msg_len)) {
+ if (poll(&pfd, 1, 1000 * net->wait) != 1) {
+ WARN("response timeout for %s\n",
+ net->remote_str);
+ return KNOT_NET_ETIMEOUT;
+ }
+
+ // Receive piece of message.
+ ret = recv(net->sockfd, (uint8_t *)&msg_len + total,
+ sizeof(msg_len) - total, 0);
+ if (ret <= 0) {
+ WARN("can't receive reply from %s\n",
+ net->remote_str);
+ return KNOT_NET_ERECV;
+ }
+
+ total += ret;
+ }
+
+ // Convert number to host format.
+ msg_len = ntohs(msg_len);
+
+ total = 0;
+
+ // Receive whole answer message by parts.
+ while (total < msg_len) {
+ if (poll(&pfd, 1, 1000 * net->wait) != 1) {
+ WARN("response timeout for %s\n",
+ net->remote_str);
+ return KNOT_NET_ETIMEOUT;
+ }
+
+ // Receive piece of message.
+ ret = recv(net->sockfd, buf + total, msg_len - total, 0);
+ if (ret <= 0) {
+ WARN("can't receive reply from %s\n",
+ net->remote_str);
+ return KNOT_NET_ERECV;
+ }
+
+ total += ret;
+ }
+
+ return total;
+ } else {
+ struct sockaddr_storage from;
+
+ // Receive replies unless correct reply or timeout.
+ while (true) {
+ socklen_t from_len = sizeof(from);
+
+ // Wait for datagram data.
+ if (poll(&pfd, 1, 1000 * net->wait) != 1) {
+ WARN("response timeout for %s\n",
+ net->remote_str);
+ return KNOT_NET_ETIMEOUT;
+ }
+
+ // Receive whole UDP datagram.
+ ret = recvfrom(net->sockfd, buf, buf_len, 0,
+ (struct sockaddr *)&from, &from_len);
+ if (ret <= 0) {
+ WARN("can't receive reply from %s\n",
+ net->remote_str);
+ return KNOT_NET_ERECV;
+ }
+
+ // Compare reply address with the remote one.
+ if (from_len > sizeof(from) ||
+ memcmp(&from, net->srv->ai_addr, from_len) != 0) {
+ char *src = NULL;
+ get_addr_str(&from, net->socktype, &src);
+ WARN("unexpected reply source %s\n", src);
+ free(src);
+ continue;
+ }
+
+ return ret;
+ }
+ }
+
+ return KNOT_NET_ERECV;
+}
+
+void net_close(net_t *net)
+{
+ if (net == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ close(net->sockfd);
+ net->sockfd = -1;
+}
+
+void net_clean(net_t *net)
+{
+ if (net == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ free(net->local_str);
+ free(net->remote_str);
+
+ if (net->local_info != NULL) {
+ freeaddrinfo(net->local_info);
+ }
+
+ if (net->remote_info != NULL) {
+ freeaddrinfo(net->remote_info);
+ }
+}
diff --git a/src/utils/common/netio.h b/src/utils/common/netio.h
new file mode 100644
index 0000000..ac0e98d
--- /dev/null
+++ b/src/utils/common/netio.h
@@ -0,0 +1,198 @@
+/* Copyright (C) 2011 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 netio.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Networking abstraction for utilities.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _UTILS__NETIO_H_
+#define _UTILS__NETIO_H_
+
+#include <stdint.h> // uint_t
+#include <netdb.h> // addrinfo
+
+#include "common/lists.h" // node
+#include "utils/common/params.h" // params_t
+
+/*! \brief Structure containing server information. */
+typedef struct {
+ /*! List node (for list container). */
+ node n;
+ /*! Name or address of the server. */
+ char *name;
+ /*! Name or number of the service. */
+ char *service;
+} server_t;
+
+typedef struct {
+ /*! Socket descriptor. */
+ int sockfd;
+
+ /*! IP protocol type. */
+ int iptype;
+ /*! Socket type. */
+ int socktype;
+ /*! Timeout for all network operations. */
+ int wait;
+
+ /*! Local interface parameters. */
+ const server_t *local;
+ /*! Remote server parameters. */
+ const server_t *remote;
+
+ /*! Local description string (used for logging). */
+ char *local_str;
+ /*! Remote description string (used for logging). */
+ char *remote_str;
+
+ /*! Output from getaddrinfo for remote server. If the server is
+ * specified using domain name, this structure may contain more
+ * results.
+ */
+ struct addrinfo *remote_info;
+ /*! Currently used result from remote_info. */
+ struct addrinfo *srv;
+ /*! Output from getaddrinfo for local address. Only first result is
+ * used.
+ */
+ struct addrinfo *local_info;
+} net_t;
+
+/*!
+ * \brief Creates and fills server structure.
+ *
+ * \param name Address or host name.
+ * \param service Port number or service name.
+ *
+ * \retval server if success.
+ * \retval NULL if error.
+ */
+server_t* server_create(const char *name, const char *service);
+
+/*!
+ * \brief Destroys server structure.
+ *
+ * \param server Server structure to destroy.
+ */
+void server_free(server_t *server);
+
+/*!
+ * \brief Translates enum IP version type to int version.
+ *
+ * \param ip IP version to convert.
+ *
+ * \retval AF_INET, AF_INET6 or AF_UNSPEC.
+ */
+int get_iptype(const ip_t ip);
+
+/*!
+ * \brief Translates enum IP protocol type to int version in context to the
+ * current DNS query type.
+ *
+ * \param proto IP protocol type to convert.
+ * \param type DNS query type number.
+ *
+ * \retval SOCK_STREAM or SOCK_DGRAM.
+ */
+int get_socktype(const protocol_t proto, const uint16_t type);
+
+/*!
+ * \brief Translates int socket type to the common string one.
+ *
+ * \param socktype Socket type (SOCK_STREAM or SOCK_DGRAM).
+ *
+ * \retval "TCP" or "UDP".
+ */
+const char* get_sockname(const int socktype);
+
+/*!
+ * \brief Initializes network structure and resolves local and remote addresses.
+ *
+ * \param local Local address and service description.
+ * \param remote Remote address and service description.
+ * \param iptype IP version.
+ * \param socktype Socket type.
+ * \param wait Network timeout interval.
+ * \param net Network structure to initialize.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval errcode if error.
+ */
+int net_init(const server_t *local,
+ const server_t *remote,
+ const int iptype,
+ const int socktype,
+ const int wait,
+ net_t *net);
+
+/*!
+ * \brief Creates socket and connects (if TCP) to remote address specified
+ * by net->srv.
+ *
+ * \param net Connection parameters.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval errcode if error.
+ */
+int net_connect(net_t *net);
+
+/*!
+ * \brief Sends data to connected remote server.
+ *
+ * \param net Connection parameters.
+ * \param buf Data to send.
+ * \param buf_len Length of the data to send.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval errcode if error.
+ */
+int net_send(const net_t *net, const uint8_t *buf, const size_t buf_len);
+
+/*!
+ * \brief Receives data from connected remote server.
+ *
+ * \param net Connection parameters.
+ * \param buf Buffer for incomming data.
+ * \param buf_len Length of the buffer.
+ *
+ * \retval >=0 length of successfully received data.
+ * \retval errcode if error.
+ */
+int net_receive(const net_t *net, uint8_t *buf, const size_t buf_len);
+
+/*!
+ * \brief Closes current network connection.
+ *
+ * \param net Connection parameters.
+ */
+void net_close(net_t *net);
+
+/*!
+ * \brief Cleans up network structure.
+ *
+ * \param net Connection parameters.
+ */
+void net_clean(net_t *net);
+
+#endif // _UTILS__NETIO_H_
+
+/*! @} */
diff --git a/src/utils/common/params.c b/src/utils/common/params.c
new file mode 100644
index 0000000..56dc662
--- /dev/null
+++ b/src/utils/common/params.c
@@ -0,0 +1,376 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/common/params.h"
+
+#include <stdio.h>
+#include <stdlib.h> // free
+#include <netinet/in.h> // in_addr
+#include <arpa/inet.h> // inet_pton
+#include <sys/socket.h> // AF_INET (BSD)
+
+#include "libknot/libknot.h"
+#include "common/errcode.h" // KNOT_EOK
+#include "common/mempattern.h" // strcdup
+#include "common/descriptor.h" // KNOT_RRTYPE_
+#include "utils/common/msg.h" // WARN
+#include "utils/common/resolv.h" // parse_nameserver
+#include "utils/common/token.h" // token
+
+#define IPV4_REVERSE_DOMAIN "in-addr.arpa."
+#define IPV6_REVERSE_DOMAIN "ip6.arpa."
+
+char* get_reverse_name(const char *name)
+{
+ struct in_addr addr4;
+ struct in6_addr addr6;
+ int ret;
+ char buf[128] = "\0";
+
+ if (name == NULL) {
+ DBG_NULL;
+ return NULL;
+ }
+
+ // Check name for IPv4 address, IPv6 address or other.
+ if (inet_pton(AF_INET, name, &addr4) == 1) {
+ uint32_t num = ntohl(addr4.s_addr);
+
+ // Create IPv4 reverse FQD name.
+ ret = snprintf(buf, sizeof(buf), "%u.%u.%u.%u.%s",
+ (num >> 0) & 0xFF, (num >> 8) & 0xFF,
+ (num >> 16) & 0xFF, (num >> 24) & 0xFF,
+ IPV4_REVERSE_DOMAIN);
+ if (ret < 0 || (size_t)ret >= sizeof(buf)) {
+ return NULL;
+ }
+
+ return strdup(buf);
+ } else if (inet_pton(AF_INET6, name, &addr6) == 1) {
+ char *pos = buf;
+ size_t len = sizeof(buf);
+ uint8_t left, right;
+
+ // Create IPv6 reverse name.
+ for (int i = 15; i >= 0; i--) {
+ left = ((addr6.s6_addr)[i] & 0xF0) >> 4;
+ right = (addr6.s6_addr)[i] & 0x0F;
+
+ ret = snprintf(pos, len, "%x.%x.", right, left);
+ if (ret < 0 || (size_t)ret >= len) {
+ return NULL;
+ }
+
+ pos += ret;
+ len -= ret;
+ }
+
+ // Add IPv6 reverse domain.
+ ret = snprintf(pos, len, "%s", IPV6_REVERSE_DOMAIN);
+ if (ret < 0 || (size_t)ret >= len) {
+ return NULL;
+ }
+
+ return strdup(buf);
+ } else {
+ return NULL;
+ }
+}
+
+char* get_fqd_name(const char *name)
+{
+ char *fqd_name = NULL;
+
+ if (name == NULL) {
+ DBG_NULL;
+ return NULL;
+ }
+
+ size_t name_len = strlen(name);
+
+ // If the name is FQDN, make a copy.
+ if (name[name_len - 1] == '.') {
+ fqd_name = strdup(name);
+ // Else make a copy and append a trailing dot.
+ } else {
+ fqd_name = malloc(name_len + 2);
+ if (fqd_name != NULL) {
+ strncpy(fqd_name, name, name_len + 2);
+ fqd_name[name_len] = '.';
+ fqd_name[name_len + 1] = 0;
+ }
+ }
+
+ return fqd_name;
+}
+
+int params_parse_class(const char *value, uint16_t *rclass)
+{
+ if (value == NULL || rclass == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ if (knot_rrclass_from_string(value, rclass) == 0) {
+ return KNOT_EOK;
+ } else {
+ return KNOT_EINVAL;
+ }
+}
+
+int params_parse_type(const char *value, uint16_t *rtype, uint32_t *xfr_serial)
+{
+ if (value == NULL || rtype == NULL || xfr_serial == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ size_t param_pos = strcspn(value, "=");
+
+ // There is no additional parameter.
+ if (param_pos == strlen(value)) {
+ if (knot_rrtype_from_string(value, rtype) != 0) {
+ return KNOT_EINVAL;
+ }
+
+ // IXFR requires serial parameter.
+ if (*rtype == KNOT_RRTYPE_IXFR) {
+ DBG("SOA serial is required for IXFR query\n");
+ return KNOT_EINVAL;
+ }
+ } else {
+ char *type_char = strndup(value, param_pos);
+
+ if (knot_rrtype_from_string(type_char, rtype) != 0) {
+ free(type_char);
+ return KNOT_EINVAL;
+ }
+
+ free(type_char);
+
+ // Additional parameter is accepted for IXFR only.
+ if (*rtype == KNOT_RRTYPE_IXFR) {
+ const char *param_str = value + 1 + param_pos;
+ char *end;
+
+ // Convert string to serial.
+ unsigned long serial = strtoul(param_str, &end, 10);
+
+ // Check for bad serial string.
+ if (end == param_str || *end != '\0' ||
+ serial > UINT32_MAX) {
+ DBG("bad SOA serial %s\n", param_str);
+ return KNOT_EINVAL;
+ }
+
+ *xfr_serial = serial;
+ } else {
+ char buf[64] = "";
+ knot_rrtype_to_string(*rtype, buf, sizeof(buf));
+ DBG("type %s can't have a parameter\n", buf);
+ return KNOT_EINVAL;
+ }
+ }
+
+ return KNOT_EOK;
+}
+
+int params_parse_server(const char *value, list *servers, const char *def_port)
+{
+ if (value == NULL || servers == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Add specified nameserver.
+ server_t *server = parse_nameserver(value, def_port);
+ if (server == NULL) {
+ ERR("bad nameserver %s\n", value);
+ return KNOT_EINVAL;
+ }
+ add_tail(servers, (node *)server);
+
+ return KNOT_EOK;
+}
+
+int params_parse_wait(const char *value, int32_t *dst)
+{
+ char *end;
+
+ if (value == NULL || dst == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ /* Convert string to number. */
+ long num = strtol(value, &end, 10);
+
+ /* Check for bad string (empty or incorrect). */
+ if (end == value || *end != '\0') {
+ ERR("bad time value %s\n", value);
+ return KNOT_EINVAL;
+ } else if (num < 1) {
+ num = 1;
+ WARN("time %s is too short, using %ld instead\n", value, num);
+ /* Reduce maximal value. Poll takes signed int in milliseconds. */
+ } else if (num > INT32_MAX) {
+ num = INT32_MAX / 1000;
+ WARN("time %s is too big, using %ld instead\n", value, num);
+ }
+
+ *dst = num;
+
+ return KNOT_EOK;
+}
+
+int params_parse_num(const char *value, uint32_t *dst)
+{
+ char *end;
+
+ if (value == NULL || dst == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Convert string to number.
+ unsigned long num = strtoul(value, &end, 10);
+
+ // Check for bad string.
+ if (end == value || *end != '\0') {
+ ERR("bad number %s\n", value);
+ return KNOT_EINVAL;
+ }
+
+ if (num > UINT32_MAX) {
+ num = UINT32_MAX;
+ WARN("number %s is too big, using %lu instead\n", value, num);
+ }
+
+ *dst = num;
+
+ return KNOT_EOK;
+}
+
+int params_parse_bufsize(const char *value, int32_t *dst)
+{
+ char *end;
+
+ if (value == NULL || dst == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Convert string to number.
+ unsigned long num = strtoul(value, &end, 10);
+
+ // Check for bad string.
+ if (end == value || *end != '\0') {
+ ERR("bad size %s\n", value);
+ return KNOT_EINVAL;
+ }
+
+ if (num > UINT16_MAX) {
+ num = UINT16_MAX;
+ WARN("size %s is too big, using %lu instead\n", value, num);
+ }
+
+ *dst = num;
+
+ return KNOT_EOK;
+}
+
+int params_parse_tsig(const char *value, knot_key_params_t *key_params)
+{
+ if (value == NULL || key_params == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ /* Invalidate previous key. */
+ if (key_params->name) {
+ ERR("Key specified multiple times.\n");
+ return KNOT_EINVAL;
+ }
+
+ char *h = strdup(value);
+ if (!h) {
+ return KNOT_ENOMEM;
+ }
+
+ /* Separate to avoid multiple allocs. */
+ char *k = NULL, *s = NULL;
+ if ((k = (char*)strchr(h, ':'))) { /* Second part - NAME|SECRET */
+ *k++ = '\0'; /* String separator */
+ s = (char*)strchr(k, ':'); /* Thirt part - |SECRET */
+ }
+
+ /* Determine algorithm. */
+ key_params->algorithm = KNOT_TSIG_ALG_HMAC_MD5;
+ if (s) {
+ *s++ = '\0'; /* Last part separator */
+ knot_lookup_table_t *alg = NULL;
+ alg = knot_lookup_by_name(knot_tsig_alg_names, h);
+ if (alg) {
+ DBG("%s: parsed algorithm '%s'\n", __func__, h);
+ key_params->algorithm = alg->id;
+ } else {
+ ERR("invalid TSIG algorithm name '%s'\n", h);
+ free(h);
+ return KNOT_EINVAL;
+ }
+ } else {
+ s = k; /* Ignore first part, push down. */
+ k = h;
+ }
+
+ if (!s) {
+ ERR("invalid key option format, use [hmac:]keyname:secret\n");
+ free(h);
+ return KNOT_EINVAL;
+ }
+
+ /* Set key name and secret. */
+ key_params->name = knot_dname_new_from_nonfqdn_str(k, strlen(k), NULL);
+ key_params->secret = strdup(s);
+
+ DBG("%s: parsed name '%s'\n", __func__, k);
+ DBG("%s: parsed secret '%s'\n", __func__, s);
+ free(h);
+
+ return KNOT_EOK;
+}
+
+int params_parse_keyfile(const char *value, knot_key_params_t *key_params)
+{
+ if (value == NULL || key_params == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ if (key_params->name) {
+ ERR("Key specified multiple times.\n");
+ return KNOT_EINVAL;
+ }
+
+ int result = knot_load_key_params(value, key_params);
+ if (result != KNOT_EOK) {
+ ERR("could not read key file: %s\n", knot_strerror(result));
+ return KNOT_EINVAL;
+ }
+
+ return KNOT_EOK;
+}
diff --git a/src/utils/common/params.h b/src/utils/common/params.h
new file mode 100644
index 0000000..05539ad
--- /dev/null
+++ b/src/utils/common/params.h
@@ -0,0 +1,119 @@
+/* Copyright (C) 2011 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 host_params.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Common utils parameters processing.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _UTILS__PARAMS_H_
+#define _UTILS__PARAMS_H_
+
+#include <stdint.h> // uint16_t
+#include <stdbool.h> // bool
+
+#include "libknot/libknot.h"
+#include "common/lists.h" // list
+
+#define DEFAULT_IPV4_NAME "127.0.0.1"
+#define DEFAULT_IPV6_NAME "::1"
+#define DEFAULT_DNS_PORT "53"
+#define DEFAULT_UDP_SIZE 512
+#define DEFAULT_EDNS_SIZE 4096
+#define MAX_PACKET_SIZE 65535
+
+#define SEP_CHARS "\n\t "
+
+/*! \brief Variants of IP protocol. */
+typedef enum {
+ IP_ALL,
+ IP_4,
+ IP_6
+} ip_t;
+
+/*! \brief Variants of transport protocol. */
+typedef enum {
+ PROTO_ALL,
+ PROTO_TCP,
+ PROTO_UDP
+} protocol_t;
+
+/*! \brief Variants of output type. */
+typedef enum {
+ /*!< Verbose output (same for host and dig). */
+ FORMAT_FULL,
+ /*!< Short dig output. */
+ FORMAT_DIG,
+ /*!< Brief host output. */
+ FORMAT_HOST,
+ /*!< Brief nsupdate output. */
+ FORMAT_NSUPDATE
+} format_t;
+
+/*! \brief Text output settings. */
+typedef struct {
+ /*!< Output format. */
+ format_t format;
+
+ /*!< Style of rrset dump. */
+ knot_dump_style_t style;
+
+ /*!< Show query packet. */
+ bool show_query;
+ /*!< Show header info. */
+ bool show_header;
+ /*!< Show EDNS info. */
+ bool show_edns;
+ /*!< Show QUERY/ZONE section. */
+ bool show_question;
+ /*!< Show ANSWER/PREREQ section. */
+ bool show_answer;
+ /*!< Show UPDATE/AUTHORITY section. */
+ bool show_authority;
+ /*!< Show ADDITIONAL section. */
+ bool show_additional;
+ /*!< Show footer info. */
+ bool show_footer;
+} style_t;
+
+char* get_reverse_name(const char *name);
+
+char* get_fqd_name(const char *name);
+
+int params_parse_class(const char *value, uint16_t *rclass);
+
+int params_parse_type(const char *value, uint16_t *rtype, uint32_t *xfr_serial);
+
+int params_parse_server(const char *value, list *servers, const char *def_port);
+
+int params_parse_wait(const char *value, int32_t *dst);
+
+int params_parse_num(const char *value, uint32_t *dst);
+
+int params_parse_bufsize(const char *value, int32_t *dst);
+
+int params_parse_tsig(const char *value, knot_key_params_t *key_params);
+
+int params_parse_keyfile(const char *value, knot_key_params_t *key_params);
+
+#endif // _UTILS__PARAMS_H_
+
+/*! @} */
diff --git a/src/utils/common/resolv.c b/src/utils/common/resolv.c
new file mode 100644
index 0000000..864a2a9
--- /dev/null
+++ b/src/utils/common/resolv.c
@@ -0,0 +1,193 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/common/resolv.h"
+
+#include <stdio.h> // fopen
+#include <stdlib.h> // free
+
+#include "common/lists.h" // list
+#include "common/errcode.h" // KNOT_ENOENT
+#include "utils/common/msg.h" // DBG_NULL
+#include "utils/common/params.h" // DEFAULT_IPV6_NAME
+
+#define RESOLV_FILE "/etc/resolv.conf"
+
+server_t* parse_nameserver(const char *nameserver, const char *def_port)
+{
+ if (nameserver == NULL || def_port == NULL) {
+ DBG_NULL;
+ return NULL;
+ }
+
+ // OpenBSD notation: nameserver [address]:port
+ if (nameserver[0] == '[') {
+ char *addr, *port;
+
+ char *start = (char *)nameserver + 1;
+ char *end = index(nameserver, ']');
+ size_t addr_len = end - start;
+
+ // Missing closing bracket -> stop processing.
+ if (end == NULL) {
+ return NULL;
+ }
+
+ // Fill enclosed address.
+ addr = strndup(start, addr_len);
+
+ // Find possible port.
+ start += addr_len + 1;
+ if (strlen(start) > 0) {
+ // Check for colon separation.
+ if (*start != ':') {
+ free(addr);
+ return NULL;
+ }
+
+ size_t port_len = strlen(++start);
+
+ // Check port string length.
+ if (port_len == 0 || port_len >= sizeof(port)) {
+ free(addr);
+ return NULL;
+ }
+
+ // Fill port part.
+ port = strdup(start);
+ } else {
+ port = strdup(def_port);
+ }
+
+ // Create server structure.
+ server_t *server = server_create(addr, port);
+
+ free(addr);
+ free(port);
+
+ return server;
+ } else {
+ return server_create(nameserver, def_port);
+ }
+}
+
+static int get_resolv_nameservers(list *servers, const char *def_port)
+{
+ char line[512];
+
+ // Open config file.
+ FILE *f = fopen(RESOLV_FILE, "r");
+
+ // Check correct open.
+ if (f == NULL) {
+ return KNOT_ENOENT;
+ }
+
+ // Read lines from config file.
+ while (fgets(line, sizeof(line), f) != NULL) {
+ size_t len;
+ char *pos = line;
+ char *option, *value;
+
+ // Find leading white characters.
+ len = strspn(pos, SEP_CHARS);
+ pos += len;
+
+ // Start of the first token.
+ option = pos;
+
+ // Find length of the token.
+ len = strcspn(pos, SEP_CHARS);
+ pos += len;
+
+ // Check if the token is not empty.
+ if (len <= 0) {
+ continue;
+ }
+
+ // Find separating white characters.
+ len = strspn(pos, SEP_CHARS);
+ pos += len;
+
+ // Check if there is a separation between tokens.
+ if (len <= 0) {
+ continue;
+ }
+
+ // Copy of the second token.
+ value = strndup(pos, strcspn(pos, SEP_CHARS));
+
+ // Process value with respect to option name.
+ if (strncmp(option, "nameserver", strlen("nameserver")) == 0) {
+ server_t *server;
+
+ server = parse_nameserver(value, def_port);
+
+ // If value is correct, add nameserver to the list.
+ if (server != NULL) {
+ add_tail(servers, (node *)server);
+ }
+ }
+
+ // Drop value string.
+ free(value);
+ }
+
+ // Close config file.
+ fclose(f);
+
+ // Return number of servers.
+ return list_size(servers);
+}
+
+int get_nameservers(list *servers, const char *def_port)
+{
+ if (servers == NULL || def_port == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Initialize list of servers.
+ init_list(servers);
+
+ // Read nameservers from resolv file.
+ int ret = get_resolv_nameservers(servers, def_port);
+
+ // If found nameservers or error.
+ if (ret != 0) {
+ return ret;
+ // If no nameservers.
+ } else {
+ server_t *server;
+
+ // Add default ipv6 nameservers.
+ server = server_create(DEFAULT_IPV6_NAME, def_port);
+
+ if (server != NULL) {
+ add_tail(servers, (node *)server);
+ }
+
+ // Add default ipv4 nameservers.
+ server = server_create(DEFAULT_IPV4_NAME, def_port);
+
+ if (server != NULL) {
+ add_tail(servers, (node *)server);
+ }
+
+ return list_size(servers);
+ }
+}
diff --git a/src/tests/libknot/libknot/edns_tests.h b/src/utils/common/resolv.h
index 4553234..8a240df 100644
--- a/src/tests/libknot/libknot/edns_tests.h
+++ b/src/utils/common/resolv.h
@@ -14,21 +14,26 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
- * \file edns_tests.h
+ * \file resolv.h
*
- * \author Jan Kadlec <jan.kadlec@nic.cz>
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
*
- * Contains unit tests for ENDS API
+ * \brief resolv.conf processing.
*
- * Contains tests for:
- * - ENDS API
+ * \addtogroup knot_utils
+ * @{
*/
-#ifndef _KNOTD__EDNS_TESTS_H_
-#define _KNOTD__EDNS_TESTS_H_
-#include "common/libtap/tap_unit.h"
+#ifndef _UTILS__RESOLV_H_
+#define _UTILS__RESOLV_H_
-/* Unit API. */
-unit_api edns_tests_api;
+#include "common/lists.h" // list
+#include "utils/common/netio.h" // server_t
-#endif /* _KNOTD__EDNS_TESTS_H_ */
+server_t* parse_nameserver(const char *nameserver, const char *def_port);
+
+int get_nameservers(list *servers, const char *def_port);
+
+#endif // _UTILS__RESOLV_H_
+
+/*! @} */
diff --git a/src/utils/common/token.c b/src/utils/common/token.c
new file mode 100644
index 0000000..457a7c0
--- /dev/null
+++ b/src/utils/common/token.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/common/token.h"
+
+#include <stdio.h>
+#include <stdlib.h> // free
+#include <ctype.h> // isspace
+#include <string.h> // memcmp
+
+#include "common/errcode.h" // KNOT_EOK
+#include "common/getline.h" // knot_getline
+#include "utils/common/msg.h" // ERR
+
+int tok_scan(const char* lp, const char **tbl, int *lpm)
+{
+ if (lp == NULL || tbl == NULL || *tbl == NULL || lpm == NULL) {
+ DBG_NULL;
+ return -1;
+ }
+
+ const char *prefix = lp; /* Ptr to line start. */
+ int i = 0, pl = 1; /* Match index, prefix length. */
+ unsigned char len = 0; /* Read length. */
+ for(;;) {
+ const char *tok = tbl[i];
+ if (*lp == '\0' || isspace((unsigned char)(*lp))) {
+ if (tok && TOK_L(tok) == len) { /* Consumed whole w? */
+ return i; /* Identifier */
+ } else { /* Word is shorter than cmd? */
+ break;
+ }
+ }
+
+ /* Find next prefix match. */
+ ++len;
+ while (tok) {
+ if (TOK_L(tok) >= len) { /* Is prefix of current token */
+ if (*lp < tok[pl]) { /* Terminate early. */
+ tok = NULL;
+ break; /* No match could be found. */
+ }
+ if (*lp == tok[pl]) { /* Match */
+ if(lpm) *lpm = i;
+ ++pl;
+ break;
+ }
+ }
+
+ /* No early cut, no match - seek next. */
+ while ((tok = tbl[++i]) != NULL) {
+ if (TOK_L(tok) >= len &&
+ memcmp(TOK_S(tok), prefix, len) == 0) {
+ break;
+ }
+ }
+ }
+
+ if (tok == NULL) {
+ break; /* All tokens exhausted. */
+ } else {
+ ++lp; /* Next char */
+ }
+ }
+
+ return -1;
+}
+
+int tok_find(const char *lp, const char **tbl)
+{
+ if (lp == NULL || tbl == NULL || *tbl == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ int lpm = -1;
+ int bp = 0;
+ if ((bp = tok_scan(lp, tbl, &lpm)) < 0) {
+ if (lpm > -1) {
+ ERR("unexpected literal: '%s', did you mean '%s' ?\n",
+ lp, TOK_S(tbl[lpm]));
+ } else {
+ ERR("unexpected literal: '%s'\n", lp);
+ }
+
+ return KNOT_EPARSEFAIL;
+ }
+
+ return bp;
+}
+
+const char* tok_skipspace(const char *lp)
+{
+ if (lp == NULL) {
+ DBG_NULL;
+ return NULL;
+ }
+
+ while (isspace((unsigned char)(*lp))) ++lp; return lp;
+}
+
+int tok_process_lines(FILE *fp, lparse_f cb, void *arg)
+{
+ if (fp == NULL || cb == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ int ret = KNOT_EOK;
+
+ /* Parse lines. */
+ char *buf = NULL;
+ size_t buflen = 0;
+ ssize_t rb = 0;
+ while ((rb = knot_getline(&buf, &buflen, fp)) != -1) {
+ ret = cb(buf, rb, arg);
+ if (ret != KNOT_EOK) break;
+ }
+
+ free(buf);
+ return ret;
+}
diff --git a/src/utils/common/token.h b/src/utils/common/token.h
new file mode 100644
index 0000000..a678092
--- /dev/null
+++ b/src/utils/common/token.h
@@ -0,0 +1,91 @@
+/* Copyright (C) 2011 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 token.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief String tokenizer and simple scanner.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _UTILS__TOKEN_H_
+#define _UTILS__TOKEN_H_
+
+#include <stdio.h>
+
+/*!
+ * \brief Example of token table:
+ *
+ * \warning Table _must_ be lexicographically ordered.
+ *
+ * const char *tok_tbl[] = {
+ * // LEN STRING
+ * "\x4" "abcd",
+ * "\x5" "class",
+ * NULL // END
+ * }
+ */
+/*! \brief String part of the token. */
+#define TOK_S(x) ((x)+1)
+/*! \brief Len of the token. */
+#define TOK_L(x) ((unsigned char)(x)[0])
+/*! \brief Function prototype for line parser. */
+typedef int(*lparse_f)(char *lp, int len, void *arg);
+
+/*!
+ * \brief Scan for matching token described by a match table.
+ *
+ * Table consists of strings, prefixed with 1B length.
+ *
+ * \param lp Pointer to current line.
+ * \param tbl Match description table.
+ * \param lpm Pointer to longest prefix match.
+ * \retval index to matching record.
+ * \retval -1 if no match is found, lpm may be set to longest prefix match.
+ */
+int tok_scan(const char* lp, const char **tbl, int *lpm);
+
+/*!
+ * \brief Find token from table in a line buffer.
+ * \param lp Pointer to current line.
+ * \param tbl Match description table.
+ * \retval index to matching record.
+ * \retval error code if no match is found
+ */
+int tok_find(const char *lp, const char **tbl);
+
+/*!
+ * \brief Return pointer to next non-blank character.
+ * \param lp Pointer to current line.
+ * \return ptr to next non-blank character.
+ */
+const char* tok_skipspace(const char *lp);
+
+/*!
+ * \brief Process file by lines.
+ * \param fp File handle to be processed.
+ * \param cb Callback function to be called for each line.
+ * \param arg Pointer to be passed to callback function.
+ * \return KNOT_EOK if success.
+ * \return error returned by @cb function
+ */
+int tok_process_lines(FILE *fp, lparse_f cb, void *arg);
+
+#endif // _UTILS__TOKEN_H_
+/*! @} */
diff --git a/src/utils/dig/dig_exec.c b/src/utils/dig/dig_exec.c
new file mode 100644
index 0000000..8a13e96
--- /dev/null
+++ b/src/utils/dig/dig_exec.c
@@ -0,0 +1,732 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/dig/dig_exec.h"
+
+#include <stdlib.h> // free
+#include <sys/time.h> // gettimeofday
+#include <sys/socket.h> // AF_INET
+#include <netinet/in.h> // sockaddr_in (BSD)
+
+#include "libknot/libknot.h"
+#include "common/lists.h" // list
+#include "common/print.h" // time_diff
+#include "common/errcode.h" // KNOT_EOK
+#include "common/descriptor.h" // KNOT_RRTYPE_
+#include "utils/common/msg.h" // WARN
+#include "utils/common/netio.h" // get_socktype
+#include "utils/common/exec.h" // print_packet
+
+static knot_packet_t* create_query_packet(const query_t *query,
+ uint8_t **data,
+ size_t *data_len)
+{
+ knot_question_t q;
+ knot_packet_t *packet;
+
+ // Set packet buffer size.
+ int max_size = query->udp_size;
+ if (max_size < 0) {
+ if (get_socktype(query->protocol, query->type_num)
+ == SOCK_STREAM) {
+ max_size = MAX_PACKET_SIZE;
+ } else if (query->flags.do_flag || query->nsid) {
+ max_size = DEFAULT_EDNS_SIZE;
+ } else {
+ max_size = DEFAULT_UDP_SIZE;
+ }
+ }
+
+ // Create packet skeleton.
+ packet = create_empty_packet(KNOT_PACKET_PREALLOC_NONE, max_size);
+ if (packet == NULL) {
+ return NULL;
+ }
+
+ // Set flags to wireformat.
+ if (query->flags.aa_flag == true) {
+ knot_wire_set_aa(packet->wireformat);
+ }
+ if (query->flags.tc_flag == true) {
+ knot_wire_set_tc(packet->wireformat);
+ }
+ if (query->flags.rd_flag == true) {
+ knot_wire_set_rd(packet->wireformat);
+ }
+ if (query->flags.ra_flag == true) {
+ knot_wire_set_ra(packet->wireformat);
+ }
+ if (query->flags.z_flag == true) {
+ knot_wire_set_z(packet->wireformat);
+ }
+ if (query->flags.ad_flag == true) {
+ knot_wire_set_ad(packet->wireformat);
+ }
+ if (query->flags.cd_flag == true) {
+ knot_wire_set_cd(packet->wireformat);
+ }
+
+ // Fill auxiliary question structure.
+ q.qclass = query->class_num;
+ q.qtype = query->type_num;
+ q.qname = knot_dname_new_from_str(query->owner, strlen(query->owner), 0);
+ if (q.qname == NULL) {
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ // Set packet question.
+ if (knot_query_set_question(packet, &q) != KNOT_EOK) {
+ // It's necessary to release q.qname by hand as it isn't
+ // connected with the packet yet.
+ knot_dname_release(q.qname);
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ // For IXFR query add authority section.
+ if (query->type_num == KNOT_RRTYPE_IXFR) {
+ // SOA rdata in wireformat.
+ uint8_t wire[22] = { 0x0 };
+ size_t pos = 0;
+ int ret;
+
+ // Create rrset with SOA record.
+ knot_rrset_t *soa = knot_rrset_new(q.qname,
+ KNOT_RRTYPE_SOA,
+ query->class_num,
+ 0);
+ if (soa == NULL) {
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ // Fill in blank SOA rdata to rrset.
+ ret = knot_rrset_rdata_from_wire_one(soa, wire, &pos,
+ sizeof(wire), sizeof(wire));
+ if (ret != KNOT_EOK) {
+ free(soa);
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ // Set SOA serial.
+ knot_rrset_rdata_soa_serial_set(soa, query->xfr_serial);
+
+ // Add authority section.
+ ret = knot_query_add_rrset_authority(packet, soa);
+ if (ret != KNOT_EOK) {
+ free(soa);
+ knot_packet_free(&packet);
+ return NULL;
+ }
+ }
+
+ // Create EDNS section if required.
+ if (query->udp_size > 0 || query->flags.do_flag || query->nsid) {
+ knot_opt_rr_t *opt_rr = knot_edns_new();
+ if (opt_rr == NULL) {
+ ERR("can't create EDNS section\n");
+ knot_edns_free(&opt_rr);
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ knot_edns_set_version(opt_rr, 0);
+ knot_edns_set_payload(opt_rr, max_size);
+
+ if (knot_response_add_opt(packet, opt_rr, 0, 0) != KNOT_EOK) {
+ ERR("can't set EDNS section\n");
+ knot_edns_free(&opt_rr);
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ // Set DO flag to EDNS section.
+ if (query->flags.do_flag) {
+ knot_edns_set_do(&packet->opt_rr);
+ }
+
+ if (query->nsid) {
+ if (knot_edns_add_option(&packet->opt_rr,
+ EDNS_OPTION_NSID,
+ 0, NULL) != KNOT_EOK) {
+ ERR("can't set NSID query\n");
+ knot_edns_free(&opt_rr);
+ knot_packet_free(&packet);
+ return NULL;
+ }
+ }
+
+ knot_edns_free(&opt_rr);
+ }
+
+ // Create wire query.
+ if (knot_packet_to_wire(packet, data, data_len) != KNOT_EOK) {
+ ERR("can't create wire query packet\n");
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ // Sign the packet if a key was specified.
+ if (query->key_params.name != NULL) {
+ int ret = sign_packet(packet, (sign_context_t *)&query->sign_ctx,
+ &query->key_params);
+ if (ret != KNOT_EOK) {
+ ERR("failed to sign query packet (%s)\n",
+ knot_strerror(ret));
+ knot_packet_free(&packet);
+ return NULL;
+ }
+
+ *data_len = packet->size;
+ }
+
+ return packet;
+}
+
+static bool check_reply_id(const knot_packet_t *reply,
+ const knot_packet_t *query)
+{
+ uint16_t query_id = knot_wire_get_id(query->wireformat);
+ uint16_t reply_id = knot_wire_get_id(reply->wireformat);
+
+ if (reply_id != query_id) {
+ WARN("reply ID (%u) is different from query ID (%u)\n",
+ reply_id, query_id);
+ return false;
+ }
+
+ return true;
+}
+
+static void check_reply_question(const knot_packet_t *reply,
+ const knot_packet_t *query)
+{
+ if (reply->header.qdcount < 1) {
+ WARN("response doesn't have question section\n");
+ return;
+ }
+
+ int name_diff = knot_dname_compare_cs(reply->question.qname,
+ query->question.qname);
+
+ if (reply->question.qclass != query->question.qclass ||
+ reply->question.qtype != query->question.qtype ||
+ name_diff != 0) {
+ WARN("query/response question sections are different\n");
+ return;
+ }
+}
+
+static int64_t first_serial_check(const knot_packet_t *reply)
+{
+ if (reply->header.ancount <= 0) {
+ return -1;
+ }
+
+ const knot_rrset_t *first = *(reply->answer);
+
+ if (first->type != KNOT_RRTYPE_SOA) {
+ return -1;
+ } else {
+ return knot_rrset_rdata_soa_serial(first);
+ }
+}
+
+static bool last_serial_check(const uint32_t serial, const knot_packet_t *reply)
+{
+ if (reply->header.ancount <= 0) {
+ return false;
+ }
+
+ const knot_rrset_t *last = *(reply->answer + reply->header.ancount - 1);
+
+ if (last->type != KNOT_RRTYPE_SOA) {
+ return false;
+ } else {
+ int64_t last_serial = knot_rrset_rdata_soa_serial(last);
+
+ if (last_serial == serial) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+static int process_query_packet(const knot_packet_t *query,
+ net_t *net,
+ const bool ignore_tc,
+ const sign_context_t *sign_ctx,
+ const knot_key_params_t *key_params,
+ const style_t *style)
+{
+ struct timeval t_start, t_query, t_end;
+ knot_packet_t *reply;
+ uint8_t in[MAX_PACKET_SIZE];
+ int in_len;
+ int ret;
+
+ // Get start query time.
+ gettimeofday(&t_start, NULL);
+
+ // Connect to the server.
+ ret = net_connect(net);
+ if (ret != KNOT_EOK) {
+ return -1;
+ }
+
+ // Send query packet.
+ ret = net_send(net, query->wireformat, query->size);
+ if (ret != KNOT_EOK) {
+ net_close(net);
+ return -1;
+ }
+
+ // Get stop query time and start reply time.
+ gettimeofday(&t_query, NULL);
+
+ // Print query packet if required.
+ if (style->show_query) {
+ print_packet(query, query->size, net,
+ time_diff(&t_start, &t_query),
+ false, style);
+ }
+
+ // Loop over incoming messages, unless reply id is correct or timeout.
+ while (true) {
+ // Receive a reply message.
+ in_len = net_receive(net, in, sizeof(in));
+ if (in_len <= 0) {
+ net_close(net);
+ return -1;
+ }
+
+ // Get stop reply time.
+ gettimeofday(&t_end, NULL);
+
+ // Create reply packet structure to fill up.
+ reply = knot_packet_new(KNOT_PACKET_PREALLOC_NONE);
+ if (reply == NULL) {
+ net_close(net);
+ return -1;
+ }
+
+ // Parse reply to the packet structure.
+ if (knot_packet_parse_from_wire(reply, in, in_len, 0,
+ KNOT_PACKET_DUPL_NO_MERGE)
+ != KNOT_EOK) {
+ ERR("malformed reply packet from %s\n", net->remote_str);
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+
+ // Compare reply header id.
+ if (check_reply_id(reply, query)) {
+ break;
+ // Check for timeout.
+ } else if (time_diff(&t_query, &t_end) > 1000 * net->wait) {
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+
+ knot_packet_free(&reply);
+ }
+
+ // Check for TC bit and repeat query with TCP if required.
+ if (knot_wire_get_tc(reply->wireformat) != 0 &&
+ ignore_tc == false && net->socktype == SOCK_DGRAM) {
+ WARN("truncated reply from %s, retrying over TCP\n",
+ net->remote_str);
+ knot_packet_free(&reply);
+ net_close(net);
+
+ net->socktype = SOCK_STREAM;
+
+ return process_query_packet(query, net, true, sign_ctx,
+ key_params, style);
+ }
+
+ // Check for question sections equality.
+ if (knot_wire_get_rcode(in) == KNOT_RCODE_NOERROR) {
+ check_reply_question(reply, query);
+ }
+
+ // Verify signature if a key was specified.
+ if (key_params->name != NULL) {
+ ret = verify_packet(reply, sign_ctx, key_params);
+ if (ret != KNOT_EOK) {
+ ERR("reply verification for %s (%s)\n",
+ net->remote_str, knot_strerror(ret));
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+ }
+
+ // Print reply packet.
+ print_packet(reply, in_len, net, time_diff(&t_query, &t_end),
+ true, style);
+
+ knot_packet_free(&reply);
+ net_close(net);
+
+ // Check for SERVFAIL.
+ if (knot_wire_get_rcode(in) == KNOT_RCODE_SERVFAIL) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void process_query(const query_t *query)
+{
+ node *server = NULL;
+ knot_packet_t *out_packet;
+ uint8_t *out = NULL;
+ size_t out_len = 0;
+ net_t net;
+ int ret;
+
+ if (query == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ // Create query packet.
+ out_packet = create_query_packet(query, &out, &out_len);
+ if (out_packet == NULL) {
+ ERR("can't create query packet\n");
+ return;
+ }
+
+ // Get connection parameters.
+ int iptype = get_iptype(query->ip);
+ int socktype = get_socktype(query->protocol, query->type_num);
+
+ // Loop over server list to process query.
+ WALK_LIST(server, query->servers) {
+ server_t *remote = (server_t *)server;
+
+ DBG("Quering for owner(%s), class(%u), type(%u), server(%s), "
+ "port(%s), protocol(%s)\n", query->owner, query->class_num,
+ query->type_num, remote->name, remote->service,
+ get_sockname(socktype));
+
+ // Loop over the number of retries.
+ for (size_t i = 0; i <= query->retries; i++) {
+ // Initialize network structure for current server.
+ ret = net_init(query->local, remote, iptype, socktype,
+ query->wait, &net);
+ if (ret != KNOT_EOK) {
+ continue;
+ }
+
+ // Loop over all resolved addresses for remote.
+ while (net.srv != NULL) {
+ ret = process_query_packet(out_packet, &net,
+ query->ignore_tc,
+ &query->sign_ctx,
+ &query->key_params,
+ &query->style);
+ // If error try next resolved address.
+ if (ret != 0) {
+ net.srv = (net.srv)->ai_next;
+ continue;
+ }
+
+ break;
+ }
+
+ // Success.
+ if (ret == 0) {
+ net_clean(&net);
+ knot_packet_free(&out_packet);
+ return;
+ // SERVFAIL.
+ } else if (ret == 1 && query->servfail_stop == true) {
+ net_clean(&net);
+ knot_packet_free(&out_packet);
+ return;
+ }
+
+ if (i < query->retries) {
+ DBG("retrying server %s#%s(%s)\n",
+ remote->name, remote->service,
+ get_sockname(socktype));
+ }
+
+ net_clean(&net);
+ }
+
+ WARN("failed to query server %s#%s(%s)\n",
+ remote->name, remote->service, get_sockname(socktype));
+ }
+
+ knot_packet_free(&out_packet);
+}
+
+static int process_packet_xfr(const knot_packet_t *query,
+ net_t *net,
+ const sign_context_t *sign_ctx,
+ const knot_key_params_t *key_params,
+ const style_t *style)
+{
+ struct timeval t_start, t_query, t_end;
+ knot_packet_t *reply;
+ uint8_t in[MAX_PACKET_SIZE];
+ int in_len;
+ int ret;
+ int64_t serial = 0;
+ size_t total_len = 0;
+ size_t msg_count = 0;
+ size_t rr_count = 0;
+
+ // Get start query time.
+ gettimeofday(&t_start, NULL);
+
+ // Connect to the server.
+ ret = net_connect(net);
+ if (ret != KNOT_EOK) {
+ return -1;
+ }
+
+ // Send query packet.
+ ret = net_send(net, query->wireformat, query->size);
+ if (ret != KNOT_EOK) {
+ net_close(net);
+ return -1;
+ }
+
+ // Get stop query time and start reply time.
+ gettimeofday(&t_query, NULL);
+
+
+ // Print query packet if required.
+ if (style->show_query) {
+ print_packet(query, query->size, net,
+ time_diff(&t_start, &t_query),
+ false, style);
+ }
+
+ // Print leading transfer information.
+ print_header_xfr(&query->question, style);
+
+ // Loop over reply messages unless first and last SOA serials differ.
+ while (true) {
+ // Receive a reply message.
+ in_len = net_receive(net, in, sizeof(in));
+ if (in_len <= 0) {
+ net_close(net);
+ return -1;
+ }
+
+ // Create reply packet structure to fill up.
+ reply = knot_packet_new(KNOT_PACKET_PREALLOC_NONE);
+ if (reply == NULL) {
+ net_close(net);
+ return -1;
+ }
+
+ // Parse reply to the packet structure.
+ if (knot_packet_parse_from_wire(reply, in, in_len, 0,
+ KNOT_PACKET_DUPL_NO_MERGE)
+ != KNOT_EOK) {
+ ERR("malformed reply packet from %s\n", net->remote_str);
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+
+ // Compare reply header id.
+ if (check_reply_id(reply, query) == false) {
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+
+ // Check for reply error.
+ uint8_t rcode_id = knot_wire_get_rcode(in);
+ if (rcode_id != KNOT_RCODE_NOERROR) {
+ knot_lookup_table_t *rcode =
+ knot_lookup_by_id(knot_rcode_names, rcode_id);
+ if (rcode != NULL) {
+ ERR("server %s respond %s\n",
+ net->remote_str, rcode->name);
+ } else {
+ ERR("server %s respond %i\n",
+ net->remote_str, rcode_id);
+ }
+
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+
+ // The first message has a special treatment.
+ if (msg_count == 0) {
+ // Verify 1. signature if a key was specified.
+ if (key_params->name != NULL) {
+ ret = verify_packet(reply, sign_ctx, key_params);
+ if (ret != KNOT_EOK) {
+ ERR("reply verification for %s (%s)\n",
+ net->remote_str, knot_strerror(ret));
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+ }
+
+ // Read first SOA serial.
+ serial = first_serial_check(reply);
+
+ if (serial < 0) {
+ ERR("first answer record isn't SOA\n");
+ knot_packet_free(&reply);
+ net_close(net);
+ return -1;
+ }
+
+ // Check for question sections equality.
+ check_reply_question(reply, query);
+ }
+
+ msg_count++;
+ rr_count += reply->header.ancount;
+ total_len += in_len;
+
+ // Print reply packet.
+ print_data_xfr(reply, style);
+
+ // Stop if last SOA record has correct serial.
+ if (last_serial_check(serial, reply)) {
+ knot_packet_free(&reply);
+ break;
+ }
+
+ knot_packet_free(&reply);
+ }
+
+ // Get stop reply time.
+ gettimeofday(&t_end, NULL);
+
+ // Print trailing transfer information.
+ print_footer_xfr(total_len, msg_count, rr_count, net,
+ time_diff(&t_query, &t_end), style);
+
+ net_close(net);
+
+ return 0;
+}
+
+static void process_query_xfr(const query_t *query)
+{
+ knot_packet_t *out_packet;
+ uint8_t *out = NULL;
+ size_t out_len = 0;
+ net_t net;
+ int ret;
+
+ if (query == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ // Create query packet.
+ out_packet = create_query_packet(query, &out, &out_len);
+ if (out_packet == NULL) {
+ ERR("can't create query packet\n");
+ return;
+ }
+
+ // Get connection parameters.
+ int iptype = get_iptype(query->ip);
+ int socktype = get_socktype(query->protocol, query->type_num);
+
+ // Use the first nameserver from the list.
+ server_t *remote = HEAD(query->servers);
+
+ DBG("Quering for owner(%s), class(%u), type(%u), server(%s), "
+ "port(%s), protocol(%s)\n", query->owner, query->class_num,
+ query->type_num, remote->name, remote->service,
+ get_sockname(socktype));
+
+ // Initialize network structure.
+ ret = net_init(query->local, remote, iptype, socktype,
+ query->wait, &net);
+ if (ret != KNOT_EOK) {
+ knot_packet_free(&out_packet);
+ return;
+ }
+
+ // Loop over all resolved addresses for remote.
+ while (net.srv != NULL) {
+ ret = process_packet_xfr(out_packet, &net,
+ &query->sign_ctx,
+ &query->key_params,
+ &query->style);
+ // If error try next resolved address.
+ if (ret != 0) {
+ net.srv = (net.srv)->ai_next;
+ continue;
+ }
+
+ break;
+ }
+
+ if (ret != 0) {
+ ERR("failed to query server %s#%s(%s)\n",
+ remote->name, remote->service, get_sockname(socktype));
+ }
+
+ net_clean(&net);
+ knot_packet_free(&out_packet);
+}
+
+int dig_exec(const dig_params_t *params)
+{
+ node *n = NULL;
+
+ if (params == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Loop over query list.
+ WALK_LIST(n, params->queries) {
+ query_t *query = (query_t *)n;
+
+ switch (query->operation) {
+ case OPERATION_QUERY:
+ process_query(query);
+ break;
+ case OPERATION_XFR:
+ process_query_xfr(query);
+ break;
+ case OPERATION_LIST_SOA:
+ break;
+ default:
+ ERR("unsupported operation\n");
+ break;
+ }
+ }
+
+ return KNOT_EOK;
+}
diff --git a/src/tests/libknot/realdata/libknot/edns_tests_realdata.h b/src/utils/dig/dig_exec.h
index cfa64b0..6e1a40b 100644
--- a/src/tests/libknot/realdata/libknot/edns_tests_realdata.h
+++ b/src/utils/dig/dig_exec.h
@@ -1,13 +1,3 @@
-/*!
- * \file edns_tests.h
- *
- * \author Jan Kadlec <jan.kadlec@nic.cz>
- *
- * Contains unit tests for ENDS API
- *
- * Contains tests for:
- * - ENDS API
- */
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
@@ -23,13 +13,25 @@
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 dig_exec.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief dig executives.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _DIG__DIG_EXEC_H_
+#define _DIG__DIG_EXEC_H_
-#ifndef _KNOTD__EDNS_TESTS_H_
-#define _KNOTD__EDNS_TESTS_H_
+#include "utils/common/params.h" // params_t
+#include "utils/dig/dig_params.h" // query_t
-#include "common/libtap/tap_unit.h"
+int dig_exec(const dig_params_t *params);
-/* Unit API. */
-unit_api edns_tests_api;
+#endif // _DIG__DIG_EXEC_H_
-#endif /* _KNOTD__EDNS_TESTS_H_ */
+/*! @} */
diff --git a/src/utils/dig/dig_main.c b/src/utils/dig/dig_main.c
new file mode 100644
index 0000000..487b150
--- /dev/null
+++ b/src/utils/dig/dig_main.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <stdlib.h> // EXIT_FAILURE
+
+#include "common/errcode.h" // KNOT_EOK
+#include "utils/dig/dig_params.h" // dig_parse
+#include "utils/dig/dig_exec.h" // dig_exec
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_SUCCESS;
+
+ dig_params_t params;
+ if (dig_parse(&params, argc, argv) == KNOT_EOK) {
+ if (!params.stop && dig_exec(&params) != KNOT_EOK) {
+ ret = EXIT_FAILURE;
+ }
+ } else {
+ ret = EXIT_FAILURE;
+ }
+
+ dig_clean(&params);
+ return ret;
+}
diff --git a/src/utils/dig/dig_params.c b/src/utils/dig/dig_params.c
new file mode 100644
index 0000000..54361c8
--- /dev/null
+++ b/src/utils/dig/dig_params.c
@@ -0,0 +1,976 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/dig/dig_params.h"
+
+#include <string.h> // strncmp
+#include <stdio.h> // printf
+#include <getopt.h> // getopt
+#include <stdlib.h> // free
+
+#include "common/lists.h" // list
+#include "common/errcode.h" // KNOT_EOK
+#include "common/descriptor.h" // KNOT_CLASS_IN
+#include "utils/common/msg.h" // WARN
+#include "utils/common/params.h" // parse_class
+#include "utils/common/resolv.h" // get_nameservers
+
+#define DEFAULT_RETRIES_DIG 2
+#define DEFAULT_TIMEOUT_DIG 5
+
+static const flags_t DEFAULT_FLAGS_DIG = {
+ .aa_flag = false,
+ .tc_flag = false,
+ .rd_flag = true,
+ .ra_flag = false,
+ .z_flag = false,
+ .ad_flag = false,
+ .cd_flag = false,
+ .do_flag = false
+};
+
+static const style_t DEFAULT_STYLE_DIG = {
+ .format = FORMAT_FULL,
+ .style = { .wrap = false, .show_class = true, .show_ttl = true,
+ .verbose = false, .reduce = false, .human_ttl = false,
+ .human_tmstamp = true },
+ .show_query = false,
+ .show_header = true,
+ .show_edns = true,
+ .show_question = true,
+ .show_answer = true,
+ .show_authority = true,
+ .show_additional = true,
+ .show_footer = true
+};
+
+query_t* query_create(const char *owner, const query_t *conf)
+{
+ // Create output structure.
+ query_t *query = calloc(1, sizeof(query_t));
+
+ if (query == NULL) {
+ DBG_NULL;
+ return NULL;
+ }
+
+ // Set the query owner if any.
+ if (owner != NULL) {
+ if ((query->owner = strdup(owner)) == NULL) {
+ query_free(query);
+ return NULL;
+ }
+ }
+
+ // Initialize list of servers.
+ init_list(&query->servers);
+
+ // Initialization with defaults or with reference query.
+ if (conf == NULL) {
+ query->local = NULL;
+ query->operation = OPERATION_QUERY;
+ query->ip = IP_ALL;
+ query->protocol = PROTO_ALL;
+ query->port = strdup("");
+ query->udp_size = -1;
+ query->retries = DEFAULT_RETRIES_DIG;
+ query->wait = DEFAULT_TIMEOUT_DIG;
+ query->ignore_tc = false;
+ query->servfail_stop = true;
+ query->class_num = -1;
+ query->type_num = -1;
+ query->xfr_serial = 0;
+ query->flags = DEFAULT_FLAGS_DIG;
+ query->style = DEFAULT_STYLE_DIG;
+ query->nsid = false;
+ } else {
+ if (conf->local != NULL) {
+ query->local = server_create(conf->local->name,
+ conf->local->service);
+ if (query->local == NULL) {
+ query_free(query);
+ return NULL;
+ }
+ } else {
+ query->local = NULL;
+ }
+ query->operation = conf->operation;
+ query->ip = conf->ip;
+ query->protocol = conf->protocol;
+ query->port = strdup(conf->port);
+ query->udp_size = conf->udp_size;
+ query->retries = conf->retries;
+ query->wait = conf->wait;
+ query->ignore_tc = conf->ignore_tc;
+ query->servfail_stop = conf->servfail_stop;
+ query->class_num = conf->class_num;
+ query->type_num = conf->type_num;
+ query->xfr_serial = conf->xfr_serial;
+ query->flags = conf->flags;
+ query->style = conf->style;
+ query->nsid = conf->nsid;
+
+ if (knot_copy_key_params(&conf->key_params, &query->key_params)
+ != KNOT_EOK) {
+ query_free(query);
+ return NULL;
+ }
+ }
+
+ // Check dynamic allocation.
+ if (query->port == NULL) {
+ query_free(query);
+ return NULL;
+ }
+
+ return query;
+}
+
+void query_free(query_t *query)
+{
+ node *n = NULL, *nxt = NULL;
+
+ if (query == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ // Cleanup servers.
+ WALK_LIST_DELSAFE(n, nxt, query->servers) {
+ server_free((server_t *)n);
+ }
+
+ // Cleanup local address.
+ if (query->local != NULL) {
+ server_free(query->local);
+ }
+
+ // Cleanup cryptographic content.
+ free_sign_context(&query->sign_ctx);
+ knot_free_key_params(&query->key_params);
+
+ free(query->owner);
+ free(query->port);
+ free(query);
+}
+
+int dig_init(dig_params_t *params)
+{
+ if (params == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ memset(params, 0, sizeof(*params));
+
+ params->stop = false;
+
+ // Initialize list of queries.
+ init_list(&params->queries);
+
+ // Create config query.
+ if ((params->config = query_create(NULL, NULL)) == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ return KNOT_EOK;
+}
+
+void dig_clean(dig_params_t *params)
+{
+ node *n = NULL, *nxt = NULL;
+
+ if (params == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ // Clean up queries.
+ WALK_LIST_DELSAFE(n, nxt, params->queries) {
+ query_free((query_t *)n);
+ }
+
+ // Clean up config.
+ query_free((query_t *)params->config);
+
+ // Clean up the structure.
+ memset(params, 0, sizeof(*params));
+}
+
+static int parse_class(const char *value, query_t *query)
+{
+ uint16_t rclass;
+
+ if (params_parse_class(value, &rclass) != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+
+ query->class_num = rclass;
+
+ return KNOT_EOK;
+}
+
+static int parse_keyfile(const char *value, query_t *query)
+{
+ knot_free_key_params(&query->key_params);
+
+ if (params_parse_keyfile(value, &query->key_params) != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+
+ return KNOT_EOK;
+}
+
+static int parse_local(const char *value, query_t *query)
+{
+ server_t *local = parse_nameserver(value, "0");
+ if (local == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ if (query->local != NULL) {
+ server_free(query->local);
+ }
+
+ query->local = local;
+
+ return KNOT_EOK;
+}
+
+static int parse_name(const char *value, list *queries, const query_t *conf)
+{
+ query_t *query = NULL;
+
+ // If name is not FQDN, append trailing dot.
+ char *fqd_name = get_fqd_name(value);
+
+ // Create new query.
+ query = query_create(fqd_name, conf);
+
+ free(fqd_name);
+
+ if (query == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ // Add new query to the queries.
+ add_tail(queries, (node *)query);
+
+ return KNOT_EOK;
+}
+
+static int parse_port(const char *value, query_t *query)
+{
+ char **port;
+
+ // Set current server port (last or query default).
+ if (list_size(&query->servers) > 0) {
+ server_t *server = TAIL(query->servers);
+ port = &(server->service);
+ } else {
+ port = &(query->port);
+ }
+
+ char *new_port = strdup(value);
+
+ if (new_port == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ // Deallocate old string.
+ free(*port);
+
+ *port = new_port;
+
+ return KNOT_EOK;
+}
+
+static int parse_reverse(const char *value, list *queries, const query_t *conf)
+{
+ query_t *query = NULL;
+
+ // Create reverse name.
+ char *reverse = get_reverse_name(value);
+
+ if (reverse == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ // Create reverse query for given address.
+ query = query_create(reverse, conf);
+
+ free(reverse);
+
+ if (query == NULL) {
+ return KNOT_ENOMEM;
+ }
+
+ // Set type for reverse query.
+ query->type_num = KNOT_RRTYPE_PTR;
+
+ // Add new query to the queries.
+ add_tail(queries, (node *)query);
+
+ return KNOT_EOK;
+}
+
+static int parse_server(const char *value, dig_params_t *params)
+{
+ query_t *query;
+
+ // Set current query (last or config).
+ if (list_size(&params->queries) > 0) {
+ query = TAIL(params->queries);
+ } else {
+ query = params->config;
+ }
+
+ return params_parse_server(value, &query->servers, query->port);
+}
+
+static int parse_tsig(const char *value, query_t *query)
+{
+ knot_free_key_params(&query->key_params);
+
+ if (params_parse_tsig(value, &query->key_params) != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+
+ return KNOT_EOK;
+}
+
+static int parse_type(const char *value, query_t *query)
+{
+ uint16_t rtype;
+ uint32_t serial;
+
+ if (params_parse_type(value, &rtype, &serial) != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+
+ query->type_num = rtype;
+ query->xfr_serial = serial;
+
+ return KNOT_EOK;
+}
+
+static void complete_servers(query_t *query, const query_t *conf)
+{
+ node *n = NULL;
+ char *def_port;
+
+ // Decide which default port use.
+ if (strlen(query->port) > 0) {
+ def_port = query->port;
+ } else if (strlen(conf->port) > 0) {
+ def_port = conf->port;
+ } else {
+ def_port = DEFAULT_DNS_PORT;
+ }
+
+ // Complete specified nameservers if any.
+ if (list_size(&query->servers) > 0) {
+ WALK_LIST(n, query->servers) {
+ server_t *s = (server_t *)n;
+
+ // If the port isn't specified yet use the default one.
+ if (strlen(s->service) == 0) {
+ free(s->service);
+ s->service = strdup(def_port);
+ if (s->service == NULL) {
+ WARN("can't set port %s\n", def_port);
+ return;
+ }
+ }
+ }
+ // Use servers from config if any.
+ } else if (list_size(&conf->servers) > 0) {
+ WALK_LIST(n, conf->servers) {
+ server_t *s = (server_t *)n;
+ char *port = def_port;
+
+ // If the port is already specified, use it.
+ if (strlen(s->service) > 0) {
+ port = s->service;
+ }
+
+ server_t *server = server_create(s->name, port);
+ if (server == NULL) {
+ WARN("can't set nameserver %s port %s\n",
+ s->name, s->service);
+ return;
+ }
+ add_tail(&query->servers, (node *)server);
+ }
+ // Use system specific.
+ } else if (get_nameservers(&query->servers, def_port) <= 0) {
+ WARN("can't read any nameservers\n");
+ }
+}
+
+void complete_queries(list *queries, const query_t *conf)
+{
+ query_t *q = NULL;
+ node *n = NULL;
+
+ if (queries == NULL || conf == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ // If there is no query, add default query: NS to ".".
+ if (list_size(queries) == 0) {
+ q = query_create(".", conf);
+ if (q == NULL) {
+ WARN("can't create query . NS IN\n");
+ return;
+ }
+ q->class_num = KNOT_CLASS_IN;
+ q->type_num = KNOT_RRTYPE_NS;
+ add_tail(queries, (node *)q);
+ }
+
+ WALK_LIST(n, *queries) {
+ query_t *q = (query_t *)n;
+
+ // Fill class number if missing.
+ if (q->class_num < 0) {
+ if (conf->class_num >= 0) {
+ q->class_num = conf->class_num;
+ } else {
+ q->class_num = KNOT_CLASS_IN;
+ }
+ }
+
+ // Fill type number if missing.
+ if (q->type_num < 0) {
+ if (conf->type_num >= 0) {
+ q->type_num = conf->type_num;
+ q->xfr_serial = conf->xfr_serial;
+ } else {
+ q->type_num = KNOT_RRTYPE_A;
+ }
+ }
+
+ // Set zone transfer if any.
+ if (q->type_num == KNOT_RRTYPE_AXFR ||
+ q->type_num == KNOT_RRTYPE_IXFR) {
+ q->operation = OPERATION_XFR;
+ }
+
+ // No retries for TCP.
+ if (q->protocol == PROTO_TCP) {
+ q->retries = 0;
+ }
+
+ // Complete nameservers list.
+ complete_servers(q, conf);
+ }
+}
+
+static void dig_help(void)
+{
+ printf("Usage: kdig [-4] [-6] [-dh] [-b address] [-c class] [-p port]\n"
+ " [-q name] [-t type] [-x address] [-k keyfile]\n"
+ " [-y [algo:]keyname:key] name @server\n"
+ "\n"
+ " +[no]multiline Wrap long records to more lines.\n"
+ " +[no]short Show record data only.\n"
+ " +[no]aaflag Set AA flag.\n"
+ " +[no]tcflag Set TC flag.\n"
+ " +[no]rdflag Set RD flag.\n"
+ " +[no]recurse Same as +[no]rdflag\n"
+ " +[no]rec Same as +[no]rdflag\n"
+ " +[no]raflag Set RA flag.\n"
+ " +[no]zflag Set zero flag bit.\n"
+ " +[no]adflag Set AD flag.\n"
+ " +[no]cdflag Set CD flag.\n"
+ " +[no]dnssec Set DO flag.\n"
+ " +[no]all Show all packet sections.\n"
+ " +[no]qr Show query packet.\n"
+ " +[no]header Show packet header.\n"
+ " +[no]edns Show EDNS pseudosection.\n"
+ " +[no]question Show question section.\n"
+ " +[no]answer Show answer section.\n"
+ " +[no]authority Show authority section.\n"
+ " +[no]additional Show additional section.\n"
+ " +[no]stats Show trailing packet statistics.\n"
+ " +[no]cl Show DNS class.\n"
+ " +[no]ttl Show TTL value.\n"
+ " +time=T Set wait for reply interval in seconds.\n"
+ " +retries=N Set number of retries.\n"
+ " +bufsize=B Set EDNS buffer size.\n"
+ " +[no]tcp Use TCP protocol.\n"
+ " +[no]fail Stop if SERVFAIL.\n"
+ " +[no]ignore Don't use TCP automatically if truncated.\n"
+ " +[no]nsid Request NSID.\n"
+ "\n"
+ " -h, --help Print help.\n"
+ " -v, --version Print program version.\n");
+}
+
+static int parse_opt1(const char *opt, const char *value, dig_params_t *params,
+ int *index)
+{
+ const char *val = value;
+ size_t len = strlen(opt);
+ int add = 1;
+ query_t *query;
+
+ // Set current query (last or config).
+ if (list_size(&params->queries) > 0) {
+ query = TAIL(params->queries);
+ } else {
+ query = params->config;
+ }
+
+ // If there is no space between option and argument.
+ if (len > 1) {
+ val = opt + 1;
+ add = 0;
+ }
+
+ switch (opt[0]) {
+ case '4':
+ if (len > 1) {
+ ERR("invalid option -%s\n", opt);
+ return KNOT_ENOTSUP;
+ }
+
+ query->ip = IP_4;
+ break;
+ case '6':
+ if (len > 1) {
+ ERR("invalid option -%s\n", opt);
+ return KNOT_ENOTSUP;
+ }
+
+ query->ip = IP_6;
+ break;
+ case 'b':
+ if (val == NULL) {
+ ERR("missing address\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_local(val, query) != KNOT_EOK) {
+ ERR("bad address %s\n", val);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case 'd':
+ msg_enable_debug(1);
+ break;
+ case 'h':
+ if (len > 1) {
+ ERR("invalid option -%s\n", opt);
+ return KNOT_ENOTSUP;
+ }
+
+ dig_help();
+ params->stop = true;
+ break;
+ case 'c':
+ if (val == NULL) {
+ ERR("missing class\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_class(val, query) != KNOT_EOK) {
+ ERR("bad class %s\n", val);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case 'k':
+ if (val == NULL) {
+ ERR("missing filename\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_keyfile(val, query) != KNOT_EOK) {
+ ERR("bad keyfile %s\n", value);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case 'p':
+ if (val == NULL) {
+ ERR("missing port\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_port(val, query) != KNOT_EOK) {
+ ERR("bad port %s\n", value);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case 'q':
+ if (val == NULL) {
+ ERR("missing name\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_name(val, &params->queries, params->config)
+ != KNOT_EOK) {
+ ERR("bad query name %s\n", val);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case 't':
+ if (val == NULL) {
+ ERR("missing type\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_type(val, query) != KNOT_EOK) {
+ ERR("bad type %s\n", val);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case 'v':
+ if (len > 1) {
+ ERR("invalid option -%s\n", opt);
+ return KNOT_ENOTSUP;
+ }
+
+ printf(KDIG_VERSION);
+ params->stop = true;
+ break;
+ case 'x':
+ if (val == NULL) {
+ ERR("missing address\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_reverse(val, &params->queries, params->config)
+ != KNOT_EOK) {
+ ERR("bad reverse name %s\n", val);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case 'y':
+ if (val == NULL) {
+ ERR("missing key\n");
+ return KNOT_EINVAL;
+ }
+
+ if (parse_tsig(val, query) != KNOT_EOK) {
+ ERR("bad key %s\n", value);
+ return KNOT_EINVAL;
+ }
+ *index += add;
+ break;
+ case '-':
+ if (strcmp(opt, "-help") == 0) {
+ dig_help();
+ params->stop = true;
+ } else if (strcmp(opt, "-version") == 0) {
+ printf(KDIG_VERSION);
+ params->stop = true;
+ } else {
+ ERR("invalid option: -%s\n", opt);
+ return KNOT_ENOTSUP;
+ }
+ break;
+ default:
+ ERR("invalid option: -%s\n", opt);
+ return KNOT_ENOTSUP;
+ }
+
+ return KNOT_EOK;
+}
+
+static int parse_opt2(const char *value, dig_params_t *params)
+{
+ query_t *query;
+
+ // Set current query (last or config).
+ if (list_size(&params->queries) > 0) {
+ query = TAIL(params->queries);
+ } else {
+ query = params->config;
+ }
+
+ // Check for format option.
+ if (strcmp(value, "multiline") == 0) {
+ query->style.style.wrap = true;
+ query->style.format = FORMAT_FULL;
+ query->style.show_header = true;
+ query->style.show_edns = true;
+ query->style.show_footer = true;
+ query->style.style.verbose = true;
+ query->style.style.human_ttl = true;
+ } else if (strcmp(value, "nomultiline") == 0) {
+ query->style.style.wrap = false;
+ }
+ else if (strcmp(value, "short") == 0) {
+ query->style.format = FORMAT_DIG;
+ query->style.show_header = false;
+ query->style.show_edns = false;
+ query->style.show_footer = false;
+ } else if (strcmp(value, "noshort") == 0) {
+ query->style.format = FORMAT_FULL;
+ }
+
+ // Check for flag option.
+ else if (strcmp(value, "aaflag") == 0) {
+ query->flags.aa_flag = true;
+ } else if (strcmp(value, "noaaflag") == 0) {
+ query->flags.aa_flag = false;
+ }
+ else if (strcmp(value, "tcflag") == 0) {
+ query->flags.tc_flag = true;
+ } else if (strcmp(value, "notcflag") == 0) {
+ query->flags.tc_flag = false;
+ }
+ else if (strcmp(value, "rdflag") == 0 ||
+ strcmp(value, "recurse") == 0 ||
+ strcmp(value, "rec") == 0) {
+ query->flags.rd_flag = true;
+ } else if (strcmp(value, "nordflag") == 0 ||
+ strcmp(value, "norecurse") == 0 ||
+ strcmp(value, "norec") == 0) {
+ query->flags.rd_flag = false;
+ }
+ else if (strcmp(value, "raflag") == 0) {
+ query->flags.ra_flag = true;
+ } else if (strcmp(value, "noraflag") == 0) {
+ query->flags.ra_flag = false;
+ }
+ else if (strcmp(value, "zflag") == 0) {
+ query->flags.z_flag = true;
+ } else if (strcmp(value, "nozflag") == 0) {
+ query->flags.z_flag = false;
+ }
+ else if (strcmp(value, "adflag") == 0) {
+ query->flags.ad_flag = true;
+ } else if (strcmp(value, "noadflag") == 0) {
+ query->flags.ad_flag = false;
+ }
+ else if (strcmp(value, "cdflag") == 0) {
+ query->flags.cd_flag = true;
+ } else if (strcmp(value, "nocdflag") == 0) {
+ query->flags.cd_flag = false;
+ }
+ else if (strcmp(value, "dnssec") == 0) {
+ query->flags.do_flag = true;
+ } else if (strcmp(value, "nodnssec") == 0) {
+ query->flags.do_flag = false;
+ }
+
+ // Check for display option.
+ else if (strcmp(value, "all") == 0) {
+ query->style.show_header = true;
+ query->style.show_edns = true;
+ query->style.show_question = true;
+ query->style.show_answer = true;
+ query->style.show_authority = true;
+ query->style.show_additional = true;
+ query->style.show_footer = true;
+ } else if (strcmp(value, "noall") == 0) {
+ query->style.show_header = false;
+ query->style.show_edns = false;
+ query->style.show_query = false;
+ query->style.show_question = false;
+ query->style.show_answer = false;
+ query->style.show_authority = false;
+ query->style.show_additional = false;
+ query->style.show_footer = false;
+ }
+ else if (strcmp(value, "qr") == 0) {
+ query->style.show_query = true;
+ } else if (strcmp(value, "noqr") == 0) {
+ query->style.show_query = false;
+ }
+ else if (strcmp(value, "header") == 0) {
+ query->style.show_header = true;
+ } else if (strcmp(value, "noheader") == 0) {
+ query->style.show_header = false;
+ }
+ else if (strcmp(value, "edns") == 0) {
+ query->style.show_edns = true;
+ } else if (strcmp(value, "noedns") == 0) {
+ query->style.show_edns = false;
+ }
+ else if (strcmp(value, "question") == 0) {
+ query->style.show_question = true;
+ } else if (strcmp(value, "noquestion") == 0) {
+ query->style.show_question = false;
+ }
+ else if (strcmp(value, "answer") == 0) {
+ query->style.show_answer = true;
+ } else if (strcmp(value, "noanswer") == 0) {
+ query->style.show_answer = false;
+ }
+ else if (strcmp(value, "authority") == 0) {
+ query->style.show_authority = true;
+ } else if (strcmp(value, "noauthority") == 0) {
+ query->style.show_authority = false;
+ }
+ else if (strcmp(value, "additional") == 0) {
+ query->style.show_additional = true;
+ } else if (strcmp(value, "noadditional") == 0) {
+ query->style.show_additional = false;
+ }
+ else if (strcmp(value, "stats") == 0) {
+ query->style.show_footer = true;
+ } else if (strcmp(value, "nostats") == 0) {
+ query->style.show_footer = false;
+ }
+ else if (strcmp(value, "cl") == 0) {
+ query->style.style.show_class = true;
+ } else if (strcmp(value, "nocl") == 0) {
+ query->style.style.show_class = false;
+ }
+ else if (strcmp(value, "ttl") == 0) {
+ query->style.style.show_ttl = true;
+ } else if (strcmp(value, "nottl") == 0) {
+ query->style.style.show_ttl = false;
+ }
+
+ // Check for query option.
+ else if (strncmp(value, "time=", 5) == 0) {
+ if (params_parse_wait(value + 5, &query->wait)
+ != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+ }
+ else if (strncmp(value, "retries=", 8) == 0) {
+ if (params_parse_num(value + 8, &query->retries)
+ != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+ }
+ else if (strncmp(value, "bufsize=", 8) == 0) {
+ if (params_parse_bufsize(value + 8, &query->udp_size)
+ != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+ }
+ else if (strcmp(value, "tcp") == 0) {
+ query->protocol = PROTO_TCP;
+ } else if (strcmp(value, "notcp") == 0) {
+ query->protocol = PROTO_UDP;
+ query->ignore_tc = true;
+ }
+ else if (strcmp(value, "fail") == 0) {
+ query->servfail_stop = true;
+ } else if (strcmp(value, "nofail") == 0) {
+ query->servfail_stop = false;
+ }
+ else if (strcmp(value, "ignore") == 0) {
+ query->ignore_tc = true;
+ } else if (strcmp(value, "noignore") == 0) {
+ query->ignore_tc = false;
+ }
+ else if (strcmp(value, "nsid") == 0) {
+ query->nsid = true;
+ } else if (strcmp(value, "nonsid") == 0) {
+ query->nsid = false;
+ }
+
+ // Unknown option.
+ else {
+ ERR("invalid option: +%s\n", value);
+ return KNOT_ENOTSUP;
+ }
+
+ return KNOT_EOK;
+}
+
+static int parse_token(const char *value, dig_params_t *params)
+{
+ query_t *query;
+
+ // Set current query (last or config).
+ if (list_size(&params->queries) > 0) {
+ query = TAIL(params->queries);
+ } else {
+ query = params->config;
+ }
+
+ // Try to guess the meaning of the token.
+ if (parse_type(value, query) == KNOT_EOK) {
+ return KNOT_EOK;
+ } else if (parse_class(value, query) == KNOT_EOK) {
+ return KNOT_EOK;
+ } else if (parse_name(value, &params->queries, params->config)
+ == KNOT_EOK) {
+ return KNOT_EOK;
+ }
+
+ ERR("invalid parameter: %s\n", value);
+ return KNOT_ENOTSUP;
+}
+
+int dig_parse(dig_params_t *params, int argc, char *argv[])
+{
+ if (params == NULL || argv == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ // Initialize parameters.
+ if (dig_init(params) != KNOT_EOK) {
+ return KNOT_ERROR;
+ }
+
+ // Command line parameters processing.
+ for (int i = 1; i < argc; i++) {
+ int ret = KNOT_ERROR;
+
+ // Process parameter.
+ switch (argv[i][0]) {
+ case '@':
+ ret = parse_server(argv[i] + 1, params);
+ break;
+ case '-':
+ ret = parse_opt1(argv[i] + 1, argv[i + 1], params, &i);
+ break;
+ case '+':
+ ret = parse_opt2(argv[i] + 1, params);
+ break;
+ default:
+ ret = parse_token(argv[i], params);
+ break;
+ }
+
+ // Check return.
+ switch (ret) {
+ case KNOT_EOK:
+ if (params->stop) {
+ return KNOT_EOK;
+ }
+ break;
+ case KNOT_ENOTSUP:
+ dig_help();
+ default: // Fall through.
+ return ret;
+ }
+ }
+
+ // Complete missing data in queries based on defaults.
+ complete_queries(&params->queries, params->config);
+
+ return KNOT_EOK;
+}
diff --git a/src/utils/dig/dig_params.h b/src/utils/dig/dig_params.h
new file mode 100644
index 0000000..f2258ac
--- /dev/null
+++ b/src/utils/dig/dig_params.h
@@ -0,0 +1,133 @@
+/* Copyright (C) 2011 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 dig_params.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief dig command line parameters.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _DIG__DIG_PARAMS_H_
+#define _DIG__DIG_PARAMS_H_
+
+#include <stdbool.h> // bool
+
+#include "utils/common/params.h" // protocol_t
+#include "utils/common/exec.h" // sign_context_t
+
+#define KDIG_VERSION "kdig, version " PACKAGE_VERSION "\n"
+
+/*! \brief Operation mode of dig. */
+typedef enum {
+ /*!< Standard 1-message query/reply. */
+ OPERATION_QUERY,
+ /*!< Zone transfer (AXFR or IXFR). */
+ OPERATION_XFR,
+ /*!< Query for NS and all authoritative SOA records. */
+ OPERATION_LIST_SOA
+} operation_t;
+
+/*! \brief DNS header and EDNS flags. */
+typedef struct {
+ /*!< Authoritative answer flag. */
+ bool aa_flag;
+ /*!< Truncated flag. */
+ bool tc_flag;
+ /*!< Recursion desired flag. */
+ bool rd_flag;
+ /*!< Recursion available flag. */
+ bool ra_flag;
+ /*!< Z flag. */
+ bool z_flag;
+ /*!< Authenticated data flag. */
+ bool ad_flag;
+ /*!< Checking disabled flag. */
+ bool cd_flag;
+ /*!< DNSSEC OK flag. */
+ bool do_flag;
+} flags_t;
+
+/*! \brief Basic parameters for DNS query. */
+typedef struct {
+ /*!< List node (for list container). */
+ node n;
+ /*!< Name to query on. */
+ char *owner;
+ /*!< List of nameservers to query to. */
+ list servers;
+ /*!< Local interface (optional). */
+ server_t *local;
+ /*!< Operation mode. */
+ operation_t operation;
+ /*!< Version of ip protocol to use. */
+ ip_t ip;
+ /*!< Protocol type (TCP, UDP) to use. */
+ protocol_t protocol;
+ /*!< Port/service to connect to. */
+ char *port;
+ /*!< UDP buffer size (16unsigned + -1 uninitialized). */
+ int32_t udp_size;
+ /*!< Number of UDP retries. */
+ uint32_t retries;
+ /*!< Wait for network response in seconds (-1 means forever). */
+ int32_t wait;
+ /*!< Ignore truncated response. */
+ bool ignore_tc;
+ /*!< Stop quering if servfail. */
+ bool servfail_stop;
+ /*!< Class number (16unsigned + -1 uninitialized). */
+ int32_t class_num;
+ /*!< Type number (16unsigned + -1 uninitialized). */
+ int32_t type_num;
+ /*!< SOA serial for XFR. */
+ uint32_t xfr_serial;
+ /*!< Header flags. */
+ flags_t flags;
+ /*!< Output settings. */
+ style_t style;
+ /*!< Query for NSID. */
+ bool nsid;
+ /*!< Key parameters. */
+ knot_key_params_t key_params;
+ /*!< Context for operations with signatures. */
+ sign_context_t sign_ctx;
+} query_t;
+
+/*! \brief Settings for dig. */
+typedef struct {
+ /*!< Stop processing - just pring help, version,... */
+ bool stop;
+ /*!< List of DNS queries to process. */
+ list queries;
+ /*!< Default settings for queries. */
+ query_t *config;
+} dig_params_t;
+
+query_t* query_create(const char *owner, const query_t *config);
+void query_free(query_t *query);
+void complete_queries(list *queries, const query_t *conf);
+
+int dig_init(dig_params_t *params);
+int dig_parse(dig_params_t *params, int argc, char *argv[]);
+void dig_clean(dig_params_t *params);
+
+#endif // _DIG__DIG_PARAMS_H_
+
+/*! @} */
diff --git a/src/utils/host/host_main.c b/src/utils/host/host_main.c
new file mode 100644
index 0000000..b10313d
--- /dev/null
+++ b/src/utils/host/host_main.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <stdlib.h> // EXIT_FAILURE
+
+#include "common/errcode.h" // KNOT_EOK
+#include "utils/host/host_params.h" // host_parse
+#include "utils/dig/dig_exec.h" // dig_exec
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_SUCCESS;
+
+ dig_params_t params;
+ if (host_parse(&params, argc, argv) == KNOT_EOK) {
+ if (!params.stop && dig_exec(&params) != KNOT_EOK) {
+ ret = EXIT_FAILURE;
+ }
+ } else {
+ ret = EXIT_FAILURE;
+ }
+
+ host_clean(&params);
+ return ret;
+}
diff --git a/src/utils/host/host_params.c b/src/utils/host/host_params.c
new file mode 100644
index 0000000..0b32893
--- /dev/null
+++ b/src/utils/host/host_params.c
@@ -0,0 +1,322 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "utils/host/host_params.h"
+
+#include <string.h> // strncmp
+#include <stdio.h> // printf
+#include <getopt.h> // getopt
+#include <stdlib.h> // free
+
+#include "common/lists.h" // list
+#include "common/errcode.h" // KNOT_EOK
+#include "common/descriptor.h" // KNOT_CLASS_IN
+#include "utils/common/msg.h" // WARN
+#include "utils/dig/dig_params.h" // dig_params_t
+#include "utils/common/resolv.h" // get_nameservers
+
+#define DEFAULT_RETRIES_HOST 1
+#define DEFAULT_TIMEOUT_HOST 2
+
+static const style_t DEFAULT_STYLE_HOST = {
+ .format = FORMAT_HOST,
+ .style = { .wrap = false, .show_class = true, .show_ttl = true,
+ .verbose = true, .reduce = false, .human_ttl = false,
+ .human_tmstamp = true },
+ .show_query = false,
+ .show_header = false,
+ .show_edns = false,
+ .show_question = true,
+ .show_answer = true,
+ .show_authority = true,
+ .show_additional = true,
+ .show_footer = false,
+};
+
+static int host_init(dig_params_t *params)
+{
+ // Initialize params with dig defaults.
+ int ret = dig_init(params);
+
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ // Set host specific defaults.
+ free(params->config->port);
+ params->config->port = strdup(DEFAULT_DNS_PORT);
+ params->config->retries = DEFAULT_RETRIES_HOST;
+ params->config->wait = DEFAULT_TIMEOUT_HOST;
+ params->config->servfail_stop = false;
+ params->config->class_num = KNOT_CLASS_IN;
+ params->config->style = DEFAULT_STYLE_HOST;
+
+ // Check port.
+ if (params->config->port == NULL) {
+ query_free(params->config);
+ return KNOT_ENOMEM;
+ }
+
+ return KNOT_EOK;
+}
+
+void host_clean(dig_params_t *params)
+{
+ if (params == NULL) {
+ DBG_NULL;
+ return;
+ }
+
+ dig_clean(params);
+}
+
+static int parse_name(const char *value, list *queries, const query_t *conf)
+{
+ char *reverse = get_reverse_name(value);
+ char *fqd_name = NULL;
+ query_t *query;
+
+ // If name is not FQDN, append trailing dot.
+ fqd_name = get_fqd_name(value);
+
+ // RR type is known.
+ if (conf->type_num >= 0) {
+ if (conf->type_num == KNOT_RRTYPE_PTR) {
+ free(fqd_name);
+
+ // Check for correct address.
+ if (reverse == NULL) {
+ ERR("invalid IPv4 or IPv6 address %s\n", value);
+ return KNOT_EINVAL;
+ }
+
+ // Add reverse query for address.
+ query = query_create(reverse, conf);
+ free(reverse);
+ if (query == NULL) {
+ return KNOT_ENOMEM;
+ }
+ add_tail(queries, (node *)query);
+ } else {
+ free(reverse);
+
+ // Add query for name and specified type.
+ query = query_create(fqd_name, conf);
+ free(fqd_name);
+ if (query == NULL) {
+ return KNOT_ENOMEM;
+ }
+ add_tail(queries, (node *)query);
+ }
+ // RR type is unknown, use defaults.
+ } else {
+ if (reverse == NULL) {
+ // Add query for name and type A.
+ query = query_create(fqd_name, conf);
+ if (query == NULL) {
+ free(fqd_name);
+ return KNOT_ENOMEM;
+ }
+ query->type_num = KNOT_RRTYPE_A;
+ add_tail(queries, (node *)query);
+
+ // Add query for name and type AAAA.
+ query = query_create(fqd_name, conf);
+ if (query == NULL) {
+ free(fqd_name);
+ return KNOT_ENOMEM;
+ }
+ query->type_num = KNOT_RRTYPE_AAAA;
+ add_tail(queries, (node *)query);
+
+ // Add query for name and type MX.
+ query = query_create(fqd_name, conf);
+ if (query == NULL) {
+ free(fqd_name);
+ return KNOT_ENOMEM;
+ }
+ free(fqd_name);
+ query->type_num = KNOT_RRTYPE_MX;
+ add_tail(queries, (node *)query);
+ } else {
+ free(fqd_name);
+
+ // Add reverse query for address.
+ query = query_create(reverse, conf);
+ free(reverse);
+ if (query == NULL) {
+ return KNOT_ENOMEM;
+ }
+ query->type_num = KNOT_RRTYPE_PTR;
+ add_tail(queries, (node *)query);
+ }
+ }
+
+ return KNOT_EOK;
+}
+
+static void host_help(void)
+{
+ printf("Usage: khost [-4] [-6] [-adhrsTvVw] [-c class] [-t type]\n"
+ " [-R retries] [-W time] name [server]\n\n"
+ " -4 Use IPv4 protocol only.\n"
+ " -6 Use IPv6 procotol only.\n"
+ " -a Same as -t ANY -v.\n"
+ " -d Allow debug messages.\n"
+ " -h, --help Print help.\n"
+ " -r Disable recursion.\n"
+ " -s Stop if servfail.\n"
+ " -T Use TCP procotol.\n"
+ " -v Verbose output.\n"
+ " -V, --version Print program version.\n"
+ " -w Wait forever.\n"
+ " -c Set query class.\n"
+ " -t Set query type.\n"
+ " -R Set number of UDP retries.\n"
+ " -W Set wait interval.\n"
+ );
+}
+
+int host_parse(dig_params_t *params, int argc, char *argv[])
+{
+ int opt = 0, li = 0;
+
+ if (params == NULL || argv == NULL) {
+ DBG_NULL;
+ return KNOT_EINVAL;
+ }
+
+ if (host_init(params) != KNOT_EOK) {
+ return KNOT_ERROR;
+ }
+
+ query_t *conf = params->config;
+ uint16_t rclass, rtype;
+ uint32_t serial;
+
+ // Long options.
+ struct option opts[] = {
+ { "version", no_argument, 0, 'V' },
+ { "help", no_argument, 0, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ // Command line options processing.
+ while ((opt = getopt_long(argc, argv, "46adhrsTvVwc:t:R:W:", opts, &li))
+ != -1) {
+ switch (opt) {
+ case '4':
+ conf->ip = IP_4;
+ break;
+ case '6':
+ conf->ip = IP_6;
+ break;
+ case 'a':
+ conf->type_num = KNOT_RRTYPE_ANY;
+ conf->style.format = FORMAT_FULL;
+ conf->style.show_header = true;
+ conf->style.show_edns = true;
+ conf->style.show_footer = true;
+ break;
+ case 'd':
+ msg_enable_debug(1);
+ break;
+ case 'h':
+ host_help();
+ params->stop = false;
+ return KNOT_EOK;
+ case 'r':
+ conf->flags.rd_flag = false;
+ break;
+ case 's':
+ conf->servfail_stop = true;
+ break;
+ case 'T':
+ conf->protocol = PROTO_TCP;
+ break;
+ case 'v':
+ conf->style.format = FORMAT_FULL;
+ conf->style.show_header = true;
+ conf->style.show_edns = true;
+ conf->style.show_footer = true;
+ break;
+ case 'V':
+ printf(KHOST_VERSION);
+ params->stop = false;
+ return KNOT_EOK;
+ case 'w':
+ conf->wait = -1;
+ break;
+ case 'c':
+ if (params_parse_class(optarg, &rclass)
+ != KNOT_EOK) {
+ ERR("bad class %s\n", optarg);
+ return KNOT_EINVAL;
+ }
+ conf->class_num = rclass;
+ break;
+ case 't':
+ if (params_parse_type(optarg, &rtype, &serial)
+ != KNOT_EOK) {
+ ERR("bad type %s\n", optarg);
+ return KNOT_EINVAL;
+ }
+ conf->type_num = rtype;
+ conf->xfr_serial = serial;
+ break;
+ case 'R':
+ if (params_parse_num(optarg, &conf->retries)
+ != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+ break;
+ case 'W':
+ if (params_parse_wait(optarg, &conf->wait)
+ != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+ break;
+ default:
+ host_help();
+ return KNOT_ENOTSUP;
+ }
+ }
+
+ // Process non-option parameters.
+ switch (argc - optind) {
+ case 2:
+ if (params_parse_server(argv[optind + 1], &conf->servers,
+ conf->port)
+ != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+ case 1: // Fall through.
+ if (parse_name(argv[optind], &params->queries, conf)
+ != KNOT_EOK) {
+ return KNOT_EINVAL;
+ }
+ break;
+ default:
+ host_help();
+ return KNOT_ENOTSUP;
+ }
+
+ // Complete missing data in queries based on defaults.
+ complete_queries(&params->queries, params->config);
+
+ return KNOT_EOK;
+}
diff --git a/src/utils/host/host_params.h b/src/utils/host/host_params.h
new file mode 100644
index 0000000..0ae6dc6
--- /dev/null
+++ b/src/utils/host/host_params.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011 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 host_params.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief host command line parameters.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _HOST__HOST_PARAMS_H_
+#define _HOST__HOST_PARAMS_H_
+
+#include "utils/dig/dig_params.h" // dig_params_t
+
+#define KHOST_VERSION "khost, version " PACKAGE_VERSION "\n"
+
+int host_parse(dig_params_t *params, int argc, char *argv[]);
+void host_clean(dig_params_t *params);
+
+#endif // _HOST__HOST_PARAMS_H_
+
+/*! @} */
diff --git a/src/utils/nsupdate/nsupdate_exec.c b/src/utils/nsupdate/nsupdate_exec.c
new file mode 100644
index 0000000..705e7c0
--- /dev/null
+++ b/src/utils/nsupdate/nsupdate_exec.c
@@ -0,0 +1,929 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <stdio.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "utils/nsupdate/nsupdate_exec.h"
+#include "utils/common/params.h"
+#include "utils/common/msg.h"
+#include "utils/common/exec.h"
+#include "utils/common/netio.h"
+#include "utils/common/token.h"
+#include "common/errcode.h"
+#include "common/mempattern.h"
+#include "common/descriptor.h"
+#include "libknot/libknot.h"
+
+/* Declarations of cmd parse functions. */
+typedef int (*cmd_handle_f)(const char *lp, nsupdate_params_t *params);
+int cmd_add(const char* lp, nsupdate_params_t *params);
+int cmd_answer(const char* lp, nsupdate_params_t *params);
+int cmd_class(const char* lp, nsupdate_params_t *params);
+int cmd_debug(const char* lp, nsupdate_params_t *params);
+int cmd_del(const char* lp, nsupdate_params_t *params);
+int cmd_gsstsig(const char* lp, nsupdate_params_t *params);
+int cmd_key(const char* lp, nsupdate_params_t *params);
+int cmd_local(const char* lp, nsupdate_params_t *params);
+int cmd_oldgsstsig(const char* lp, nsupdate_params_t *params);
+int cmd_origin(const char* lp, nsupdate_params_t *params);
+int cmd_prereq(const char* lp, nsupdate_params_t *params);
+int cmd_realm(const char* lp, nsupdate_params_t *params);
+int cmd_send(const char* lp, nsupdate_params_t *params);
+int cmd_server(const char* lp, nsupdate_params_t *params);
+int cmd_show(const char* lp, nsupdate_params_t *params);
+int cmd_ttl(const char* lp, nsupdate_params_t *params);
+int cmd_update(const char* lp, nsupdate_params_t *params);
+int cmd_zone(const char* lp, nsupdate_params_t *params);
+
+/* Sorted list of commands.
+ * This way we could identify command byte-per-byte and
+ * cancel early if the next is lexicographically greater.
+ */
+const char* cmd_array[] = {
+ "\x3" "add",
+ "\x6" "answer",
+ "\x5" "class", /* {classname} */
+ "\x5" "debug",
+ "\x3" "del",
+ "\x6" "delete",
+ "\x7" "gsstsig",
+ "\x3" "key", /* {name} {secret} */
+ "\x5" "local", /* {address} [port] */
+ "\xa" "oldgsstsig",
+ "\x6" "origin", /* {name} */
+ "\x6" "prereq", /* (nx|yx)(domain|rrset) {domain-name} ... */
+ "\x5" "realm", /* {[realm_name]} */
+ "\x4" "send",
+ "\x6" "server", /* {servername} [port] */
+ "\x4" "show",
+ "\x3" "ttl", /* {seconds} */
+ "\x6" "update", /* (add|delete) {domain-name} ... */
+ "\x4" "zone", /* {zonename} */
+ NULL
+};
+
+cmd_handle_f cmd_handle[] = {
+ cmd_add,
+ cmd_answer,
+ cmd_class,
+ cmd_debug,
+ cmd_del,
+ cmd_del, /* delete/del synonyms */
+ cmd_gsstsig,
+ cmd_key,
+ cmd_local,
+ cmd_oldgsstsig,
+ cmd_origin,
+ cmd_prereq,
+ cmd_realm,
+ cmd_send,
+ cmd_server,
+ cmd_show,
+ cmd_ttl,
+ cmd_update,
+ cmd_zone,
+};
+
+/* {prereq} command table. */
+const char* pq_array[] = {
+ "\x8" "nxdomain",
+ "\x7" "nxrrset",
+ "\x8" "yxdomain",
+ "\x7" "yxrrset",
+ NULL
+};
+enum {
+ PQ_NXDOMAIN = 0,
+ PQ_NXRRSET,
+ PQ_YXDOMAIN,
+ PQ_YXRRSET,
+ UP_ADD,
+ UP_DEL
+};
+
+/* RR parser flags */
+enum {
+ PARSE_NODEFAULT = 1 << 0, /* Do not fill defaults. */
+ PARSE_NAMEONLY = 1 << 1 /* Parse only name. */
+};
+
+static int dname_isvalid(const char *lp, size_t len) {
+ knot_dname_t *dn = knot_dname_new_from_str(lp, len, NULL);
+ if (dn == NULL) {
+ return 0;
+ }
+ knot_dname_free(&dn);
+ return 1;
+}
+
+/* This is probably redundant, but should be a bit faster so let's keep it. */
+static int parse_full_rr(scanner_t *s, const char* lp)
+{
+ if (scanner_process(lp, lp + strlen(lp), 0, s) < 0) {
+ return KNOT_EPARSEFAIL;
+ }
+ char nl = '\n'; /* Ensure newline after complete RR */
+ if (scanner_process(&nl, &nl+sizeof(char), 1, s) < 0) { /* Terminate */
+ return KNOT_EPARSEFAIL;
+ }
+
+ /* Class must not differ from specified. */
+ if (s->r_class != s->default_class) {
+ char cls_s[16] = {0};
+ knot_rrclass_to_string(s->default_class, cls_s, sizeof(cls_s));
+ ERR("class mismatch: '%s'\n", cls_s);
+ return KNOT_EPARSEFAIL;
+ }
+
+ return KNOT_EOK;
+}
+
+static int parse_partial_rr(scanner_t *s, const char *lp, unsigned flags) {
+ int ret = KNOT_EOK;
+ char b1[32], b2[32]; /* Should suffice for both class/type */
+
+ /* Extract owner. */
+ size_t len = strcspn(lp, SEP_CHARS);
+ knot_dname_t *owner = knot_dname_new_from_str(lp, len, NULL);
+ if (owner == NULL) {
+ return KNOT_EPARSEFAIL;
+ }
+
+ /* ISC nsupdate doesn't do this, but it seems right to me. */
+ if (!knot_dname_is_fqdn(owner)) {
+ knot_dname_t* suf = knot_dname_new_from_wire(s->zone_origin,
+ s->zone_origin_length,
+ NULL);
+ if (suf == NULL) {
+ knot_dname_free(&owner);
+ return KNOT_ENOMEM;
+ }
+ knot_dname_cat(owner, suf);
+ knot_dname_free(&suf);
+ }
+
+ s->r_owner_length = knot_dname_size(owner);
+ memcpy(s->r_owner, knot_dname_name(owner), s->r_owner_length);
+ lp = tok_skipspace(lp + len);
+
+ /* Initialize */
+ s->r_type = KNOT_RRTYPE_ANY;
+ s->r_class = s->default_class;
+ s->r_data_length = 0;
+ if (flags & PARSE_NODEFAULT) {
+ s->r_ttl = 0;
+ } else {
+ s->r_ttl = s->default_ttl;
+ }
+
+ /* Parse only name? */
+ if (flags & PARSE_NAMEONLY) {
+ knot_dname_free(&owner);
+ return KNOT_EOK;
+ }
+
+ /* Now there could be [ttl] [class] [type [data...]]. */
+ /*! \todo support for fancy time format in ttl */
+ char *np = NULL;
+ long ttl = strtol(lp, &np, 10);
+ if (ttl >= 0 && np && (*np == '\0' || isspace((unsigned char)(*np)))) {
+ s->r_ttl = ttl;
+ DBG("%s: parsed ttl=%lu\n", __func__, ttl);
+ lp = tok_skipspace(np);
+ }
+
+ len = strcspn(lp, SEP_CHARS); /* Try to find class */
+ memset(b1, 0, sizeof(b1));
+ strncpy(b1, lp, len < sizeof(b1) ? len : sizeof(b1));
+
+ uint16_t v;
+ if (knot_rrclass_from_string(b1, &v) == 0) {
+ s->r_class = v;
+ DBG("%s: parsed class=%u\n", __func__, s->r_class);
+ lp = tok_skipspace(lp + len);
+ }
+
+ /* Class must not differ from specified. */
+ if (s->r_class != s->default_class) {
+ char cls_s[16] = {0};
+ knot_rrclass_to_string(s->default_class, cls_s, sizeof(cls_s));
+ ERR("class mismatch: '%s'\n", cls_s);
+ knot_dname_free(&owner);
+ return KNOT_EPARSEFAIL;
+ }
+
+ len = strcspn(lp, SEP_CHARS); /* Type */
+ memset(b2, 0, sizeof(b2));
+ strncpy(b2, lp, len < sizeof(b2) ? len : sizeof(b2));
+ if (knot_rrtype_from_string(b2, &v) == 0) {
+ s->r_type = v;
+ DBG("%s: parsed type=%u '%s'\n", __func__, s->r_type, b2);
+ lp = tok_skipspace(lp + len);
+ }
+
+ /* Remainder */
+ if (*lp == '\0') {
+ knot_dname_free(&owner);
+ return ret; /* No RDATA */
+ }
+
+ /* Synthetize full RR line to prevent consistency errors. */
+ char *owner_s = knot_dname_to_str(owner);
+ knot_rrclass_to_string(s->r_class, b1, sizeof(b1));
+ knot_rrtype_to_string(s->r_type, b2, sizeof(b2));
+
+ /* Need to parse rdata, synthetize input. */
+ char *rr = sprintf_alloc("%s %u %s %s %s\n",
+ owner_s, s->r_ttl, b1, b2, lp);
+ if (scanner_process(rr, rr + strlen(rr), 1, s) < 0) {
+ ret = KNOT_EPARSEFAIL;
+ }
+
+ free(owner_s);
+ free(rr);
+ knot_dname_free(&owner);
+ return ret;
+}
+
+static server_t *parse_host(const char *lp, const char* default_port)
+{
+ /* Extract server address. */
+ server_t *srv = NULL;
+ size_t len = strcspn(lp, SEP_CHARS);
+ char *addr = strndup(lp, len);
+ if (!addr) return NULL;
+ DBG("%s: parsed addr: %s\n", __func__, addr);
+
+ /* Store port/service if present. */
+ lp = tok_skipspace(lp + len);
+ if (*lp == '\0') {
+ srv = server_create(addr, default_port);
+ free(addr);
+ return srv;
+ }
+
+ len = strcspn(lp, SEP_CHARS);
+ char *port = strndup(lp, len);
+ if (!port) {
+ free(addr);
+ return NULL;
+ }
+ DBG("%s: parsed port: %s\n", __func__, port);
+
+ /* Create server struct. */
+ srv = server_create(addr, port);
+ free(addr);
+ free(port);
+ return srv;
+}
+
+static int pkt_append(nsupdate_params_t *p, int sect)
+{
+ /* Check packet state first. */
+ int ret = KNOT_EOK;
+ scanner_t *s = p->rrp;
+ if (!p->pkt) {
+ p->pkt = create_empty_packet(KNOT_PACKET_PREALLOC_RESPONSE,
+ MAX_PACKET_SIZE);
+ knot_question_t q;
+ q.qclass = p->class_num;
+ q.qtype = p->type_num;
+ q.qname = knot_dname_new_from_nonfqdn_str(p->zone, strlen(p->zone), NULL);
+ ret = knot_query_set_question(p->pkt, &q);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+ knot_query_set_opcode(p->pkt, KNOT_OPCODE_UPDATE);
+ }
+
+ /* Form a rrset. */
+ knot_dname_t *o = knot_dname_new_from_wire(s->r_owner, s->r_owner_length, NULL);
+ if (!o) {
+ DBG("%s: failed to create dname - %s\n",
+ __func__, knot_strerror(ret));
+ return KNOT_ENOMEM;
+ }
+ knot_rrset_t *rr = knot_rrset_new(o, s->r_type, s->r_class, s->r_ttl);
+ knot_dname_release(o);
+ if (!rr) {
+ DBG("%s: failed to create rrset - %s\n",
+ __func__, knot_strerror(ret));
+ return KNOT_ENOMEM;
+ }
+
+ /* Create RDATA (not for NXRRSET prereq). */
+ if (s->r_data_length > 0 && sect != PQ_NXRRSET) {
+ size_t pos = 0;
+ ret = knot_rrset_rdata_from_wire_one(rr, s->r_data, &pos,
+ s->r_data_length,
+ s->r_data_length);
+ if (ret != KNOT_EOK) {
+ DBG("%s: failed to set rrset from wire - %s\n",
+ __func__, knot_strerror(ret));
+ knot_rrset_free(&rr);
+ return ret;
+ }
+ }
+
+ /* Add to correct section.
+ * ZONES ... QD section.
+ * UPDATE ... NS section.
+ * PREREQ ... AN section.
+ * ADDIT. ... same.
+ */
+ switch(sect) {
+ case UP_ADD:
+ case UP_DEL:
+ ret = knot_response_add_rrset_authority(p->pkt, rr, 0, 0, 0);
+ break;
+ case PQ_NXDOMAIN:
+ case PQ_NXRRSET:
+ case PQ_YXDOMAIN:
+ case PQ_YXRRSET:
+ ret = knot_response_add_rrset_answer(p->pkt, rr, 0, 0, 0);
+ break;
+ default:
+ assert(0); /* Should never happen. */
+ break;
+ }
+
+ if (ret != KNOT_EOK) {
+ DBG("%s: failed to append rdata to appropriate section - %s\n",
+ __func__, knot_strerror(ret));
+ if (ret == KNOT_ESPACE) {
+ ERR("exceeded UPDATE message maximum size %zu\n",
+ knot_packet_max_size(p->pkt));
+ }
+ }
+
+ return ret;
+}
+
+static int pkt_sendrecv(nsupdate_params_t *params,
+ uint8_t *qwire, size_t qlen,
+ uint8_t *rwire, size_t rlen)
+{
+ net_t net;
+ int ret;
+
+ ret = net_init(params->srcif,
+ params->server,
+ get_iptype(params->ip),
+ get_socktype(params->protocol, KNOT_RRTYPE_SOA),
+ params->wait,
+ &net);
+
+ ret = net_connect(&net);
+ DBG("%s: send_msg = %d\n", __func__, net.sockfd);
+ if (ret != KNOT_EOK) return -1;
+
+ ret = net_send(&net, qwire, qlen);
+ if (ret != KNOT_EOK) {
+ net_close(&net);
+ net_clean(&net);
+ return -1;
+ }
+
+ /* Wait for reception. */
+ int rb = net_receive(&net, rwire, rlen);
+ DBG("%s: receive_msg = %d\n", __func__, rb);
+ if (rb <= 0) {
+ net_close(&net);
+ net_clean(&net);
+ return -1;
+ }
+
+ net_close(&net);
+ net_clean(&net);
+
+ return rb;
+}
+
+static int nsupdate_process_line(char *lp, int len, void *arg)
+{
+ nsupdate_params_t *params = (nsupdate_params_t *)arg;
+
+ /* Remove trailing white space chars. */
+ for (int i = len - 1; i >= 0; i--) {
+ if (isspace((unsigned char)lp[i]) == 0) {
+ break;
+ }
+ lp[i] = '\0';
+ }
+
+ /* Check for empty line or comment. */
+ if (lp[0] == '\0' || lp[0] == ';') {
+ return KNOT_EOK;
+ }
+
+ int ret = tok_find(lp, cmd_array);
+ if (ret < 0) {
+ return KNOT_EOK; /* Syntax error - do nothing. */
+ }
+
+ const char *cmd = cmd_array[ret];
+ const char *val = tok_skipspace(lp + TOK_L(cmd));
+ ret = cmd_handle[ret](val, params);
+ if (ret != KNOT_EOK) {
+ DBG("operation '%s' failed (%s)\n",
+ TOK_S(cmd), knot_strerror(ret));
+ }
+
+ return KNOT_EOK;
+}
+
+static int nsupdate_process(nsupdate_params_t *params, FILE *fp)
+{
+ /* Process lines. */
+ int ret = tok_process_lines(fp, nsupdate_process_line, params);
+
+ /* Check for longing query. */
+ if (params->pkt && ret == KNOT_EOK) {
+ cmd_send("", params);
+ }
+
+ /* Free last answer. */
+ if (params->resp) {
+ knot_packet_free(&params->resp);
+ }
+
+ return ret;
+}
+
+int nsupdate_exec(nsupdate_params_t *params)
+{
+ if (!params) {
+ return KNOT_EINVAL;
+ }
+
+ int ret = KNOT_EOK;
+
+ /* If not file specified, use stdin. */
+ if (EMPTY_LIST(params->qfiles)) {
+ return nsupdate_process(params, stdin);
+ }
+
+ /* Read from each specified file. */
+ strnode_t *n = NULL;
+ WALK_LIST(n, params->qfiles) {
+ if (strcmp(n->str, "-") == 0) {
+ ret = nsupdate_process(params, stdin);
+ continue;
+ }
+ FILE *fp = fopen(n->str, "r");
+ if (!fp) {
+ ERR("could not open '%s': %s\n",
+ n->str, strerror(errno));
+ return KNOT_ERROR;
+ }
+ ret = nsupdate_process(params, fp);
+ fclose(fp);
+ }
+
+ return ret;
+}
+
+int cmd_update(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* update is optional token, next add|del|delete */
+ int bp = tok_find(lp, cmd_array);
+ if (bp < 0) return bp; /* Syntax error. */
+
+ /* allow only specific tokens */
+ cmd_handle_f *h = cmd_handle;
+ if (h[bp] != cmd_add && h[bp] != cmd_del) {
+ ERR("unexpected token '%s' after 'update', allowed: '%s'\n",
+ lp, "{add|del|delete}");
+ return KNOT_EPARSEFAIL;
+ }
+
+ return h[bp](tok_skipspace(lp + TOK_L(cmd_array[bp])), params);
+}
+
+
+int cmd_add(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ scanner_t *rrp = params->rrp;
+ if (parse_full_rr(rrp, lp) != KNOT_EOK) {
+ return KNOT_EPARSEFAIL;
+ }
+
+ /* Parsed RR */
+ DBG("%s: parsed rr cls=%u, ttl=%u, type=%u (rdata len=%u)\n",
+ __func__, rrp->r_class, rrp->r_ttl,rrp->r_type, rrp->r_data_length);
+
+ return pkt_append(params, UP_ADD); /* Append to packet. */
+}
+
+int cmd_del(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ scanner_t *rrp = params->rrp;
+ if (parse_partial_rr(rrp, lp, PARSE_NODEFAULT) != KNOT_EOK) {
+ return KNOT_EPARSEFAIL;
+ }
+
+ /* Check owner name. */
+ if (rrp->r_owner_length == 0) {
+ ERR("failed to parse prereq owner name '%s'\n", lp);
+ return KNOT_EPARSEFAIL;
+ }
+
+ rrp->r_ttl = 0; /* Set TTL = 0 when deleting. */
+
+ /* When deleting whole RRSet, use ANY class */
+ if (rrp->r_data_length == 0) {
+ rrp->r_class = KNOT_CLASS_ANY;
+ } else {
+ rrp->r_class = KNOT_CLASS_NONE;
+ }
+
+ /* Parsed RR */
+ DBG("%s: parsed rr cls=%u, ttl=%u, type=%u (rdata len=%u)\n",
+ __func__, rrp->r_class, rrp->r_ttl,rrp->r_type, rrp->r_data_length);
+
+ return pkt_append(params, UP_DEL); /* Append to packet. */
+}
+
+int cmd_class(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ uint16_t cls;
+
+ if (knot_rrclass_from_string(lp, &cls) != 0) {
+ ERR("failed to parse class '%s'\n", lp);
+ return KNOT_EPARSEFAIL;
+ } else {
+ params->class_num = cls;
+ scanner_t *s = params->rrp;
+ s->default_class = params->class_num;
+ }
+
+ return KNOT_EOK;
+}
+
+int cmd_ttl(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ uint32_t ttl = 0;
+
+ if (params_parse_num(lp, &ttl) != KNOT_EOK) {
+ return KNOT_EPARSEFAIL;
+ }
+
+ return nsupdate_set_ttl(params, ttl);
+}
+
+int cmd_debug(const char* lp, nsupdate_params_t *params)
+{
+ UNUSED(params);
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ msg_enable_debug(1);
+ return KNOT_EOK;
+}
+
+int cmd_prereq_domain(const char *lp, nsupdate_params_t *params, unsigned type)
+{
+ UNUSED(type);
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ scanner_t *s = params->rrp;
+ int ret = parse_partial_rr(s, lp, PARSE_NODEFAULT|PARSE_NAMEONLY);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ return ret;
+}
+
+int cmd_prereq_rrset(const char *lp, nsupdate_params_t *params, unsigned type)
+{
+ UNUSED(type);
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ scanner_t *rrp = params->rrp;
+ if (parse_partial_rr(rrp, lp, 0) != KNOT_EOK) {
+ return KNOT_EPARSEFAIL;
+ }
+
+ /* Check owner name. */
+ if (rrp->r_owner_length == 0) {
+ ERR("failed to parse prereq owner name '%s'\n", lp);
+ return KNOT_EPARSEFAIL;
+ }
+
+ /* Parsed RR */
+ DBG("%s: parsed rr cls=%u, ttl=%u, type=%u (rdata len=%u)\n",
+ __func__, rrp->r_class, rrp->r_ttl,rrp->r_type, rrp->r_data_length);
+
+ return KNOT_EOK;
+}
+
+int cmd_prereq(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* Scan prereq specifier ([ny]xrrset|[ny]xdomain) */
+ int ret = KNOT_EOK;
+ int bp = tok_find(lp, pq_array);
+ if (bp < 0) return bp; /* Syntax error. */
+
+ const char *tok = pq_array[bp];
+ DBG("%s: type %s\n", __func__, TOK_S(tok));
+ lp = tok_skipspace(lp + TOK_L(tok));
+ switch(bp) {
+ case PQ_NXDOMAIN:
+ case PQ_YXDOMAIN:
+ ret = cmd_prereq_domain(lp, params, bp);
+ break;
+ case PQ_NXRRSET:
+ case PQ_YXRRSET:
+ ret = cmd_prereq_rrset(lp, params, bp);
+ break;
+ default:
+ return KNOT_ERROR;
+ }
+
+ /* Append to packet. */
+ if (ret == KNOT_EOK) {
+ scanner_t *s = params->rrp;
+ s->r_ttl = 0; /* Set TTL = 0 for prereq. */
+ /* YX{RRSET,DOMAIN} - cls ANY */
+ if (bp == PQ_YXRRSET || bp == PQ_YXDOMAIN) {
+ s->r_class = KNOT_CLASS_ANY;
+ } else { /* NX{RRSET,DOMAIN} - cls NONE */
+ s->r_class = KNOT_CLASS_NONE;
+ }
+
+ ret = pkt_append(params, bp);
+ }
+
+ return ret;
+}
+
+int cmd_send(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+ DBG("sending packet\n");
+
+ /* Create wireformat. */
+ int ret = KNOT_EOK;
+ uint8_t *wire = NULL;
+ size_t len = 0;
+
+ if ((ret = knot_packet_to_wire(params->pkt, &wire, &len))!= KNOT_EOK) {
+ ERR("couldn't serialize packet, %s\n", knot_strerror(ret));
+ return ret;
+ }
+
+ sign_context_t sign_ctx;
+ memset(&sign_ctx, '\0', sizeof(sign_context_t));
+
+ /* Sign if key specified. */
+ if (params->key_params.name) {
+ ret = sign_packet(params->pkt, &sign_ctx, &params->key_params);
+ if (ret != KNOT_EOK) {
+ ERR("failed to sign UPDATE message - %s\n",
+ knot_strerror(ret));
+ return ret;
+ }
+ len = params->pkt->size;
+ }
+
+ int rb = 0;
+ /* Send/recv message (1 try + N retries). */
+ int tries = 1 + params->retries;
+ for (; tries > 0; --tries) {
+ memset(params->rwire, 0, sizeof(params->rwire));
+ rb = pkt_sendrecv(params, wire, len,
+ params->rwire, sizeof(params->rwire));
+ if (rb > 0) break;
+ }
+
+ /* Clear sent packet. */
+ knot_question_t *q = knot_packet_question(params->pkt);
+ knot_dname_release(q->qname);
+ knot_packet_free_rrsets(params->pkt);
+ knot_packet_free(&params->pkt);
+
+ /* Clear previous response. */
+ if (params->resp) {
+ knot_packet_free(&params->resp);
+ }
+
+ /* Check Send/recv result. */
+ if (rb <= 0) {
+ free_sign_context(&sign_ctx);
+ return KNOT_ECONNREFUSED;
+ }
+
+ /* Parse response. */
+ params->resp = knot_packet_new(KNOT_PACKET_PREALLOC_NONE);
+ if (!params->resp) {
+ free_sign_context(&sign_ctx);
+ return KNOT_ENOMEM;
+ }
+ ret = knot_packet_parse_from_wire(params->resp, params->rwire, rb, 0, 0);
+ if (ret != KNOT_EOK) {
+ ERR("failed to parse response, %s\n", knot_strerror(ret));
+ free_sign_context(&sign_ctx);
+ return ret;
+ }
+
+ /* Check signature if expected. */
+ if (params->key_params.name) {
+ ret = verify_packet(params->resp, &sign_ctx, &params->key_params);
+ free_sign_context(&sign_ctx);
+ if (ret != KNOT_EOK) { /* Collect TSIG error. */
+ fprintf(stderr, "%s: %s\n", "; TSIG error with server",
+ knot_strerror(ret));
+ return ret;
+ }
+ }
+
+ /* Check return code. */
+ knot_lookup_table_t *rcode;
+ int rc = knot_packet_rcode(params->resp);
+ DBG("%s: received rcode=%d\n", __func__, rc);
+ rcode = knot_lookup_by_id(knot_rcode_names, rc);
+ if (rcode && rcode->id > KNOT_RCODE_NOERROR) {
+ ERR("update failed: %s\n", rcode->name);
+ }
+
+ /*! \todo Should we check TC bit? */
+
+ return KNOT_EOK;
+}
+
+int cmd_zone(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* Check zone name. */
+ size_t len = strcspn(lp, SEP_CHARS);
+ if (!dname_isvalid(lp, len)) {
+ ERR("failed to parse zone '%s'\n", lp);
+ return KNOT_EPARSEFAIL;
+ }
+
+ free(params->zone);
+ params->zone = strndup(lp, len);
+
+ return KNOT_EOK;
+}
+
+int cmd_server(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* Parse host. */
+ server_t *srv = parse_host(lp, params->server->service);
+
+ /* Enqueue. */
+ if (!srv) return KNOT_ENOMEM;
+
+ server_free(params->server);
+ params->server = srv;
+
+ return KNOT_EOK;
+}
+
+int cmd_local(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* Parse host. */
+ server_t *srv = parse_host(lp, "0");
+
+ /* Enqueue. */
+ if (!srv) return KNOT_ENOMEM;
+
+ server_free(params->srcif);
+ params->srcif = srv;
+
+ return KNOT_EOK;
+}
+
+int cmd_show(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* Show current packet. */
+ if (!params->pkt) return KNOT_EOK;
+ printf("Outgoing update query:\n");
+ size_t len = knot_packet_size(params->pkt);
+ print_packet(params->pkt, len, NULL, -1, false, &params->style);
+ return KNOT_EOK;
+}
+
+int cmd_answer(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* Show current answer. */
+ if (!params->resp) return KNOT_EOK;
+ printf("\nAnswer:\n");
+ size_t len = knot_packet_size(params->resp);
+ print_packet(params->resp, len, NULL, -1, true, &params->style);
+ return KNOT_EOK;
+}
+
+int cmd_key(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ char *kstr = strdup(lp); /* Convert to default format. */
+ if (!kstr) return KNOT_ENOMEM;
+
+ int ret = KNOT_EOK;
+ size_t len = strcspn(lp, SEP_CHARS);
+ if(kstr[len] == '\0') {
+ ERR("command 'key' without {secret} specified\n");
+ ret = KNOT_EINVAL;
+ } else {
+ // override existing key
+ knot_free_key_params(&params->key_params);
+
+ kstr[len] = ':'; /* Replace ' ' with ':' sep */
+ ret = params_parse_tsig(kstr, &params->key_params);
+ }
+
+ free(kstr);
+ return ret;
+}
+
+/*
+ * Not implemented.
+ */
+
+int cmd_gsstsig(const char* lp, nsupdate_params_t *params)
+{
+ UNUSED(params);
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ return KNOT_ENOTSUP;
+}
+
+int cmd_oldgsstsig(const char* lp, nsupdate_params_t *params)
+{
+ UNUSED(params);
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ return KNOT_ENOTSUP;
+}
+
+int cmd_origin(const char* lp, nsupdate_params_t *params)
+{
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ /* Check zone name. */
+ size_t len = strcspn(lp, SEP_CHARS);
+ if (!dname_isvalid(lp, len)) {
+ ERR("failed to parse zone '%s'\n", lp);
+ return KNOT_EPARSEFAIL;
+ }
+
+ char *name = strndup(lp, len);
+
+ int ret = nsupdate_set_origin(params, name);
+
+ free(name);
+
+ return ret;
+}
+
+int cmd_realm(const char* lp, nsupdate_params_t *params)
+{
+ UNUSED(params);
+ DBG("%s: lp='%s'\n", __func__, lp);
+
+ return KNOT_ENOTSUP;
+}
diff --git a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.h b/src/utils/nsupdate/nsupdate_exec.h
index cc3b705..439a416 100644
--- a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.h
+++ b/src/utils/nsupdate/nsupdate_exec.h
@@ -1,13 +1,3 @@
-/*!
- * \file rrset_tests.h
- *
- * \author Jan Kadlec <jan.kadlec@nic.cz>
- *
- * Contains unit tests for RRSet (knot_rrset_t) and its API.
- *
- * Contains tests for:
- * -
- */
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
@@ -22,14 +12,25 @@
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 nsupdate_exec.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief
+ *
+ * \addtogroup knot_utils
+ * @{
*/
-#ifndef _KNOTD_RRSET_TESTS_H_
-#define _KNOTD_RRSET_TESTS_H_
+#ifndef _NSUPDATE__NSUPDATE_EXEC_H_
+#define _NSUPDATE__NSUPDATE_EXEC_H_
+
+#include "utils/nsupdate/nsupdate_params.h" // nsupdate_params_t
-#include "common/libtap/tap_unit.h"
+int nsupdate_exec(nsupdate_params_t *params);
-/* Unit API. */
-unit_api rrset_tests_api;
+#endif // _NSUPDATE__NSUPDATE_EXEC_H_
-#endif /* _KNOTD_RRSET_TESTS_H_ */
+/*! @} */
diff --git a/src/utils/nsupdate/nsupdate_main.c b/src/utils/nsupdate/nsupdate_main.c
new file mode 100644
index 0000000..baf2b19
--- /dev/null
+++ b/src/utils/nsupdate/nsupdate_main.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <stdlib.h> // EXIT_FAILURE
+
+#include "common/errcode.h" // KNOT_EOK
+#include "utils/nsupdate/nsupdate_params.h" // params_t
+#include "utils/nsupdate/nsupdate_exec.h" // host_exec
+
+int main(int argc, char *argv[])
+{
+ int ret = EXIT_SUCCESS;
+
+ nsupdate_params_t params;
+ if (nsupdate_parse(&params, argc, argv) == KNOT_EOK) {
+ if (!params.stop && nsupdate_exec(&params) != KNOT_EOK) {
+ ret = EXIT_FAILURE;
+ }
+ } else {
+ ret = EXIT_FAILURE;
+ }
+
+ nsupdate_clean(&params);
+ return ret;
+}
diff --git a/src/utils/nsupdate/nsupdate_params.c b/src/utils/nsupdate/nsupdate_params.c
new file mode 100644
index 0000000..4d1f054
--- /dev/null
+++ b/src/utils/nsupdate/nsupdate_params.c
@@ -0,0 +1,267 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <string.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "utils/nsupdate/nsupdate_params.h"
+#include "utils/common/msg.h"
+#include "utils/common/netio.h"
+#include "common/errcode.h"
+#include "common/descriptor.h"
+#include "libknot/libknot.h"
+
+#define DEFAULT_RETRIES_NSUPDATE 3
+#define DEFAULT_TIMEOUT_NSUPDATE 12
+
+static const style_t DEFAULT_STYLE_NSUPDATE = {
+ .format = FORMAT_NSUPDATE,
+ .style = { .wrap = false, .show_class = true, .show_ttl = true,
+ .verbose = false, .reduce = false, .human_ttl = false,
+ .human_tmstamp = true },
+ .show_query = false,
+ .show_header = true,
+ .show_edns = false,
+ .show_question = true,
+ .show_answer = true,
+ .show_authority = true,
+ .show_additional = true,
+ .show_footer = false,
+};
+
+static void parse_rr(const scanner_t *s)
+{
+ UNUSED(s);
+}
+
+static void parse_err(const scanner_t *s) {
+ ERR("failed to parse RR, %s\n", knot_strerror(s->error_code));
+}
+
+static int parser_set_default(scanner_t *s, const char *fmt, ...)
+{
+ /* Format string. */
+ char buf[512]; /* Must suffice for domain name and TTL. */
+ va_list ap;
+ va_start(ap, fmt);
+ int n = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+
+ if (n < 0 || (size_t)n >= sizeof(buf)) {
+ return KNOT_ESPACE;
+ }
+
+ /* fmt must contain newline */
+ if (scanner_process(buf, buf + n, 0, s) < 0) {
+ return KNOT_EPARSEFAIL;
+ }
+
+ return KNOT_EOK;
+}
+
+static int nsupdate_init(nsupdate_params_t *params)
+{
+ memset(params, 0, sizeof(nsupdate_params_t));
+
+ params->stop = false;
+
+ /* Initialize list. */
+ init_list(&params->qfiles);
+
+ /* Default server. */
+ params->server = server_create(DEFAULT_IPV4_NAME, DEFAULT_DNS_PORT);
+ if (!params->server) return KNOT_ENOMEM;
+
+ /* Default settings. */
+ params->ip = IP_ALL;
+ params->protocol = PROTO_ALL;
+ params->retries = DEFAULT_RETRIES_NSUPDATE;
+ params->wait = DEFAULT_TIMEOUT_NSUPDATE;
+ params->class_num = KNOT_CLASS_IN;
+ params->type_num = KNOT_RRTYPE_SOA;
+
+ /* Default style. */
+ params->style = DEFAULT_STYLE_NSUPDATE;
+
+ /* Initialize RR parser. */
+ params->rrp = scanner_create(".");
+ if (!params->rrp) return KNOT_ENOMEM;
+ params->rrp->process_record = parse_rr;
+ params->rrp->process_error = parse_err;
+ params->rrp->default_class = params->class_num;
+ params->zone = strdup(".");
+ nsupdate_set_ttl(params, 0);
+ nsupdate_set_origin(params, ".");
+
+ return KNOT_EOK;
+}
+
+void nsupdate_clean(nsupdate_params_t *params)
+{
+ strnode_t *n = NULL, *nxt = NULL;
+
+ if (params == NULL) {
+ return;
+ }
+
+ server_free(params->server);
+ server_free(params->srcif);
+ free(params->zone);
+ scanner_free(params->rrp);
+ knot_packet_free(&params->pkt);
+ knot_packet_free(&params->resp);
+
+ /* Free qfiles. */
+ WALK_LIST_DELSAFE(n, nxt, params->qfiles) {
+ free(n);
+ }
+
+ knot_free_key_params(&params->key_params);
+
+ /* Clean up the structure. */
+ memset(params, 0, sizeof(*params));
+}
+
+static void nsupdate_help(void)
+{
+ printf("Usage: knsupdate [-d] [-v] [-k keyfile | -y [hmac:]name:key]\n"
+ " [-p port] [-t timeout] [-r retries] [filename]\n");
+}
+
+int nsupdate_parse(nsupdate_params_t *params, int argc, char *argv[])
+{
+ int opt = 0, li = 0;
+ int ret = KNOT_EOK;
+
+ if (params == NULL || argv == NULL) {
+ return KNOT_EINVAL;
+ }
+
+ ret = nsupdate_init(params);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ // Long options.
+ struct option opts[] = {
+ { "version", no_argument, 0, 'V' },
+ { "help", no_argument, 0, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ /* Command line options processing. */
+ while ((opt = getopt_long(argc, argv, "dhDvVp:t:r:y:k:", opts, &li))
+ != -1) {
+ switch (opt) {
+ case 'd':
+ case 'D': /* Extra debugging. */
+ msg_enable_debug(1);
+ break;
+ case 'h':
+ nsupdate_help();
+ params->stop = true;
+ return KNOT_EOK;
+ case 'v':
+ params->protocol = PROTO_TCP;
+ break;
+ case 'V':
+ printf(KNSUPDATE_VERSION);
+ params->stop = true;
+ return KNOT_EOK;
+ case 'p':
+ free(params->server->service);
+ params->server->service = strdup(optarg);
+ if (!params->server->service) {
+ ERR("failed to set default port '%s'\n", optarg);
+ return KNOT_ENOMEM;
+ }
+ break;
+ case 'r':
+ ret = params_parse_num(optarg, &params->retries);
+ if (ret != KNOT_EOK) return ret;
+ break;
+ case 't':
+ ret = params_parse_wait(optarg, &params->wait);
+ if (ret != KNOT_EOK) return ret;
+ break;
+ case 'y':
+ ret = params_parse_tsig(optarg, &params->key_params);
+ if (ret != KNOT_EOK) return ret;
+ break;
+ case 'k':
+ ret = params_parse_keyfile(optarg, &params->key_params);
+ if (ret != KNOT_EOK) return ret;
+ break;
+ default:
+ nsupdate_help();
+ return KNOT_ENOTSUP;
+ }
+ }
+
+ /* No retries for TCP. */
+ if (params->protocol == PROTO_TCP) {
+ params->retries = 0;
+ } else {
+ /* If wait/tries < 1 s, set 1 second for each try. */
+ if (params->wait > 0 &&
+ (uint32_t)params->wait < ( 1 + params->retries)) {
+ params->wait = 1;
+ } else {
+ params->wait /= (1 + params->retries);
+ }
+ }
+
+ /* Process non-option parameters. */
+ for (; optind < argc; ++optind) {
+ strnode_t *n = malloc(sizeof(strnode_t));
+ if (!n) { /* Params will be cleaned on exit. */
+ return KNOT_ENOMEM;
+ }
+ n->str = argv[optind];
+ add_tail(&params->qfiles, &n->n);
+ }
+
+ return ret;
+}
+
+int nsupdate_set_ttl(nsupdate_params_t *params, const uint32_t ttl)
+{
+ int ret = parser_set_default(params->rrp, "$TTL %u\n", ttl);
+ if (ret == KNOT_EOK) {
+ params->ttl = ttl;
+ } else {
+ ERR("failed to set default TTL, %s\n", knot_strerror(ret));
+ }
+ return ret;
+}
+
+int nsupdate_set_origin(nsupdate_params_t *params, const char *origin)
+{
+ char *fqdn = get_fqd_name(origin);
+
+ int ret = parser_set_default(params->rrp, "$ORIGIN %s\n", fqdn);
+
+ free(fqdn);
+
+ if (ret != KNOT_EOK) {
+ ERR("failed to set default origin, %s\n", knot_strerror(ret));
+ }
+ return ret;
+}
diff --git a/src/utils/nsupdate/nsupdate_params.h b/src/utils/nsupdate/nsupdate_params.h
new file mode 100644
index 0000000..7fcb98a
--- /dev/null
+++ b/src/utils/nsupdate/nsupdate_params.h
@@ -0,0 +1,91 @@
+/* Copyright (C) 2011 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 nsupdate_params.h
+ *
+ * \author Marek Vavrusa <marek.vavrusa@nic.cz>
+ *
+ * \brief nsupdate command line parameters.
+ *
+ * \addtogroup knot_utils
+ * @{
+ */
+
+#ifndef _NSUPDATE__NSUPDATE_PARAMS_H_
+#define _NSUPDATE__NSUPDATE_PARAMS_H_
+
+#include <stdint.h>
+
+#include "libknot/libknot.h"
+#include "common/lists.h" // list
+#include "zscanner/scanner.h" // scanner_t
+#include "utils/common/netio.h" // server_t
+#include "utils/common/params.h" // protocol_t
+#include "libknot/sign/key.h" // knot_key_params_t
+
+#define KNSUPDATE_VERSION "knsupdate, version " PACKAGE_VERSION "\n"
+
+/*! Parser init string. */
+#define PARSER_INIT_STR "$ORIGIN %s\n$TTL %u\n"
+
+/*! \brief nsupdate-specific params data. */
+typedef struct {
+ /*!< Stop processing - just pring help, version,... */
+ bool stop;
+ /*!< List of files with query data. */
+ list qfiles;
+ /*!< List of nameservers to query to. */
+ server_t *server;
+ /*!< Local interface (optional). */
+ server_t *srcif;
+ /*!< Operation mode. */
+ ip_t ip;
+ /*!< Type (TCP, UDP) protocol to use. */
+ protocol_t protocol;
+ /*!< Default class number. */
+ uint16_t class_num;
+ /*!< Default type number. */
+ uint16_t type_num;
+ /*!< Default TTL. */
+ uint32_t ttl;
+ /*!< Number of UDP retries. */
+ uint32_t retries;
+ /*!< Wait for network response in seconds (-1 means forever). */
+ int32_t wait;
+ /*!< Current zone. */
+ char *zone;
+ /*!< RR parser. */
+ scanner_t *rrp;
+ /*!< Current packet. */
+ knot_packet_t *pkt;
+ /*!< Current response. */
+ knot_packet_t *resp;
+ /*!< Buffer for response. */
+ uint8_t rwire[MAX_PACKET_SIZE];
+ /*!< Key parameters. */
+ knot_key_params_t key_params;
+ /*!< Default output settings. */
+ style_t style;
+} nsupdate_params_t;
+
+int nsupdate_parse(nsupdate_params_t *params, int argc, char *argv[]);
+int nsupdate_set_ttl(nsupdate_params_t *params, const uint32_t ttl);
+int nsupdate_set_origin(nsupdate_params_t *params, const char *origin);
+void nsupdate_clean(nsupdate_params_t *params);
+
+#endif // _NSUPDATE__NSUPDATE_PARAMS_H_
+
+/*! @} */
diff --git a/src/zcompile/LICENSE b/src/zcompile/LICENSE
deleted file mode 100644
index 55faacf..0000000
--- a/src/zcompile/LICENSE
+++ /dev/null
@@ -1,30 +0,0 @@
-Copyright (c) 2001-2006, 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 REGENTS OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/zcompile/parser-descriptor.c b/src/zcompile/parser-descriptor.c
deleted file mode 100644
index 466beb4..0000000
--- a/src/zcompile/parser-descriptor.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*!
- * \file parser-descriptor.c
- *
- * \author Modifications by Jan Kadlec <jan.kadlec@nic.cz>,
- * most of the work by NLnet Labs.
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \brief Contains resource record descriptor and its API
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
-#include <string.h>
-#include <sys/types.h>
-
-//#include "common.h"
-#include "zcompile/parser-descriptor.h"
-/* TODO this has to be removed - move tokens to separate file
- but can it be done?) */
-#include "zcompile/zcompile.h"
-/* FIXME: Generate .y and .l to zoneparser/ */
-#include "zparser.h"
-
-enum desclen { PARSER_RRTYPE_DESCRIPTORS_LENGTH = 65536 }; // used to be 101
-
-/* Taken from RFC 1035, section 3.2.4. */
-static knot_lookup_table_t dns_rrclasses[] = {
- { PARSER_CLASS_IN, "IN" }, /* the Internet */
- { PARSER_CLASS_CS, "CS" }, /* the CSNET class (Obsolete) */
- { PARSER_CLASS_CH, "CH" }, /* the CHAOS class */
- { PARSER_CLASS_HS, "HS" }, /* Hesiod */
- { 0, NULL }
-};
-static parser_rrtype_descriptor_t
- knot_rrtype_descriptors[PARSER_RRTYPE_DESCRIPTORS_LENGTH] = {
- /* 0 */
- { 0, 0, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 1 */
- { PARSER_RRTYPE_A, T_A, "A", 1, { PARSER_RDATA_WF_A }, true },
- /* 2 */
- { PARSER_RRTYPE_NS, T_NS, "NS", 1,
- { PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 3 */
- { PARSER_RRTYPE_MD, T_MD, "MD", 1,
- { PARSER_RDATA_WF_UNCOMPRESSED_DNAME }, true },
- /* 4 */
- { PARSER_RRTYPE_MF, T_MF, "MF", 1,
- { PARSER_RDATA_WF_UNCOMPRESSED_DNAME }, true },
- /* 5 */
- { PARSER_RRTYPE_CNAME, T_CNAME, "CNAME", 1,
- { PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 6 */
- { PARSER_RRTYPE_SOA, T_SOA, "SOA", 7,
- { PARSER_RDATA_WF_COMPRESSED_DNAME, PARSER_RDATA_WF_COMPRESSED_DNAME,
- PARSER_RDATA_WF_LONG, PARSER_RDATA_WF_LONG, PARSER_RDATA_WF_LONG,
- PARSER_RDATA_WF_LONG, PARSER_RDATA_WF_LONG }, true },
- /* 7 */
- { PARSER_RRTYPE_MB, T_MB, "MB", 1,
- { PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 8 */
- { PARSER_RRTYPE_MG, T_MG, "MG", 1,
- { PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 9 */
- { PARSER_RRTYPE_MR, T_MR, "MR", 1,
- { PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 10 */
- { PARSER_RRTYPE_NULL, T_NULL, NULL, 1,
- { PARSER_RDATA_WF_BINARY }, true },
- /* 11 */
- { PARSER_RRTYPE_WKS, T_WKS, "WKS", 2,
- { PARSER_RDATA_WF_A, PARSER_RDATA_WF_BINARY }, true },
- /* 12 */
- { PARSER_RRTYPE_PTR, T_PTR, "PTR", 1,
- { PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 13 */
- { PARSER_RRTYPE_HINFO, T_HINFO, "HINFO", 2,
- { PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT }, true },
- /* 14 */
- { PARSER_RRTYPE_MINFO, T_MINFO, "MINFO", 2,
- { PARSER_RDATA_WF_COMPRESSED_DNAME,
- PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 15 */
- { PARSER_RRTYPE_MX, T_MX, "MX", 2,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 16 */ /* This is obscure, but I guess there's no other way */
- { PARSER_RRTYPE_TXT, T_TXT, "TXT", PARSER_MAX_RDATA_ITEMS,
- { PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT }, false },
- /* 17 */
- { PARSER_RRTYPE_RP, T_RP, "RP", 2,
- { PARSER_RDATA_WF_COMPRESSED_DNAME,
- PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 18 */
- { PARSER_RRTYPE_AFSDB, T_AFSDB, "AFSDB", 2,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 19 */
- { PARSER_RRTYPE_X25, T_X25, "X25", 1,
- { PARSER_RDATA_WF_TEXT }, true },
- /* 20 */
- { PARSER_RRTYPE_ISDN, T_ISDN, "ISDN", 2,
- { PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT }, false },
- /* 21 */
- { PARSER_RRTYPE_RT, T_RT, "RT", 2,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_COMPRESSED_DNAME }, true },
- /* 22 */
- { PARSER_RRTYPE_NSAP, T_NSAP, "NSAP", 1,
- { PARSER_RDATA_WF_BINARY }, true },
- /* 23 */
- { 23, 0, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 24 */
- { PARSER_RRTYPE_SIG, T_SIG, "SIG", 9,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_LONG, PARSER_RDATA_WF_LONG, PARSER_RDATA_WF_LONG,
- PARSER_RDATA_WF_SHORT,PARSER_RDATA_WF_UNCOMPRESSED_DNAME,
- PARSER_RDATA_WF_BINARY }, true },
- /* 25 */
- { PARSER_RRTYPE_KEY, T_KEY, "KEY", 4,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BINARY }, true },
- /* 26 */
- { PARSER_RRTYPE_PX, T_PX, "PX", 3,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_UNCOMPRESSED_DNAME,
- PARSER_RDATA_WF_UNCOMPRESSED_DNAME }, true },
- /* 27 */
- { 27, 0, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 28 */
- { PARSER_RRTYPE_AAAA, T_AAAA, "AAAA", 1,
- { PARSER_RDATA_WF_AAAA }, true },
- /* 29 */
- { PARSER_RRTYPE_LOC, T_LOC, "LOC", 1,
- { PARSER_RDATA_WF_BINARY }, true },
- /* 30 */
- { PARSER_RRTYPE_NXT, T_NXT, "NXT", 2,
- { PARSER_RDATA_WF_UNCOMPRESSED_DNAME,
- PARSER_RDATA_WF_BINARY }, true },
- /* 31 */
- { 31, 0, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 32 */
- { 32, 0, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 33 */
- { PARSER_RRTYPE_SRV, T_SRV, "SRV", 4,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_SHORT,
- PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_UNCOMPRESSED_DNAME },
- true },
- /* 34 */
- { 34, 0, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 35 */
- { PARSER_RRTYPE_NAPTR, T_NAPTR, "NAPTR", 6,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_UNCOMPRESSED_DNAME }, true },
- /* 36 */
- { PARSER_RRTYPE_KX, T_KX, "KX", 2,
- { PARSER_RDATA_WF_SHORT,
- PARSER_RDATA_WF_UNCOMPRESSED_DNAME }, true },
- /* 37 */
- { PARSER_RRTYPE_CERT, T_CERT, "CERT", 4,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_SHORT,
- PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BINARY }, true },
- /* 38 */
- { PARSER_RRTYPE_A6, T_A6, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 39 */
- { PARSER_RRTYPE_DNAME, T_DNAME, "DNAME", 1,
- { PARSER_RDATA_WF_UNCOMPRESSED_DNAME }, true },
- /* 40 */
- { 40, 0, NULL, 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 41 */
- /* OPT has its parser token, but should never be in zone file... */
- { PARSER_RRTYPE_OPT, T_OPT, "OPT", 1,
- { PARSER_RDATA_WF_BINARY }, true },
- /* 42 */
- { PARSER_RRTYPE_APL, T_APL, "APL", PARSER_MAX_RDATA_ITEMS,
- { PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL,
- PARSER_RDATA_WF_APL, PARSER_RDATA_WF_APL }, false },
- /* 43 */
- { PARSER_RRTYPE_DS, T_DS, "DS", 4,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BINARY }, true },
- /* 44 */
- { PARSER_RRTYPE_SSHFP, T_SSHFP, "SSHFP", 3,
- { PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BINARY }, true },
- /* 45 */
- { PARSER_RRTYPE_IPSECKEY, T_IPSECKEY, "IPSECKEY", 5,
- { PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_IPSECGATEWAY,
- PARSER_RDATA_WF_BINARY }, false },
- /* 46 */
- { PARSER_RRTYPE_RRSIG, T_RRSIG, "RRSIG", 9,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_LONG,
- PARSER_RDATA_WF_LONG, PARSER_RDATA_WF_LONG,
- PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_BINARY,
- PARSER_RDATA_WF_BINARY }, true },
- /* 47 */
- { PARSER_RRTYPE_NSEC, T_NSEC, "NSEC", 2,
- { PARSER_RDATA_WF_BINARY, PARSER_RDATA_WF_BINARY }, true },
- /* 48 */
- { PARSER_RRTYPE_DNSKEY, T_DNSKEY, "DNSKEY", 4,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BINARY }, true },
- /* 49 */
- { PARSER_RRTYPE_DHCID, T_DHCID, "DHCID", 1, { PARSER_RDATA_WF_BINARY }, true },
- /* 50 */
- { PARSER_RRTYPE_NSEC3, T_NSEC3, "NSEC3", 6,
- { PARSER_RDATA_WF_BYTE, /* hash type */
- PARSER_RDATA_WF_BYTE, /* flags */
- PARSER_RDATA_WF_SHORT, /* iterations */
- PARSER_RDATA_WF_BINARYWITHLENGTH, /* salt */
- PARSER_RDATA_WF_BINARYWITHLENGTH, /* next hashed name */
- PARSER_RDATA_WF_BINARY /* type bitmap */ }, true },
- /* 51 */
- { PARSER_RRTYPE_NSEC3PARAM, T_NSEC3PARAM, "NSEC3PARAM", 4,
- { PARSER_RDATA_WF_BYTE, /* hash type */
- PARSER_RDATA_WF_BYTE, /* flags */
- PARSER_RDATA_WF_SHORT, /* iterations */
- PARSER_RDATA_WF_BINARYWITHLENGTH /* salt */ }, true },
- /* 52 TLSA */
- { PARSER_RRTYPE_TLSA, T_TLSA, "TLSA", 3,
- { PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BINARY}, true },
-
-
- /* In NSD they have indices between 52 and 99 filled with
- unknown types. TODO add here if it's really needed? */
- /* it is indeed needed, in rrtype_from_string */
-
- /* There's a GNU extension that works like this: [first ... last] = value */
-
- [53 ... 98] = { PARSER_RRTYPE_TYPEXXX, T_UTYPE, NULL, 1, { PARSER_RDATA_WF_BINARY }},
-
- /* 99 */
- [99] = { PARSER_RRTYPE_SPF, T_SPF, "SPF", PARSER_MAX_RDATA_ITEMS,
- { PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT,
- PARSER_RDATA_WF_TEXT, PARSER_RDATA_WF_TEXT }, false },
- [100 ... 32768] = { PARSER_RRTYPE_TYPEXXX, T_UTYPE, NULL, 1, { PARSER_RDATA_WF_BINARY }},
- /* 32769 */
- [32769] = { PARSER_RRTYPE_DLV, T_DLV, "DLV", 4,
- { PARSER_RDATA_WF_SHORT, PARSER_RDATA_WF_BYTE,
- PARSER_RDATA_WF_BYTE, PARSER_RDATA_WF_BINARY }},
- [32770 ... 65535] = { PARSER_RRTYPE_TYPEXXX, T_UTYPE, NULL, 1, { PARSER_RDATA_WF_BINARY }}
-};
-
-parser_rrtype_descriptor_t *parser_rrtype_descriptor_by_type(uint16_t type)
-{
- if (type <= 65535) {
- return &knot_rrtype_descriptors[type];
- }
- return &knot_rrtype_descriptors[0];
-}
-
-/* I see a lot of potential here to speed up zone parsing - this is O(n) *
- * could be better */
-parser_rrtype_descriptor_t *parser_rrtype_descriptor_by_name(const char *name)
-{
- if (!name) {
- return NULL;
- }
-
- if (strcasecmp(name, "IN") == 0) {
- return NULL;
- }
-
- if (isdigit((int)name[0])) {
- return NULL;
- }
-
-// /* The most common - A and NS. */
-// if (strcasecmp(name, "NS") == 0) {
-// return &knot_rrtype_descriptors[2];
-// }
-
-// if (strcasecmp(name, "A") == 0) {
-// return &knot_rrtype_descriptors[1];
-// }
-
-// /* Then RRSIG */
-// if (strcasecmp(name, "RRSIG") == 0) {
-// return &knot_rrtype_descriptors[46];
-// }
-
-// /* Then DS */
-// if (strcasecmp(name, "DS") == 0) {
-// return &knot_rrtype_descriptors[43];
-// }
-// /* Then NSEC3 */
-// if (strcasecmp(name, "NSEC3") == 0) {
-// return &knot_rrtype_descriptors[50];
-// }
-// /* Then NSEC */
-// if (strcasecmp(name, "NSEC") == 0) {
-// return &knot_rrtype_descriptors[47];
-// }
-
- int i;
-
- for (i = 0; i < PARSER_RRTYPE_LAST + 1; ++i) {
- if (knot_rrtype_descriptors[i].name &&
- strcasecmp(knot_rrtype_descriptors[i].name, name) == 0) {
- return &knot_rrtype_descriptors[i];
- }
- }
-
- if (knot_rrtype_descriptors[PARSER_RRTYPE_DLV].name &&
- strcasecmp(knot_rrtype_descriptors[PARSER_RRTYPE_DLV].name,
- name) == 0) {
- return &knot_rrtype_descriptors[PARSER_RRTYPE_DLV];
- }
-
- return NULL;
-}
-
-const char *parser_rrtype_to_string(uint16_t rrtype)
-{
- static char buf[20];
- parser_rrtype_descriptor_t *descriptor =
- parser_rrtype_descriptor_by_type(rrtype);
- if (descriptor->name) {
- return descriptor->name;
- } else {
- snprintf(buf, sizeof(buf), "TYPE%d", (int) rrtype);
- return buf;
- }
-}
-
-uint16_t parser_rrtype_from_string(const char *name)
-{
- char *end;
- long rrtype;
- parser_rrtype_descriptor_t *entry;
- if (!name) {
- return 0;
- }
-
- entry = parser_rrtype_descriptor_by_name(name);
- if (entry) {
- return entry->type;
- }
-
- if (strlen(name) < 5) {
- return 0;
- }
-
- if (strncasecmp(name, "TYPE", 4) != 0) {
- return 0;
- }
-
- if (!isdigit((int)name[4])) {
- return 0;
- }
-
- /* The rest from the string must be a number. */
- rrtype = strtol(name + 4, &end, 10);
- if (*end != '\0') {
- return 0;
- }
- if (rrtype < 0 || rrtype > 65535L) {
- return 0;
- }
-
- return (uint16_t) rrtype;
-}
-
-const char *parser_rrclass_to_string(uint16_t rrclass)
-{
- static char buf[20];
- knot_lookup_table_t *entry = knot_lookup_by_id(dns_rrclasses,
- rrclass);
- if (entry) {
- assert(strlen(entry->name) < sizeof(buf));
- knot_strlcpy(buf, entry->name, sizeof(buf));
- } else {
- snprintf(buf, sizeof(buf), "CLASS%d", (int) rrclass);
- }
- return buf;
-}
-
-uint16_t parser_rrclass_from_string(const char *name)
-{
- char *end;
- long rrclass;
- knot_lookup_table_t *entry;
-
- entry = knot_lookup_by_name(dns_rrclasses, name);
- if (entry) {
- return (uint16_t) entry->id;
- }
-
- if (strlen(name) < 6) {
- return 0;
- }
-
- if (strncasecmp(name, "CLASS", 5) != 0) {
- return 0;
- }
-
- if (!isdigit((int)name[5])) {
- return 0;
- }
-
- // The rest from the string must be a number.
- rrclass = strtol(name + 5, &end, 10);
- if (*end != '\0') {
- return 0;
- }
- if (rrclass < 0 || rrclass > 65535L) {
- return 0;
- }
-
- return (uint16_t) rrclass;
-}
-
-/*! @} */
diff --git a/src/zcompile/parser-descriptor.h b/src/zcompile/parser-descriptor.h
deleted file mode 100644
index 48c6f02..0000000
--- a/src/zcompile/parser-descriptor.h
+++ /dev/null
@@ -1,279 +0,0 @@
-/*!
- * \file parser-descriptor.h
- *
- * \author Modifications by Jan Kadlec <jan.kadlec@nic.cz>,
- * most of the work by NLnet Labs.
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \brief Contains resource record descriptor and its API
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _KNOTD_PARSER_DESCRIPTOR_H_
-#define _KNOTD_PARSER_DESCRIPTOR_H_
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#include "libknot/util/utils.h"
-
-enum parser_mxrdtln {
- PARSER_MAX_RDATA_ITEMS = 64,
- PARSER_MAX_RDATA_ITEM_SIZE = 255,
- PARSER_MAX_RDATA_WIRE_SIZE =
- PARSER_MAX_RDATA_ITEMS * PARSER_MAX_RDATA_ITEM_SIZE
-};
-//#define MAXRDATALEN 64
-
-/* 64 is in NSD. Seems a little too much, but I'd say it's not a real issue. */
-
-/*!
- * \brief Enum containing RR class codes.
- */
-enum parser_rr_class {
- PARSER_CLASS_IN = 1,
- PARSER_CLASS_CS,
- PARSER_CLASS_CH,
- PARSER_CLASS_HS,
- PARSER_CLASS_NONE = 254,
- PARSER_CLASS_ANY = 255
-};
-
-typedef enum parser_rr_class parser_rr_class_t;
-
-enum parser_rr_type {
- PARSER_RRTYPE_UNKNOWN, /*!< 0 - an unknown type */
- PARSER_RRTYPE_A, /*!< 1 - a host address */
- PARSER_RRTYPE_NS, /*!< 2 - an authoritative name server */
- PARSER_RRTYPE_MD, /*!< 3 - a mail destination (Obsolete - use MX) */
- PARSER_RRTYPE_MF, /*!< 4 - a mail forwarder (Obsolete - use MX) */
- PARSER_RRTYPE_CNAME, /*!< 5 - the canonical name for an alias */
- PARSER_RRTYPE_SOA, /*!< 6 - marks the start of a zone of authority */
- PARSER_RRTYPE_MB, /*!< 7 - a mailbox domain name (EXPERIMENTAL) */
- PARSER_RRTYPE_MG, /*!< 8 - a mail group member (EXPERIMENTAL) */
- PARSER_RRTYPE_MR, /*!< 9 - a mail rename domain name (EXPERIMENTAL) */
- PARSER_RRTYPE_NULL, /*!< 10 - a null RR (EXPERIMENTAL) */
- PARSER_RRTYPE_WKS, /*!< 11 - a well known service description */
- PARSER_RRTYPE_PTR, /*!< 12 - a domain name pointer */
- PARSER_RRTYPE_HINFO, /*!< 13 - host information */
- PARSER_RRTYPE_MINFO, /*!< 14 - mailbox or mail list information */
- PARSER_RRTYPE_MX, /*!< 15 - mail exchange */
- PARSER_RRTYPE_TXT, /*!< 16 - text strings */
- PARSER_RRTYPE_RP, /*!< 17 - RFC1183 */
- PARSER_RRTYPE_AFSDB, /*!< 18 - RFC1183 */
- PARSER_RRTYPE_X25, /*!< 19 - RFC1183 */
- PARSER_RRTYPE_ISDN, /*!< 20 - RFC1183 */
- PARSER_RRTYPE_RT, /*!< 21 - RFC1183 */
- PARSER_RRTYPE_NSAP, /*!< 22 - RFC1706 */
-
- PARSER_RRTYPE_SIG = 24, /*!< 24 - 2535typecode */
- PARSER_RRTYPE_KEY, /*!< 25 - 2535typecode */
- PARSER_RRTYPE_PX, /*!< 26 - RFC2163 */
-
- PARSER_RRTYPE_AAAA = 28, /*!< 28 - ipv6 address */
- PARSER_RRTYPE_LOC, /*!< 29 - LOC record RFC1876 */
- PARSER_RRTYPE_NXT, /*!< 30 - 2535typecode */
-
- PARSER_RRTYPE_SRV = 33, /*!< 33 - SRV record RFC2782 */
-
- PARSER_RRTYPE_NAPTR = 35, /*!< 35 - RFC2915 */
- PARSER_RRTYPE_KX, /*!< 36 - RFC2230 Key Exchange Delegation Record */
- PARSER_RRTYPE_CERT, /*!< 37 - RFC2538 */
- PARSER_RRTYPE_A6, /*!< 38 - RFC2874 */
- PARSER_RRTYPE_DNAME, /*!< 39 - RFC2672 */
-
- PARSER_RRTYPE_OPT = 41, /*!< 41 - Pseudo OPT record... */
- PARSER_RRTYPE_APL, /*!< 42 - RFC3123 */
- PARSER_RRTYPE_DS, /*!< 43 - RFC 4033, 4034, and 4035 */
- PARSER_RRTYPE_SSHFP, /*!< 44 - SSH Key Fingerprint */
- PARSER_RRTYPE_IPSECKEY, /*!< 45 - public key for ipsec use. RFC 4025 */
- PARSER_RRTYPE_RRSIG, /*!< 46 - RFC 4033, 4034, and 4035 */
- PARSER_RRTYPE_NSEC, /*!< 47 - RFC 4033, 4034, and 4035 */
- PARSER_RRTYPE_DNSKEY, /*!< 48 - RFC 4033, 4034, and 4035 */
- PARSER_RRTYPE_DHCID, /*!< 49 - RFC4701 DHCP information */
- /*!
- * \brief 50 - NSEC3, secure denial, prevents zonewalking
- */
- PARSER_RRTYPE_NSEC3,
- /*!
- * \brief 51 - NSEC3PARAM at zone apex nsec3 parameters
- */
- PARSER_RRTYPE_NSEC3PARAM,
- PARSER_RRTYPE_TLSA = 52,
-
- /* TODO consider some better way of doing this, indices too high */
-
- PARSER_RRTYPE_SPF = 99, /*!< RFC 4408 */
-
- // not designating any RRs
- PARSER_RRTYPE_TSIG = 250,
- PARSER_RRTYPE_IXFR = 251,
- PARSER_RRTYPE_AXFR = 252,
- /*!
- * \brief A request for mailbox-related records (MB, MG or MR)
- */
- PARSER_RRTYPE_MAILB = 253,
- /*!
- * \brief A request for mail agent RRs (Obsolete - see MX)
- */
- PARSER_RRTYPE_MAILA = 254,
- PARSER_RRTYPE_ANY = 255, /*!< any type (wildcard) */
-
- // totally weird numbers (cannot use for indexing)
- PARSER_RRTYPE_TA = 32768, /*!< DNSSEC Trust Authorities */
- PARSER_RRTYPE_DLV = 32769, /*!< RFC 4431 */
- PARSER_RRTYPE_TYPEXXX = 32770
-};
-
-/*!
- * \brief Enum containing RR type codes.
- *
- * \todo Not all indices can be used for indexing.
- */
-typedef enum parser_rr_type parser_rr_type_t;
-
-static uint const PARSER_RRTYPE_LAST = PARSER_RRTYPE_SPF;
-
-enum parser_rdata_wireformat {
- /*!
- * \brief Possibly compressed domain name.
- */
- PARSER_RDATA_WF_COMPRESSED_DNAME = 50,
- PARSER_RDATA_WF_UNCOMPRESSED_DNAME = 51, /*!< Uncompressed domain name. */
- PARSER_RDATA_WF_LITERAL_DNAME = 52, /*!< Literal (not downcased) dname. */
- PARSER_RDATA_WF_BYTE = 1, /*!< 8-bit integer. */
- PARSER_RDATA_WF_SHORT = 2, /*!< 16-bit integer. */
- PARSER_RDATA_WF_LONG = 4, /*!< 32-bit integer. */
- PARSER_RDATA_WF_TEXT = 53, /*!< Text string. */
- PARSER_RDATA_WF_A = 58, /*!< 32-bit IPv4 address. */
- PARSER_RDATA_WF_AAAA = 16, /*!< 128-bit IPv6 address. */
- PARSER_RDATA_WF_BINARY = 54, /*!< Binary data (unknown length). */
- /*!
- * \brief Binary data preceded by 1 byte length
- */
- PARSER_RDATA_WF_BINARYWITHLENGTH = 55,
- PARSER_RDATA_WF_APL = 56, /*!< APL data. */
- PARSER_RDATA_WF_IPSECGATEWAY = 57 /*!< IPSECKEY gateway ip4, ip6 or dname. */
-};
-
-/*!
- * \brief Enum containing wireformat codes. Taken from NSD's "dns.h"
- */
-typedef enum parser_rdatawireformat parser_rdata_wireformat_t;
-
-struct parser_rrtype_descriptor {
- uint16_t type; /*!< RR type */
- int token; /*< Token used in zoneparser */
- const char *name; /*!< Textual name. */
- uint8_t length; /*!< Maximum number of RDATA items. */
- /*!
- * \brief rdata_wireformat_type
- */
- uint8_t wireformat[PARSER_MAX_RDATA_ITEMS];
- bool fixed_items; /*!< Has fixed number of RDATA items? */
-};
-
-/*!
- * \brief Structure holding RR descriptor
- */
-typedef struct parser_rrtype_descriptor parser_rrtype_descriptor_t;
-
-/*!
- * \brief Gets RR descriptor for given RR type.
- *
- * \param type Code of RR type whose descriptor should be returned.
- *
- * \return RR descriptor for given type code, NULL descriptor if
- * unknown type.
- *
- * \todo Change return value to const.
- */
-parser_rrtype_descriptor_t *parser_rrtype_descriptor_by_type(uint16_t type);
-
-/*!
- * \brief Gets RR descriptor for given RR name.
- *
- * \param name Mnemonic of RR type whose descriptor should be returned.
- *
- * \return RR descriptor for given name, NULL descriptor if
- * unknown type.
- *
- * \todo Change return value to const.
- */
-parser_rrtype_descriptor_t *parser_rrtype_descriptor_by_name(const char *name);
-
-/*!
- * \brief Converts numeric type representation to mnemonic string.
- *
- * \param rrtype Type RR type code to be converted.
- *
- * \return Mnemonic string if found, str(TYPE[rrtype]) otherwise.
- */
-const char *parser_rrtype_to_string(uint16_t rrtype);
-
-/*!
- * \brief Converts mnemonic string representation of a type to numeric one.
- *
- * \param name Mnemonic string to be converted.
- *
- * \return Correct code if found, 0 otherwise.
- */
-uint16_t parser_rrtype_from_string(const char *name);
-
-/*!
- * \brief Converts numeric class representation to string one.
- *
- * \param rrclass Class code to be converted.
- *
- * \return String represenation of class if found,
- * str(CLASS[rrclass]) otherwise.
- */
-const char *parser_rrclass_to_string(uint16_t rrclass);
-
-/*!
- * \brief Converts string representation of a class to numeric one.
- *
- * \param name Class string to be converted.
- *
- * \return Correct code if found, 0 otherwise.
- */
-uint16_t parser_rrclass_from_string(const char *name);
-
-#endif /* _KNOTD_PARSER_DESCRIPTOR_H_ */
-
-/*! @} */
diff --git a/src/zcompile/parser-util.c b/src/zcompile/parser-util.c
deleted file mode 100644
index b112ece..0000000
--- a/src/zcompile/parser-util.c
+++ /dev/null
@@ -1,2488 +0,0 @@
-/*!
- * \file parser-util.c
- *
- * \author NLnet Labs
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \brief utility functions for zone parser.
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <config.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-//#include "common.h"
-#include "common/base32hex.h"
-#include "zcompile/parser-util.h"
-#include "zcompile/zcompile.h"
-#include "parser-descriptor.h"
-#include "libknot/util/utils.h"
-#include "zcompile/zcompile-error.h"
-
-#define IP6ADDRLEN (128/8)
-#define NS_INT16SZ 2
-#define NS_INADDRSZ 4
-#define NS_IN6ADDRSZ 16
-#define APL_NEGATION_MASK 0x80U
-
-/* int
- * inet_pton(af, src, dst)
- * convert from presentation format (which usually means ASCII printable)
- * to network format (which is usually some kind of binary format).
- * return:
- * 1 if the address was valid for the specified address family
- * 0 if the address wasn't valid (`dst' is untouched in this case)
- * -1 if some other error occurred (`dst' is untouched in this case, too)
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton(int af, const char *src, void *dst)
-{
- switch (af) {
- case AF_INET:
- return (inet_pton4(src, dst));
- case AF_INET6:
- return (inet_pton6(src, dst));
- default:
- errno = EAFNOSUPPORT;
- return (-1);
- }
- /* NOTREACHED */
-}
-
-//int my_b32_pton(const char *src, uint8_t *target, size_t tsize)
-//{
-// char ch;
-// size_t p = 0;
-
-// memset(target, '\0', tsize);
-// while ((ch = *src++)) {
-// uint8_t d;
-// size_t b;
-// size_t n;
-
-// if (p + 5 >= tsize * 8) {
-// return -1;
-// }
-
-// if (isspace(ch)) {
-// continue;
-// }
-
-// if (ch >= '0' && ch <= '9') {
-// d = ch - '0';
-// } else if (ch >= 'A' && ch <= 'V') {
-// d = ch - 'A' + 10;
-// } else if (ch >= 'a' && ch <= 'v') {
-// d = ch - 'a' + 10;
-// } else {
-// return -1;
-// }
-
-// b = 7 - p % 8;
-// n = p / 8;
-
-// if (b >= 4) {
-// target[n] |= d << (b - 4);
-// } else {
-// target[n] |= d >> (4 - b);
-// target[n+1] |= d << (b + 4);
-// }
-// p += 5;
-// }
-// return (p + 7) / 8;
-//}
-
-
-#define Assert(Cond) if (!(Cond)) abort()
-
-static const char Base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char Pad64 = '=';
-
-/* int
- * inet_pton4(src, dst)
- * like inet_aton() but without all the hexadecimal and shorthand.
- * return:
- * 1 if `src' is a valid dotted quad, else 0.
- * notice:
- * does not touch `dst' unless it's returning 1.
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton4(const char *src, uint8_t *dst)
-{
- static const char digits[] = "0123456789";
- int saw_digit, octets, ch;
- uint8_t tmp[NS_INADDRSZ], *tp;
-
- saw_digit = 0;
- octets = 0;
- *(tp = tmp) = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
-
- if ((pch = strchr(digits, ch)) != NULL) {
- uint32_t new = *tp * 10 + (pch - digits);
-
- if (new > 255) {
- return (0);
- }
- *tp = new;
- if (! saw_digit) {
- if (++octets > 4) {
- return (0);
- }
- saw_digit = 1;
- }
- } else if (ch == '.' && saw_digit) {
- if (octets == 4) {
- return (0);
- }
- *++tp = 0;
- saw_digit = 0;
- } else {
- return (0);
- }
- }
- if (octets < 4) {
- return (0);
- }
-
- memcpy(dst, tmp, NS_INADDRSZ);
- return (1);
-}
-
-/* int
- * inet_pton6(src, dst)
- * convert presentation level address to network order binary form.
- * return:
- * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- * (1) does not touch `dst' unless it's returning 1.
- * (2) :: in a full address is silently ignored.
- * credit:
- * inspired by Mark Andrews.
- * author:
- * Paul Vixie, 1996.
- */
-int inet_pton6(const char *src, uint8_t *dst)
-{
- static const char xdigits_l[] = "0123456789abcdef",
- xdigits_u[] = "0123456789ABCDEF";
- uint8_t tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
- const char *xdigits, *curtok;
- int ch, saw_xdigit;
- uint32_t val;
-
- memset((tp = tmp), '\0', NS_IN6ADDRSZ);
- endp = tp + NS_IN6ADDRSZ;
- colonp = NULL;
- /* Leading :: requires some special handling. */
- if (*src == ':')
- if (*++src != ':') {
- return (0);
- }
- curtok = src;
- saw_xdigit = 0;
- val = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
-
- if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) {
- pch = strchr((xdigits = xdigits_u), ch);
- }
- if (pch != NULL) {
- val <<= 4;
- val |= (pch - xdigits);
- if (val > 0xffff) {
- return (0);
- }
- saw_xdigit = 1;
- continue;
- }
- if (ch == ':') {
- curtok = src;
- if (!saw_xdigit) {
- if (colonp) {
- return (0);
- }
- colonp = tp;
- continue;
- }
- if (tp + NS_INT16SZ > endp) {
- return (0);
- }
- *tp++ = (uint8_t)(val >> 8) & 0xff;
- *tp++ = (uint8_t) val & 0xff;
- saw_xdigit = 0;
- val = 0;
- continue;
- }
- if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
- inet_pton4(curtok, tp) > 0) {
- tp += NS_INADDRSZ;
- saw_xdigit = 0;
- break; /* '\0' was seen by inet_pton4(). */
- }
- return (0);
- }
- if (saw_xdigit) {
- if (tp + NS_INT16SZ > endp) {
- return (0);
- }
- *tp++ = (uint8_t)(val >> 8) & 0xff;
- *tp++ = (uint8_t) val & 0xff;
- }
- if (colonp != NULL) {
- /*
- * Since some memmove()'s erroneously fail to handle
- * overlapping regions, we'll do the shift by hand.
- */
- const int n = tp - colonp;
- int i;
-
- for (i = 1; i <= n; i++) {
- endp[- i] = colonp[n - i];
- colonp[n - i] = 0;
- }
- tp = endp;
- }
- if (tp != endp) {
- return (0);
- }
- memcpy(dst, tmp, NS_IN6ADDRSZ);
- return (1);
-}
-
-
-#ifndef IN6ADDRSZ
-#define IN6ADDRSZ 16 /* IPv6 T_AAAA */
-#endif
-
-#ifndef INT16SZ
-#define INT16SZ 2 /* for systems without 16-bit ints */
-#endif
-
-/*
- * WARNING: Don't even consider trying to compile this on a system where
- * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
- */
-
-
-/* char *
- * inet_ntop(af, src, dst, size)
- * convert a network format address to presentation format.
- * return:
- * pointer to presentation format address (`dst'), or NULL (see errno).
- * author:
- * Paul Vixie, 1996.
- */
-//const char *inet_ntop(int af, const void *src, char *dst, size_t size)
-//{
-// switch (af) {
-// case AF_INET:
-// return (inet_ntop4(src, dst, size));
-// case AF_INET6:
-// return (inet_ntop6(src, dst, size));
-// default:
-// errno = EAFNOSUPPORT;
-// return (NULL);
-// }
-// /* NOTREACHED */
-//}
-
-/* const char *
- * inet_ntop4(src, dst, size)
- * format an IPv4 address, more or less like inet_ntoa()
- * return:
- * `dst' (as a const)
- * notes:
- * (1) uses no statics
- * (2) takes a u_char* not an in_addr as input
- * author:
- * Paul Vixie, 1996.
- */
-const char *inet_ntop4(const u_char *src, char *dst, size_t size)
-{
- static const char fmt[] = "%u.%u.%u.%u";
- char tmp[sizeof "255.255.255.255"];
- int l;
-
- l = snprintf(tmp, size, fmt, src[0], src[1], src[2], src[3]);
- if (l <= 0 || l >= (int)size) {
- errno = ENOSPC;
- return (NULL);
- }
- knot_strlcpy(dst, tmp, size);
- return (dst);
-}
-
-/* const char *
- * inet_ntop6(src, dst, size)
- * convert IPv6 binary address into presentation (printable) format
- * author:
- * Paul Vixie, 1996.
- */
-const char *inet_ntop6(const u_char *src, char *dst, size_t size)
-{
- /*
- * Note that int32_t and int16_t need only be "at least" large enough
- * to contain a value of the specified size. On some systems, like
- * Crays, there is no such thing as an integer variable with 16 bits.
- * Keep this in mind if you think this function should have been coded
- * to use pointer overlays. All the world's not a VAX.
- */
- char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
- char *tp, *ep;
- struct {
- int base, len;
- } best, cur;
- best.base = cur.base =-1;
- best.len = cur.len = 0;
- u_int words[IN6ADDRSZ / INT16SZ];
- int i;
- int advance;
-
- /*
- * Preprocess:
- * Copy the input (bytewise) array into a wordwise array.
- * Find the longest run of 0x00's in src[] for :: shorthanding.
- */
- memset(words, '\0', sizeof words);
- for (i = 0; i < IN6ADDRSZ; i++) {
- words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
- }
-
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
- if (words[i] == 0) {
- if (cur.base == -1) {
- cur.base = i, cur.len = 1;
- } else {
- cur.len++;
- }
- } else {
- if (cur.base != -1) {
- if (best.base == -1 || cur.len > best.len) {
- best = cur;
- }
- cur.base = -1;
- }
- }
- }
- if (cur.base != -1) {
- if (best.base == -1 || cur.len > best.len) {
- best = cur;
- }
- }
- if (best.base != -1 && best.len < 2) {
- best.base = -1;
- }
-
- /*
- * Format the result.
- */
- tp = tmp;
- ep = tmp + sizeof(tmp);
- for (i = 0; i < (IN6ADDRSZ / INT16SZ) && tp < ep; i++) {
- /* Are we inside the best run of 0x00's? */
- if (best.base != -1 && i >= best.base &&
- i < (best.base + best.len)) {
- if (i == best.base) {
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = ':';
- }
- continue;
- }
- /* Are we following an initial run of 0x00s or any real hex? */
- if (i != 0) {
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = ':';
- }
- /* Is this address an encapsulated IPv4? */
- if (i == 6 && best.base == 0 &&
- (best.len == 6 ||
- (best.len == 5 && words[5] == 0xffff))) {
- if (!inet_ntop4(src + 12, tp, (size_t)(ep - tp))) {
- return (NULL);
- }
- tp += strlen(tp);
- break;
- }
- advance = snprintf(tp, ep - tp, "%x", words[i]);
- if (advance <= 0 || advance >= ep - tp) {
- return (NULL);
- }
- tp += advance;
- }
- /* Was it a trailing run of 0x00's? */
- if (best.base != -1 && (best.base + best.len) ==
- (IN6ADDRSZ / INT16SZ)) {
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = ':';
- }
- if (tp + 1 >= ep) {
- return (NULL);
- }
- *tp++ = '\0';
-
- /*
- * Check for overflow, copy, and we're done.
- */
- if ((size_t)(tp - tmp) > size) {
- errno = ENOSPC;
- return (NULL);
- }
- knot_strlcpy(dst, tmp, size);
- return (dst);
-}
-
-
-static int b64rmap_initialized = 0;
-static uint8_t b64rmap[256];
-
-static const uint8_t b64rmap_special = 0xf0;
-static const uint8_t b64rmap_end = 0xfd;
-static const uint8_t b64rmap_space = 0xfe;
-static const uint8_t b64rmap_invalid = 0xff;
-
-/**
- * Initializing the reverse map is not thread safe.
- * Which is fine for NSD. For now...
- **/
-void b64_initialize_rmap()
-{
- int i;
- char ch;
-
- /* Null: end of string, stop parsing */
- b64rmap[0] = b64rmap_end;
-
- for (i = 1; i < 256; ++i) {
- ch = (char)i;
- /* Whitespaces */
- if (isspace(ch)) {
- b64rmap[i] = b64rmap_space;
- }
- /* Padding: stop parsing */
- else if (ch == Pad64) {
- b64rmap[i] = b64rmap_end;
- }
- /* Non-base64 char */
- else {
- b64rmap[i] = b64rmap_invalid;
- }
- }
-
- /* Fill reverse mapping for base64 chars */
- for (i = 0; Base64[i] != '\0'; ++i) {
- b64rmap[(uint8_t)Base64[i]] = i;
- }
-
- b64rmap_initialized = 1;
-}
-
-int b64_pton_do(char const *src, uint8_t *target, size_t targsize)
-{
- int tarindex, state, ch;
- uint8_t ofs;
-
- state = 0;
- tarindex = 0;
-
- while (1) {
- ch = *src++;
- ofs = b64rmap[ch];
-
- if (ofs >= b64rmap_special) {
- /* Ignore whitespaces */
- if (ofs == b64rmap_space) {
- continue;
- }
- /* End of base64 characters */
- if (ofs == b64rmap_end) {
- break;
- }
- /* A non-base64 character. */
- return (-1);
- }
-
- switch (state) {
- case 0:
- if ((size_t)tarindex >= targsize) {
- return (-1);
- }
- target[tarindex] = ofs << 2;
- state = 1;
- break;
- case 1:
- if ((size_t)tarindex + 1 >= targsize) {
- return (-1);
- }
- target[tarindex] |= ofs >> 4;
- target[tarindex+1] = (ofs & 0x0f)
- << 4 ;
- tarindex++;
- state = 2;
- break;
- case 2:
- if ((size_t)tarindex + 1 >= targsize) {
- return (-1);
- }
- target[tarindex] |= ofs >> 2;
- target[tarindex+1] = (ofs & 0x03)
- << 6;
- tarindex++;
- state = 3;
- break;
- case 3:
- if ((size_t)tarindex >= targsize) {
- return (-1);
- }
- target[tarindex] |= ofs;
- tarindex++;
- state = 0;
- break;
- default:
- abort();
- }
- }
-
- /*
- * We are done decoding Base-64 chars. Let's see if we ended
- * on a byte boundary, and/or with erroneous trailing characters.
- */
-
- if (ch == Pad64) { /* We got a pad char. */
- ch = *src++; /* Skip it, get next. */
- switch (state) {
- case 0: /* Invalid = in first position */
- case 1: /* Invalid = in second position */
- return (-1);
-
- case 2: /* Valid, means one byte of info */
- /* Skip any number of spaces. */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- break;
- }
- /* Make sure there is another trailing = sign. */
- if (ch != Pad64) {
- return (-1);
- }
- ch = *src++; /* Skip the = */
- /* Fall through to "single trailing =" case. */
- /* FALLTHROUGH */
-
- case 3: /* Valid, means two bytes of info */
- /*
- * We know this char is an =. Is there anything but
- * whitespace after it?
- */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- return (-1);
- }
-
- /*
- * Now make sure for cases 2 and 3 that the "extra"
- * bits that slopped past the last full byte were
- * zeros. If we don't check them, they become a
- * subliminal channel.
- */
- if (target[tarindex] != 0) {
- return (-1);
- }
- }
- } else {
- /*
- * We ended by seeing the end of the string. Make sure we
- * have no partial bytes lying around.
- */
- if (state != 0) {
- return (-1);
- }
- }
-
- return (tarindex);
-}
-
-
-int b64_pton_len(char const *src)
-{
- int tarindex, state, ch;
- uint8_t ofs;
-
- state = 0;
- tarindex = 0;
-
- while (1) {
- ch = *src++;
- ofs = b64rmap[ch];
-
- if (ofs >= b64rmap_special) {
- /* Ignore whitespaces */
- if (ofs == b64rmap_space) {
- continue;
- }
- /* End of base64 characters */
- if (ofs == b64rmap_end) {
- break;
- }
- /* A non-base64 character. */
- return (-1);
- }
-
- switch (state) {
- case 0:
- state = 1;
- break;
- case 1:
- tarindex++;
- state = 2;
- break;
- case 2:
- tarindex++;
- state = 3;
- break;
- case 3:
- tarindex++;
- state = 0;
- break;
- default:
- abort();
- }
- }
-
- /*
- * We are done decoding Base-64 chars. Let's see if we ended
- * on a byte boundary, and/or with erroneous trailing characters.
- */
-
- if (ch == Pad64) { /* We got a pad char. */
- ch = *src++; /* Skip it, get next. */
- switch (state) {
- case 0: /* Invalid = in first position */
- case 1: /* Invalid = in second position */
- return (-1);
-
- case 2: /* Valid, means one byte of info */
- /* Skip any number of spaces. */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- break;
- }
- /* Make sure there is another trailing = sign. */
- if (ch != Pad64) {
- return (-1);
- }
- ch = *src++; /* Skip the = */
- /* Fall through to "single trailing =" case. */
- /* FALLTHROUGH */
-
- case 3: /* Valid, means two bytes of info */
- /*
- * We know this char is an =. Is there anything but
- * whitespace after it?
- */
- for ((void)NULL; ch != '\0'; ch = *src++)
- if (b64rmap[ch] != b64rmap_space) {
- return (-1);
- }
-
- }
- } else {
- /*
- * We ended by seeing the end of the string. Make sure we
- * have no partial bytes lying around.
- */
- if (state != 0) {
- return (-1);
- }
- }
-
- return (tarindex);
-}
-
-int b64_pton(char const *src, uint8_t *target, size_t targsize)
-{
- if (!b64rmap_initialized) {
- b64_initialize_rmap();
- }
-
- if (target) {
- return b64_pton_do(src, target, targsize);
- } else {
- return b64_pton_len(src);
- }
-}
-
-void set_bit(uint8_t bits[], size_t index)
-{
- /*
- * The bits are counted from left to right, so bit #0 is the
- * left most bit.
- */
- bits[index / 8] |= (1 << (7 - index % 8));
-}
-
-uint32_t strtoserial(const char *nptr, const char **endptr)
-{
- uint32_t i = 0;
- uint32_t serial = 0;
-
- for (*endptr = nptr; **endptr; (*endptr)++) {
- switch (**endptr) {
- case ' ':
- case '\t':
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i *= 10;
- i += (**endptr - '0');
- break;
- default:
- break;
- }
- }
- serial += i;
- return serial;
-}
-
-inline void write_uint32(void *dst, uint32_t data)
-{
-/*!< \todo Check what this means and delete if obsolete. */
-#ifdef ALLOW_UNALIGNED_ACCESSES
- *(uint32_t *) dst = htonl(data);
-#else
- uint8_t *p = (uint8_t *) dst;
- p[0] = (uint8_t)((data >> 24) & 0xff);
- p[1] = (uint8_t)((data >> 16) & 0xff);
- p[2] = (uint8_t)((data >> 8) & 0xff);
- p[3] = (uint8_t)(data & 0xff);
-#endif
-}
-
-uint32_t strtottl(const char *nptr, const char **endptr)
-{
- uint32_t i = 0;
- uint32_t seconds = 0;
-
- for (*endptr = nptr; **endptr; (*endptr)++) {
- switch (**endptr) {
- case ' ':
- case '\t':
- break;
- case 's':
- case 'S':
- seconds += i;
- i = 0;
- break;
- case 'm':
- case 'M':
- seconds += i * 60;
- i = 0;
- break;
- case 'h':
- case 'H':
- seconds += i * 60 * 60;
- i = 0;
- break;
- case 'd':
- case 'D':
- seconds += i * 60 * 60 * 24;
- i = 0;
- break;
- case 'w':
- case 'W':
- seconds += i * 60 * 60 * 24 * 7;
- i = 0;
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i *= 10;
- i += (**endptr - '0');
- break;
- default:
- seconds += i;
- return seconds;
- }
- }
- seconds += i;
- return seconds;
-}
-
-/* Number of days per month (except for February in leap years). */
-static const int mdays[] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-static int is_leap_year(int year)
-{
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
-}
-
-static int leap_days(int y1, int y2)
-{
- --y1;
- --y2;
- return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
-}
-
-/*
- * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
- */
-time_t mktime_from_utc(const struct tm *tm)
-{
- int year = 1900 + tm->tm_year;
- time_t days = 365 * (year - 1970) + leap_days(1970, year);
- time_t hours;
- time_t minutes;
- time_t seconds;
- int i;
-
- for (i = 0; i < tm->tm_mon; ++i) {
- days += mdays[i];
- }
- if (tm->tm_mon > 1 && is_leap_year(year)) {
- ++days;
- }
- days += tm->tm_mday - 1;
-
- hours = days * 24 + tm->tm_hour;
- minutes = hours * 60 + tm->tm_min;
- seconds = minutes * 60 + tm->tm_sec;
-
- return seconds;
-}
-
-/*!< Following functions are conversions from text to wire. */
-//#define DEBUG_UNKNOWN_RDATA
-
-#ifdef DEBUG_UNKNOWN_RDATA
-#define dbg_rdata(msg...) fprintf(stderr, msg)
-#define DBG_RDATA(cmds) do { cmds } while (0)
-#else
-#define dbg_rdata(msg...)
-#define DBG_RDATA(cmds)
-#endif
-
-
-
-#define IP6ADDRLEN (128/8)
-#define NS_INT16SZ 2
-#define NS_INADDRSZ 4
-#define NS_IN6ADDRSZ 16
-#define APL_NEGATION_MASK 0x80U
-#define APL_LENGTH_MASK (~APL_NEGATION_MASK)
-
-//#define ZP_DEBUG
-
-#ifdef ZP_DEBUG
-#define dbg_zp(msg...) fprintf(stderr, msg)
-#else
-#define dbg_zp(msg...)
-#endif
-
-
-/*!
- * \brief Return data of raw data item.
- *
- * \param item Item.
- * \return uint16_t * Raw data.
- */
-static inline uint16_t * rdata_atom_data(knot_rdata_item_t item)
-{
- return (uint16_t *)(item.raw_data + 1);
-}
-
-/*!
- * \brief Return type of RRSet covered by given RRSIG.
- *
- * \param rrset RRSIG.
- * \return uint16_t Type covered.
- */
-uint16_t rrsig_type_covered(knot_rrset_t *rrset)
-{
- assert(rrset->rdata->items[0].raw_data[0] == sizeof(uint16_t));
-
- return ntohs(*(uint16_t *) rdata_atom_data(rrset->rdata->items[0]));
-}
-
-/*!
- * \brief Checks if item contains domain.
- *
- * \param type Type of RRSet.
- * \param index Index to check.
- *
- * \return > 1 if item is domain, 0 otherwise.
- */
-static inline int rdata_atom_is_domain(uint16_t type, size_t index)
-{
- const knot_rrtype_descriptor_t *descriptor
- = knot_rrtype_descriptor_by_type(type);
- return (index < descriptor->length
- && (descriptor->wireformat[index] ==
- KNOT_RDATA_WF_COMPRESSED_DNAME ||
- descriptor->wireformat[index] ==
- KNOT_RDATA_WF_LITERAL_DNAME ||
- descriptor->wireformat[index] ==
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME));
-}
-
-/*!
- * \brief Returns which wireformat type is on given index.
- *
- * \param type Type of RRSet.
- * \param index Index.
- *
- * \return uint8_t Wireformat type.
- */
-static inline uint8_t rdata_atom_wireformat_type(uint16_t type, size_t index)
-{
- const knot_rrtype_descriptor_t *descriptor =
- knot_rrtype_descriptor_by_type(type);
- assert(index < descriptor->length);
- return descriptor->wireformat[index];
-}
-
-typedef int (*printf_t)(const char *fmt, ...);
-
-/*!
- * \brief Converts rdata wireformat to rdata items.
- *
- * \param wireformat Wireformat/.
- * \param rrtype RR type.
- * \param data_size Size of wireformat.
- * \param items created rdata items.
- *
- * \return Number of items converted.
- */
-static ssize_t rdata_wireformat_to_rdata_atoms(const uint16_t *wireformat,
- uint16_t rrtype,
- const uint16_t data_size,
- knot_rdata_item_t **items)
-{
- /*!< \todo This is so ugly, it makes me wanna puke. */
- uint16_t const *end =
- (uint16_t *)((uint8_t *)wireformat + (data_size));
- dbg_rdata("set end pointer: %p which means length: %d\n", end,
- (uint8_t *)end - (uint8_t *)wireformat);
- dbg_rdata("Parsing following wf: ");
- size_t i;
- knot_rdata_item_t *temp_rdatas =
- malloc(sizeof(*temp_rdatas) * MAXRDATALEN);
- if (temp_rdatas == NULL) {
- ERR_ALLOC_FAILED;
- return KNOTDZCOMPILE_ENOMEM;
- }
- memset(temp_rdatas, 0, sizeof(*temp_rdatas) * MAXRDATALEN);
-
- knot_rrtype_descriptor_t *descriptor =
- knot_rrtype_descriptor_by_type(rrtype);
-
- assert(descriptor->length <= MAXRDATALEN);
-
- dbg_rdata("will be parsing %d items, total size: %d\n",
- descriptor->length, data_size);
-
- for (i = 0; i < descriptor->length; ++i) {
- dbg_rdata("this particular item is type %d.\n",
- rdata_atom_wireformat_type(rrtype, i));
- int is_domain = 0;
- int is_wirestore = 0;
- size_t length = 0;
- length = 0;
- bool required = descriptor->fixed_items;
-
- switch (rdata_atom_wireformat_type(rrtype, i)) {
- case KNOT_RDATA_WF_COMPRESSED_DNAME:
- case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
- dbg_rdata("Parsed item is a dname.\n");
- is_domain = 1;
- break;
- case KNOT_RDATA_WF_LITERAL_DNAME:
- dbg_rdata("Parsed item is a literal dname.\n");
- is_domain = 1;
- is_wirestore = 1;
- break;
- case KNOT_RDATA_WF_BYTE:
- dbg_rdata("Parsed item is a byte.\n");
- length = sizeof(uint8_t);
- break;
- case KNOT_RDATA_WF_SHORT:
- dbg_rdata("Parsed item is a short.\n");
- length = sizeof(uint16_t);
- break;
- case KNOT_RDATA_WF_LONG:
- dbg_rdata("Parsed item is a long.\n");
- length = sizeof(uint32_t);
- break;
- case KNOT_RDATA_WF_APL:
- dbg_rdata("APL data.\n");
- case KNOT_RDATA_WF_TEXT_SINGLE:
- case KNOT_RDATA_WF_TEXT:
- dbg_rdata("TEXT rdata.\n");
- case KNOT_RDATA_WF_BINARYWITHLENGTH:
- dbg_rdata("BINARYWITHLENGTH rdata.\n");
- /* Length is stored in the first byte. */
- length = data_size;
- break;
- case KNOT_RDATA_WF_A:
- dbg_rdata("Parsed item is an IPv4 address.\n");
- length = sizeof(in_addr_t);
- break;
- case KNOT_RDATA_WF_AAAA:
- dbg_rdata("Parsed item is an IPv6 address.\n");
- length = IP6ADDRLEN;
- break;
- case KNOT_RDATA_WF_BINARY:
- /* Remaining RDATA is binary. */
- dbg_rdata("BINARY: item %d: guessing length from pointers: %p %p. ",
- i,
- wireformat, end);
- length = (uint8_t *)end - (uint8_t *)wireformat;
- dbg_rdata("Result: %d.\n",
- length);
- break;
-// case KNOT_RDATA_WF_APL:
-// length = (sizeof(uint16_t) /* address family */
-// + sizeof(uint8_t) /* prefix */
-// + sizeof(uint8_t)); /* length */
-// if ((uint8_t *)wireformat + length <= (uint8_t *)end) {
-// /* Mask out negation bit. */
-// dbg_rdata("APL: length was %d. ", length);
-// length += (wireformat[data_size - 1]
-// & APL_LENGTH_MASK);
-// dbg_rdata("APL: after masking: %d.\n", length);
-// }
-// break;
- case KNOT_RDATA_WF_IPSECGATEWAY:
- dbg_rdata("Parsed item is an IPSECGATEWAY address.\n");
- dbg_rdata("Gateway type: %d\n",
- ((uint8_t *)rdata_atom_data(temp_rdatas[1]))[0]);
- switch (((uint8_t *)rdata_atom_data(temp_rdatas[1]))[0]) {
- /* gateway type */
- case IPSECKEY_NOGATEWAY:
- dbg_rdata("NOGATEWAY\n");
- length = 0;
- break;
- case IPSECKEY_IP4:
- dbg_rdata("IPv4\n");
- length = 4;
- break;
- case IPSECKEY_IP6:
- dbg_rdata("IPv6\n");
- length = IP6ADDRLEN;
- break;
- case IPSECKEY_DNAME:
- dbg_rdata("DNAME\n");
- is_domain = 1;
- is_wirestore = 1;
- break;
- default:
- dbg_rdata("Unknown IPSECKEY gateway!\n");
- free(temp_rdatas);
- return -1;
- } // switch
- }
-
- if (is_domain) {
- knot_dname_t *dname = NULL;
- /*
- * Since we don't know how many dnames there are
- * in the whole wireformat we have to search for next
- * '\0'.
- */
- for (length = 0;
- (length < ((uint8_t *)end - (uint8_t *)wireformat))
- && (((uint8_t *)wireformat)[length] != '\0');
- length++) {
- ;
- }
- length++;
- dbg_rdata("item %d: length derived from position of "
- "0: %d\n", i, length);
-
- if (!required && (wireformat == end)) {
- break;
- }
-
- dname = knot_dname_new_from_wire((uint8_t *)wireformat,
- length,
- NULL);
-
- if (dname == NULL) {
- dbg_rdata("malformed dname!\n");
- /*! \todo rdata purge */
- free(temp_rdatas);
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- dbg_rdata("item %d: created dname: %s, length: %d\n", i,
- knot_dname_to_str(dname), length);
-
- if (is_wirestore) {
- /*temp_rdatas[i].raw_data =
- (uint16_t *) region_alloc(
- region, sizeof(uint16_t) + dname->name_size);
- temp_rdatas[i].data[0] = dname->name_size;
- memcpy(temp_rdatas[i].data+1, dname_name(dname),
- dname->name_size); */
- temp_rdatas[i].raw_data =
- malloc(sizeof(uint16_t) +
- sizeof(uint8_t) * dname->size);
- if (temp_rdatas[i].raw_data == NULL) {
- ERR_ALLOC_FAILED;
- /*! \todo rdata purge */
- free(temp_rdatas);
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- temp_rdatas[i].raw_data[0] = dname->size;
- memcpy(temp_rdatas[i].raw_data + 1,
- dname->name, dname->size);
-
- knot_dname_release(dname);
- } else {
- temp_rdatas[i].dname = dname;
- }
-
- } else {
- /*!< \todo This calculated length makes no sense! */
- dbg_rdata("item %d :length: %d calculated: %d (%p %p)\n", i, length,
- end - wireformat,
- wireformat, end);
- if ((uint8_t *)wireformat + length > (uint8_t *)end) {
- if (required) {
- /* Truncated RDATA. */
- /*! \todo rdata purge */
- free(temp_rdatas);
- dbg_rdata("truncated rdata, end pointer is exceeded by %d octets.\n",
- (wireformat + length) - end);
- return KNOTDZCOMPILE_EBRDATA;
- } else {
- break;
- }
- }
-
- assert(wireformat <= end); /*!< \todo remove! */
- dbg_rdata("calling init with: %p and length : %d\n",
- wireformat, length);
- temp_rdatas[i].raw_data = alloc_rdata_init(wireformat,
- length);
- if (temp_rdatas[i].raw_data == NULL) {
- ERR_ALLOC_FAILED;
- /*! \todo rdata purge */
- free(temp_rdatas);
- return -1;
- }
-
-// temp_rdatas[i].raw_data[0] = length;
-// memcpy(temp_rdatas[i].raw_data + 1, wireformat, length);
-
-/* temp_rdatas[i].data = (uint16_t *) region_alloc(
- region, sizeof(uint16_t) + length);
- temp_rdatas[i].data[0] = length;
- buffer_read(packet,
- temp_rdatas[i].data + 1, length); */
- }
- dbg_rdata("%d: adding length: %d (remaining: %d)\n", i, length,
- (uint8_t *)end - ((uint8_t *)wireformat + length));
-// hex_print(temp_rdatas[i].raw_data + 1, length);
- wireformat = (uint16_t *)((uint8_t *)wireformat + length);
-// wireformat = wireformat + length;
- dbg_rdata("wire: %p\n", wireformat);
- dbg_rdata("remaining now: %d\n",
- end - wireformat);
- }
-
- dbg_rdata("%p %p\n", wireformat, (uint8_t *)wireformat);
-
- if (wireformat < end) {
- /* Trailing garbage. */
- dbg_rdata("Garbage: w: %p e: %p %d\n", wireformat, end, end - wireformat);
- free(temp_rdatas);
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- *items = temp_rdatas;
- /* *rdatas = (rdata_atom_type *) region_alloc_init(
- region, temp_rdatas, i * sizeof(rdata_atom_type)); */
- dbg_rdata("wf_to_rdata_atoms: Succesfully converted %d items.\n",
- i);
- return (ssize_t)i;
-}
-
-/* Taken from RFC 2535, section 7. */
-knot_lookup_table_t dns_algorithms[] = {
- { 1, "RSAMD5" }, /* RFC 2537 */
- { 2, "DH" }, /* RFC 2539 */
- { 3, "DSA" }, /* RFC 2536 */
- { 4, "ECC" },
- { 5, "RSASHA1" }, /* RFC 3110 */
- { 252, "INDIRECT" },
- { 253, "PRIVATEDNS" },
- { 254, "PRIVATEOID" },
- { 0, NULL }
-};
-
-/* Taken from RFC 4398, section 2.1. */
-knot_lookup_table_t dns_certificate_types[] = {
- /* 0 Reserved */
- { 1, "PKIX" }, /* X.509 as per PKIX */
- { 2, "SPKI" }, /* SPKI cert */
- { 3, "PGP" }, /* OpenPGP packet */
- { 4, "IPKIX" }, /* The URL of an X.509 data object */
- { 5, "ISPKI" }, /* The URL of an SPKI certificate */
- { 6, "IPGP" }, /* The fingerprint and URL of an OpenPGP packet */
- { 7, "ACPKIX" }, /* Attribute Certificate */
- { 8, "IACPKIX" }, /* The URL of an Attribute Certificate */
- { 253, "URI" }, /* URI private */
- { 254, "OID" }, /* OID private */
- /* 255 Reserved */
- /* 256-65279 Available for IANA assignment */
- /* 65280-65534 Experimental */
- /* 65535 Reserved */
- { 0, NULL }
-};
-
-/* Imported from lexer. */
-extern int hexdigit_to_int(char ch);
-
-extern uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE];
-extern uint16_t nsec_highest_rcode;
-
-/*!
- * \brief Allocate SIZE+sizeof(uint16_t) bytes and store SIZE in the first
- * element. Return a pointer to the allocation.
- *
- * \param size How many bytes to allocate.
- */
-static uint16_t * alloc_rdata(size_t size)
-{
- uint16_t *result = malloc(sizeof(uint16_t) + size);
- *result = size;
- return result;
-}
-
-uint16_t *alloc_rdata_init(const void *data, size_t size)
-{
- uint16_t *result = malloc(sizeof(uint16_t) + size);
- if (result == NULL) {
- return NULL;
- }
- *result = size;
- memcpy(result + 1, data, size);
- return result;
-}
-
-/*
- * These are parser function for generic zone file stuff.
- */
-uint16_t * zparser_conv_hex(const char *hex, size_t len)
-{
- /* convert a hex value to wireformat */
- uint16_t *r = NULL;
- uint8_t *t;
- int i;
-
- if (len % 2 != 0) {
- zc_error_prev_line("number of hex digits "
- "must be a multiple of 2");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else if (len > MAX_RDLENGTH * 2) {
- zc_error_prev_line("hex data exceeds maximum rdata length (%d)",
- MAX_RDLENGTH);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- /* the length part */
-
- r = alloc_rdata(len / 2);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- t = (uint8_t *)(r + 1);
-
- /* Now process octet by octet... */
- while (*hex) {
- *t = 0;
- for (i = 16; i >= 1; i -= 15) {
- if (isxdigit((int)*hex)) {
- *t += hexdigit_to_int(*hex) * i;
- } else {
- zc_error_prev_line(
- "illegal hex character '%c'",
- (int) *hex);
- parser->error_occurred =
- KNOTDZCOMPILE_EBRDATA;
- free(r);
- return NULL;
- }
- ++hex;
- }
- ++t;
- }
- }
-
- return r;
-}
-
-/* convert hex, precede by a 1-byte length */
-uint16_t * zparser_conv_hex_length(const char *hex, size_t len)
-{
- uint16_t *r = NULL;
- uint8_t *t;
- int i;
- if (len % 2 != 0) {
- zc_error_prev_line("number of hex digits must be a "
- "multiple of 2");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else if (len > 255 * 2) {
- zc_error_prev_line("hex data exceeds 255 bytes");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- uint8_t *l;
-
- /* the length part */
- r = alloc_rdata(len / 2 + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- t = (uint8_t *)(r + 1);
-
- l = t++;
- *l = '\0';
-
- /* Now process octet by octet... */
- while (*hex) {
- *t = 0;
- for (i = 16; i >= 1; i -= 15) {
- if (isxdigit((int)*hex)) {
- *t += hexdigit_to_int(*hex) * i;
- } else {
- zc_error_prev_line(
- "illegal hex character '%c'",
- (int) *hex);
- parser->error_occurred =
- KNOTDZCOMPILE_EBRDATA;
- free(r);
- return NULL;
- }
- ++hex;
- }
- ++t;
- ++*l;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_time(const char *time)
-{
- /* convert a time YYHM to wireformat */
- uint16_t *r = NULL;
- struct tm tm;
-
- /* Try to scan the time... */
- if (!strptime(time, "%Y%m%d%H%M%S", &tm)) {
- zc_error_prev_line("date and time is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- uint32_t l = htonl(mktime_from_utc(&tm));
- r = alloc_rdata_init(&l, sizeof(l));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_services(const char *protostr, char *servicestr)
-{
- /*
- * Convert a protocol and a list of service port numbers
- * (separated by spaces) in the rdata to wireformat
- */
- uint16_t *r = NULL;
- uint8_t *p;
- uint8_t bitmap[65536/8];
- char sep[] = " ";
- char *word;
- int max_port = -8;
- /* convert a protocol in the rdata to wireformat */
- struct protoent *proto;
-
- memset(bitmap, 0, sizeof(bitmap));
-
- proto = getprotobyname(protostr);
- if (!proto) {
- proto = getprotobynumber(atoi(protostr));
- }
- if (!proto) {
- zc_error_prev_line("unknown protocol '%s'", protostr);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
-
- char *sp = 0;
- while ((word = strtok_r(servicestr, sep, &sp))) {
- struct servent *service = NULL;
- int port;
-
- service = getservbyname(word, proto->p_name);
- if (service) {
- /* Note: ntohs not ntohl! Strange but true. */
- port = ntohs((uint16_t) service->s_port);
-// printf("assigned port %d\n", port);
- } else {
-// printf("else\n");
- char *end;
- port = strtol(word, &end, 10);
- if (*end != '\0') {
- zc_error_prev_line(
- "unknown service '%s' for"
- " protocol '%s'",
- word, protostr);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- }
-
- if (port < 0 || port > 65535) {
- zc_error_prev_line("bad port number %d", port);
- } else {
- set_bit(bitmap, port);
- if (port > max_port) {
- max_port = port;
- }
- }
- servicestr = NULL;
- }
-
- r = alloc_rdata(sizeof(uint8_t) + max_port / 8 + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- p = (uint8_t *)(r + 1);
- *p = proto->p_proto;
- memcpy(p + 1, bitmap, *r - 1);
-
- return r;
-}
-
-uint16_t * zparser_conv_serial(const char *serialstr)
-{
- uint16_t *r = NULL;
- uint32_t serial;
- const char *t;
-
- serial = strtoserial(serialstr, &t);
- if (*t != '\0') {
- zc_error_prev_line("serial is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- serial = htonl(serial);
- r = alloc_rdata_init(&serial, sizeof(serial));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_period(const char *periodstr)
-{
- /* convert a time period (think TTL's) to wireformat) */
- uint16_t *r = NULL;
- uint32_t period;
- const char *end;
-
- /* Allocate required space... */
- period = strtottl(periodstr, &end);
- if (*end != '\0') {
- zc_error_prev_line("time period is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- period = htonl(period);
- r = alloc_rdata_init(&period, sizeof(period));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_short(const char *text)
-{
- uint16_t *r = NULL;
- uint16_t value;
- char *end;
-
- value = htons((uint16_t) strtol(text, &end, 10));
- if (*end != '\0') {
- zc_error_prev_line("integer value is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(&value, sizeof(value));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_byte(const char *text)
-{
- uint16_t *r = NULL;
- uint8_t value;
- char *end;
-
- value = (uint8_t) strtol(text, &end, 10);
- if (*end != '\0') {
- zc_error_prev_line("integer value is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(&value, sizeof(value));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_algorithm(const char *text)
-{
- const knot_lookup_table_t *alg;
- uint8_t id;
-
- alg = knot_lookup_by_name(dns_algorithms, text);
- if (alg) {
- id = (uint8_t) alg->id;
- } else {
- char *end;
- id = (uint8_t) strtol(text, &end, 10);
- if (*end != '\0') {
- zc_error_prev_line("algorithm is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- }
-
- uint16_t *r = alloc_rdata_init(&id, sizeof(id));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- return r;
-}
-
-uint16_t * zparser_conv_certificate_type(const char *text)
-{
- /* convert a algoritm string to integer */
- const knot_lookup_table_t *type;
- uint16_t id;
-
- type = knot_lookup_by_name(dns_certificate_types, text);
- if (type) {
- id = htons((uint16_t) type->id);
- } else {
- char *end;
- id = htons((uint16_t) strtol(text, &end, 10));
- if (*end != '\0') {
- zc_error_prev_line("certificate type is expected");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- }
-
- uint16_t *r = alloc_rdata_init(&id, sizeof(id));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- return r;
-}
-
-uint16_t * zparser_conv_a(const char *text)
-{
- in_addr_t address;
- uint16_t *r = NULL;
-
- if (inet_pton(AF_INET, text, &address) != 1) {
- zc_error_prev_line("invalid IPv4 address '%s'", text);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(&address, sizeof(address));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
-
- return r;
-}
-
-uint16_t * zparser_conv_aaaa(const char *text)
-{
- uint8_t address[IP6ADDRLEN];
- uint16_t *r = NULL;
-
- if (inet_pton(AF_INET6, text, address) != 1) {
- zc_error_prev_line("invalid IPv6 address '%s'", text);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(address, sizeof(address));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_text(const char *text, size_t len)
-{
- uint16_t *r = NULL;
-
- dbg_zp("Converting text: %s\n", text);
-
- if (len > 255) {
- zc_error_prev_line("text string is longer than 255 characters,"
- " try splitting it into multiple parts");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- uint8_t *p;
- r = alloc_rdata(len + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- p = (uint8_t *)(r + 1);
- *p = len;
- memcpy(p + 1, text, len);
- }
- return r;
-}
-
-uint16_t * zparser_conv_dns_name(const uint8_t *name, size_t len)
-{
- uint16_t *r = NULL;
- uint8_t *p = NULL;
- r = alloc_rdata(len);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- p = (uint8_t *)(r + 1);
- memcpy(p, name, len);
-
- return r;
-}
-
-uint16_t * zparser_conv_b32(const char *b32)
-{
- uint8_t buffer[B64BUFSIZE];
- uint16_t *r = NULL;
- size_t i = B64BUFSIZE - 1;
-
- if (strcmp(b32, "-") == 0) {
- r = alloc_rdata_init("", 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- return r;
- }
-
- /*!< \todo BLEEDING EYES! */
-
- char b32_copy[strlen(b32) + 1];
-
- for (int i = 0; i < strlen(b32); i++) {
- b32_copy[i] = toupper(b32[i]);
- }
-
- /*!< \todo BLEEDING EYES! */
- b32_copy[strlen(b32)] = '\0';
-
- int32_t b32_ret = base32hex_decode((uint8_t *)b32_copy, strlen(b32_copy),
- buffer + 1, i);
-
- i = b32_ret;
-
- if (b32_ret <= 0) {
- zc_error_prev_line("invalid base32 data");
- parser->error_occurred = 1;
- } else {
- buffer[0] = i; /* store length byte */
- r = alloc_rdata_init(buffer, i + 1);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_b64(const char *b64)
-{
- uint8_t buffer[B64BUFSIZE];
- uint16_t *r = NULL;
- int i;
-
- i = b64_pton(b64, buffer, B64BUFSIZE);
- if (i == -1) {
- zc_error_prev_line("invalid base64 data\n");
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- r = alloc_rdata_init(buffer, i);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_rrtype(const char *text)
-{
- uint16_t *r = NULL;
- uint16_t type = knot_rrtype_from_string(text);
-
- if (type == 0) {
- zc_error_prev_line("unrecognized RR type '%s'", text);
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- } else {
- type = htons(type);
- r = alloc_rdata_init(&type, sizeof(type));
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
- }
- return r;
-}
-
-uint16_t * zparser_conv_nxt(uint8_t nxtbits[])
-{
- /* nxtbits[] consists of 16 bytes with some zero's in it
- * copy every byte with zero to r and write the length in
- * the first byte
- */
- uint16_t i;
- uint16_t last = 0;
-
- for (i = 0; i < 16; i++) {
- if (nxtbits[i] != 0) {
- last = i + 1;
- }
- }
-
- uint16_t *r = alloc_rdata_init(nxtbits, last);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- return NULL;
- }
-
- return r;
-}
-
-
-/* we potentially have 256 windows, each one is numbered. empty ones
- * should be discarded
- */
-uint16_t * zparser_conv_nsec(uint8_t nsecbits[NSEC_WINDOW_COUNT]
- [NSEC_WINDOW_BITS_SIZE])
-{
- /* nsecbits contains up to 64K of bits which represent the
- * types available for a name. Walk the bits according to
- * nsec++ draft from jakob
- */
- uint16_t *r;
- uint8_t *ptr;
- size_t i, j;
- uint16_t window_count = 0;
- uint16_t total_size = 0;
- uint16_t window_max = 0;
-
- /* The used windows. */
- int used[NSEC_WINDOW_COUNT];
- /* The last byte used in each the window. */
- int size[NSEC_WINDOW_COUNT];
-
- window_max = 1 + (nsec_highest_rcode / 256);
-
- /* used[i] is the i-th window included in the nsec
- * size[used[0]] is the size of window 0
- */
-
- /* walk through the 256 windows */
- for (i = 0; i < window_max; ++i) {
- int empty_window = 1;
- /* check each of the 32 bytes */
- for (j = 0; j < NSEC_WINDOW_BITS_SIZE; ++j) {
- if (nsecbits[i][j] != 0) {
- size[i] = j + 1;
- empty_window = 0;
- }
- }
- if (!empty_window) {
- used[window_count] = i;
- window_count++;
- }
- }
-
- for (i = 0; i < window_count; ++i) {
- total_size += sizeof(uint16_t) + size[used[i]];
- }
-
- r = alloc_rdata(total_size);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return NULL;
- }
- ptr = (uint8_t *)(r + 1);
-
- /* now walk used and copy it */
- for (i = 0; i < window_count; ++i) {
- ptr[0] = used[i];
- ptr[1] = size[used[i]];
- memcpy(ptr + 2, &nsecbits[used[i]], size[used[i]]);
- ptr += size[used[i]] + 2;
- }
-
- return r;
-}
-
-/* Parse an int terminated in the specified range. */
-static int parse_int(const char *str,
- char **end,
- int *result,
- const char *name,
- int min,
- int max)
-{
- long value;
- value = strtol(str, end, 10);
- if (value < min || value > max) {
- zc_error_prev_line("%s must be within the range [%d .. %d]",
- name,
- min,
- max);
- return 0;
- } else {
- *result = (int) value;
- return 1;
- }
-}
-
-/* RFC1876 conversion routines */
-static uint32_t poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
- 1000000, 10000000, 100000000, 1000000000
- };
-
-/*
- * Converts ascii size/precision X * 10**Y(cm) to 0xXY.
- * Sets the given pointer to the last used character.
- *
- */
-static uint8_t precsize_aton(char *cp, char **endptr)
-{
- unsigned int mval = 0, cmval = 0;
- uint8_t retval = 0;
- int exponent;
- int mantissa;
-
- while (isdigit((int)*cp)) {
- mval = mval * 10 + hexdigit_to_int(*cp++);
- }
-
- if (*cp == '.') { /* centimeters */
- cp++;
- if (isdigit((int)*cp)) {
- cmval = hexdigit_to_int(*cp++) * 10;
- if (isdigit((int)*cp)) {
- cmval += hexdigit_to_int(*cp++);
- }
- }
- }
-
- if (mval >= poweroften[7]) {
- /* integer overflow possible for *100 */
- mantissa = mval / poweroften[7];
- exponent = 9; /* max */
- } else {
- cmval = (mval * 100) + cmval;
-
- for (exponent = 0; exponent < 9; exponent++)
- if (cmval < poweroften[exponent+1]) {
- break;
- }
-
- mantissa = cmval / poweroften[exponent];
- }
- if (mantissa > 9) {
- mantissa = 9;
- }
-
- retval = (mantissa << 4) | exponent;
-
- if (*cp == 'm') {
- cp++;
- }
-
- *endptr = cp;
-
- return (retval);
-}
-
-/*
- * Parses a specific part of rdata.
- *
- * Returns:
- *
- * number of elements parsed
- * zero on error
- *
- */
-uint16_t * zparser_conv_loc(char *str)
-{
- uint16_t *r;
- uint32_t *p;
- int i;
- int deg, min, secs; /* Secs is stored times 1000. */
- uint32_t lat = 0, lon = 0, alt = 0;
- /* encoded defaults: version=0 sz=1m hp=10000m vp=10m */
- uint8_t vszhpvp[4] = {0, 0x12, 0x16, 0x13};
- char *start;
- double d;
-
- for (;;) {
- deg = min = secs = 0;
-
- /* Degrees */
- if (*str == '\0') {
- zc_error_prev_line("unexpected end of LOC data");
- return NULL;
- }
-
- if (!parse_int(str, &str, &deg, "degrees", 0, 180)) {
- return NULL;
- }
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after degrees");
- return NULL;
- }
- ++str;
-
- /* Minutes? */
- if (isdigit((int)*str)) {
- if (!parse_int(str, &str, &min, "minutes", 0, 60)) {
- return NULL;
- }
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after minutes");
- return NULL;
- }
- ++str;
- }
-
- /* Seconds? */
- if (isdigit((int)*str)) {
- start = str;
- if (!parse_int(str, &str, &i, "seconds", 0, 60)) {
- return NULL;
- }
-
- if (*str == '.' && !parse_int(str + 1, &str, &i,
- "seconds fraction",
- 0, 999)) {
- return NULL;
- }
-
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after seconds");
- return NULL;
- }
-
- d = strtod(start, &start);
- if (errno != 0) {
- zc_error_prev_line("error parsing seconds");
- }
-
- if (d < 0.0 || d > 60.0) {
- zc_error_prev_line(
- "seconds not in range 0.0 .. 60.0");
- }
-
- secs = (int)(d * 1000.0 + 0.5);
- ++str;
- }
-
- switch (*str) {
- case 'N':
- case 'n':
- lat = ((uint32_t)1 << 31) +
- (deg * 3600000 + min * 60000 + secs);
- break;
- case 'E':
- case 'e':
- lon = ((uint32_t)1 << 31) +
- (deg * 3600000 + min * 60000 + secs);
- break;
- case 'S':
- case 's':
- lat = ((uint32_t)1 << 31) -
- (deg * 3600000 + min * 60000 + secs);
- break;
- case 'W':
- case 'w':
- lon = ((uint32_t)1 << 31) -
- (deg * 3600000 + min * 60000 + secs);
- break;
- default:
- zc_error_prev_line(
- "invalid latitude/longtitude: '%c'", *str);
- return NULL;
- }
- ++str;
-
- if (lat != 0 && lon != 0) {
- break;
- }
-
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected after"
- " latitude/longitude");
- return NULL;
- }
- ++str;
- }
-
- /* Altitude */
- if (*str == '\0') {
- zc_error_prev_line("unexpected end of LOC data");
- return NULL;
- }
-
- if (!isspace((int)*str)) {
- zc_error_prev_line("space expected before altitude");
- return NULL;
- }
- ++str;
-
- start = str;
-
- /* Sign */
- if (*str == '+' || *str == '-') {
- ++str;
- }
-
- /* Meters of altitude... */
- int ret = strtol(str, &str, 10);
- UNUSED(ret); // Result checked in following switch
-
- switch (*str) {
- case ' ':
- case '\0':
- case 'm':
- break;
- case '.':
- if (!parse_int(str + 1, &str, &i, "altitude fraction", 0, 99)) {
- return NULL;
- }
- if (!isspace((int)*str) && *str != '\0' && *str != 'm') {
- zc_error_prev_line("altitude fraction must be a number");
- return NULL;
- }
- break;
- default:
- zc_error_prev_line("altitude must be expressed in meters");
- return NULL;
- }
- if (!isspace((int)*str) && *str != '\0') {
- ++str;
- }
-
- d = strtod(start, &start);
- if (errno != 0) {
- zc_error_prev_line("error parsing altitued");
- }
-
- alt = (uint32_t)(10000000.0 + d * 100 + 0.5);
-
- if (!isspace((int)*str) && *str != '\0') {
- zc_error_prev_line("unexpected character after altitude");
- return NULL;
- }
-
- /* Now parse size, horizontal precision and vertical precision if any */
- for (i = 1; isspace((int)*str) && i <= 3; i++) {
- vszhpvp[i] = precsize_aton(str + 1, &str);
-
- if (!isspace((int)*str) && *str != '\0') {
- zc_error_prev_line("invalid size or precision");
- return NULL;
- }
- }
-
- /* Allocate required space... */
- r = alloc_rdata(16);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- p = (uint32_t *)(r + 1);
-
- memmove(p, vszhpvp, 4);
- write_uint32(p + 1, lat);
- write_uint32(p + 2, lon);
- write_uint32(p + 3, alt);
-
- return r;
-}
-
-/*
- * Convert an APL RR RDATA element.
- */
-uint16_t * zparser_conv_apl_rdata(char *str)
-{
- int negated = 0;
- uint16_t address_family;
- uint8_t prefix;
- uint8_t maximum_prefix;
- uint8_t length;
- uint8_t address[IP6ADDRLEN];
- char *colon = strchr(str, ':');
- char *slash = strchr(str, '/');
- int af;
- int rc;
- uint16_t rdlength;
- uint16_t *r;
- uint8_t *t;
- char *end;
- long p;
-
- if (!colon) {
- zc_error_prev_line("address family separator is missing");
- return NULL;
- }
- if (!slash) {
- zc_error_prev_line("prefix separator is missing");
- return NULL;
- }
-
- *colon = '\0';
- *slash = '\0';
-
- if (*str == '!') {
- negated = 1;
- ++str;
- }
-
- if (strcmp(str, "1") == 0) {
- address_family = htons(1);
- af = AF_INET;
- length = sizeof(in_addr_t);
- maximum_prefix = length * 8;
- } else if (strcmp(str, "2") == 0) {
- address_family = htons(2);
- af = AF_INET6;
- length = IP6ADDRLEN;
- maximum_prefix = length * 8;
- } else {
- zc_error_prev_line("invalid address family '%s'", str);
- return NULL;
- }
-
- rc = inet_pton(af, colon + 1, address);
- if (rc == 0) {
- zc_error_prev_line("invalid address '%s'", colon + 1);
- return NULL;
- } else if (rc == -1) {
- char ebuf[256] = {0};
- strerror_r(errno, ebuf, sizeof(ebuf));
- zc_error_prev_line("inet_pton failed: %s", ebuf);
- return NULL;
- }
-
- /* Strip trailing zero octets. */
- while (length > 0 && address[length - 1] == 0) {
- --length;
- }
-
-
- p = strtol(slash + 1, &end, 10);
- if (p < 0 || p > maximum_prefix) {
- zc_error_prev_line("prefix not in the range 0 .. %d",
- maximum_prefix);
- return NULL;
- } else if (*end != '\0') {
- zc_error_prev_line("invalid prefix '%s'", slash + 1);
- return NULL;
- }
- prefix = (uint8_t) p;
-
- rdlength = (sizeof(address_family) + sizeof(prefix) + sizeof(length)
- + length);
- r = alloc_rdata(rdlength);
- if (r == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- t = (uint8_t *)(r + 1);
-
- memcpy(t, &address_family, sizeof(address_family));
- t += sizeof(address_family);
- memcpy(t, &prefix, sizeof(prefix));
- t += sizeof(prefix);
- memcpy(t, &length, sizeof(length));
- if (negated) {
- *t |= APL_NEGATION_MASK;
- }
- t += sizeof(length);
- memcpy(t, address, length);
-
- return r;
-}
-
-/*
- * Below some function that also convert but not to wireformat
- * but to "normal" (int,long,char) types
- */
-
-uint32_t zparser_ttl2int(const char *ttlstr, int *error)
-{
- /* convert a ttl value to a integer
- * return the ttl in a int
- * -1 on error
- */
-
- uint32_t ttl;
- const char *t;
-
- ttl = strtottl(ttlstr, &t);
- if (*t != 0) {
- zc_error_prev_line("invalid TTL value: %s", ttlstr);
- *error = 1;
- }
-
- return ttl;
-}
-
-void zadd_rdata_wireformat(uint16_t *data)
-{
- parser->temporary_items[parser->rdata_count].raw_data = data;
- parser->rdata_count++;
-}
-
-/**
- * Used for TXT RR's to grow with undefined number of strings.
- */
-void zadd_rdata_txt_wireformat(uint16_t *data, int first)
-{
- if (data == NULL) {
- parser->error_occurred = KNOTDZCOMPILE_EBRDATA;
- return;
- }
- dbg_zp("Adding text!\n");
- knot_rdata_item_t *rd;
-
- /* First STR in str_seq, allocate 65K in first unused rdata
- * else find last used rdata */
- if (first) {
- rd = &parser->temporary_items[parser->rdata_count];
- rd->raw_data = alloc_rdata(65535 * sizeof(uint8_t));
- if (rd->raw_data == NULL) {
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- }
- parser->rdata_count++;
- rd->raw_data[0] = 0;
- } else {
- rd = &parser->temporary_items[parser->rdata_count-1];
- }
-
- if (rd == NULL || rd->raw_data == NULL) {
- return;
- }
-
- if ((size_t)rd->raw_data[0] + (size_t)data[0] > 65535) {
- zc_error_prev_line("too large rdata element");
- return;
- }
-
- memcpy((uint8_t *)rd->raw_data + 2 + rd->raw_data[0],
- data + 1, data[0]);
- rd->raw_data[0] += data[0];
- free(data);
- dbg_zp("Item after add\n");
-// hex_print(rd->raw_data + 1, rd->raw_data[0]);
-}
-
-void zadd_rdata_domain(knot_dname_t *dname)
-{
- knot_dname_retain(dname);
-// printf("Adding rdata name: %s %p\n", dname->name, dname);
- parser->temporary_items[parser->rdata_count].dname = dname;
- parser->rdata_count++;
-}
-
-void parse_unknown_rdata(uint16_t type, uint16_t *wireformat)
-{
- dbg_rdata("parsing unknown rdata for type: %s (%d)\n",
- knot_rrtype_to_string(type), type);
- uint16_t size;
- ssize_t rdata_count;
- ssize_t i;
- knot_rdata_item_t *items = NULL;
-
- if (wireformat) {
- size = *wireformat;
- } else {
- return;
- }
-
- rdata_count = rdata_wireformat_to_rdata_atoms(wireformat + 1, type,
- size, &items);
- dbg_rdata("got %d items\n", rdata_count);
- if (rdata_count < 0) {
- dbg_rdata("wf to items returned error: %s (%d)\n",
- error_to_str(knot_zcompile_error_msgs, rdata_count),
- rdata_count);
- zc_error_prev_line("bad unknown RDATA\n");
- /*!< \todo leaks */
- return;
- }
-
- for (i = 0; i < rdata_count; ++i) {
- if (rdata_atom_is_domain(type, i)) {
- zadd_rdata_domain(items[i].dname);
- } else {
- //XXX won't this create size two times?
- zadd_rdata_wireformat((uint16_t *)items[i].raw_data);
- }
- }
- free(items);
- /* Free wireformat */
- free(wireformat);
-
- dbg_rdata("parse_unknown_rdata: Successfuly parsed unknown rdata.\n");
-}
-
-void set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE],
- uint16_t index)
-{
- /*
- * The bits are counted from left to right, so bit #0 is the
- * left most bit.
- */
- uint8_t window = index / 256;
- uint8_t bit = index % 256;
-
- bits[window][bit / 8] |= (1 << (7 - bit % 8));
-}
-
-/*! @} */
diff --git a/src/zcompile/parser-util.h b/src/zcompile/parser-util.h
deleted file mode 100644
index 57258dc..0000000
--- a/src/zcompile/parser-util.h
+++ /dev/null
@@ -1,357 +0,0 @@
-/*!
- * \file parser-util.h
- *
- * \author NLnet Labs
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- * Minor modifications by CZ.NIC, z.s.p.o.
- *
- * \brief Zone compiler utility functions.
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _KNOTD_PARSER_UTIL_H_
-#define _KNOTD_PARSER_UTIL_H_
-
-#include <assert.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
-#include <netinet/in.h>
-#include <netdb.h>
-
-#include "zcompile/zcompile.h"
-#include "libknot/util/descriptor.h"
-
-int inet_pton4(const char *src, uint8_t *dst);
-int inet_pton6(const char *src, uint8_t *dst);
-//int my_b32_pton(const char *src, uint8_t *target, size_t tsize);
-const char *inet_ntop4(const u_char *src, char *dst, size_t size);
-const char *inet_ntop6(const u_char *src, char *dst, size_t size);
-int inet_pton(int af, const char *src, void *dst);
-void b64_initialize_rmap();
-int b64_pton_do(char const *src, uint8_t *target, size_t targsize);
-int b64_pton_len(char const *src);
-int b64_pton(char const *src, uint8_t *target, size_t targsize);
-void set_bit(uint8_t bits[], size_t index);
-uint32_t strtoserial(const char *nptr, const char **endptr);
-void write_uint32(void *dst, uint32_t data);
-uint32_t strtottl(const char *nptr, const char **endptr);
-time_t mktime_from_utc(const struct tm *tm);
-
-/*!< Conversions from text to wire. */
-/*!
- * \brief Converts hex text format to wireformat.
- *
- * \param hex String to be converted.
- * \param len Length of string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_hex(const char *hex, size_t len);
-
-/*!
- * \brief Converts hex text format with length to wireformat.
- *
- * \param hex String to be converted/.
- * \param len Length of string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_hex_length(const char *hex, size_t len);
-
-/*!
- * \brief Converts time string to wireformat.
- *
- * \param time Time string to be converted.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_time(const char *time);
-/*!
- * \brief Converts a protocol and a list of service port numbers
- * (separated by spaces) in the rdata to wireformat
- *
- * \param protostr Protocol string.
- * \param servicestr Service string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_services(const char *protostr, char *servicestr);
-
-/*!
- * \brief Converts serial to wireformat.
- *
- * \param serialstr Serial string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_serial(const char *serialstr);
-/*!
- * \brief Converts period to wireformat.
- *
- * \param periodstr Period string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_period(const char *periodstr);
-
-/*!
- * \brief Converts short int to wireformat.
- *
- * \param text String containing short int.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_short(const char *text);
-
-/*!
- * \brief Converts long int to wireformat.
- *
- * \param text String containing long int.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_long(const char *text);
-
-/*!
- * \brief Converts byte to wireformat.
- *
- * \param text String containing byte.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_byte(const char *text);
-
-/*!
- * \brief Converts A rdata string to wireformat.
- *
- * \param text String containing A rdata.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_a(const char *text);
-
-/*!
- * \brief Converts AAAA rdata string to wireformat.
- *
- * \param text String containing AAAA rdata.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_aaaa(const char *text);
-
-/*!
- * \brief Converts text string to wireformat.
- *
- * \param text Text string.
- * \param len Length of string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_text(const char *text, size_t len);
-
-/*!
- * \brief Converts domain name string to wireformat.
- *
- * \param name Domain name string.
- * \param len Length of string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_dns_name(const uint8_t* name, size_t len);
-
-/*!
- * \brief Converts base32 encoded string to wireformat.
- * TODO consider replacing with our implementation.
- *
- * \param b32 Base32 encoded string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_b32(const char *b32);
-
-/*!
- * \brief Converts base64 encoded string to wireformat.
- * TODO consider replacing with our implementation.
- *
- * \param b64 Base64 encoded string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_b64(const char *b64);
-
-/*!
- * \brief Converts RR type string to wireformat.
- *
- * \param rr RR type string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_rrtype(const char *rr);
-
-/*!
- * \brief Converts NXT string to wireformat.
- *
- * \param nxtbits NXT string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_nxt(uint8_t *nxtbits);
-
-/*!
- * \brief Converts NSEC bitmap to wireformat.
- *
- * \param nsecbits[][] NSEC bits.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_nsec(uint8_t nsecbits[NSEC_WINDOW_COUNT]
- [NSEC_WINDOW_BITS_SIZE]);
-/*!
- * \brief Converts LOC string to wireformat.
- *
- * \param str LOC string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_loc(char *str);
-
-/*!
- * \brief Converts algorithm string to wireformat.
- *
- * \param algstr Algorithm string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_algorithm(const char *algstr);
-
-/*!
- * \brief Converts certificate type string to wireformat.
- *
- * \param typestr Certificate type mnemonic string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_certificate_type(const char *typestr);
-
-/*!
- * \brief Converts APL data to wireformat.
- *
- * \param str APL data string.
- *
- * \return Converted wireformat.
- */
-uint16_t *zparser_conv_apl_rdata(char *str);
-
-/*!
- * \brief Parses unknown rdata.
- *
- * \param type Type of data.
- * \param wireformat Wireformat of data.
- *
- * \return Converted wireformat.
- */
-void parse_unknown_rdata(uint16_t type, uint16_t *wireformat);
-
-/*!
- * \brief Converts TTL string to int.
- *
- * \param ttlstr String
- * \param error Error code.
- *
- * \return Converted wireformat.
- */
-uint32_t zparser_ttl2int(const char *ttlstr, int* error);
-
-/*!
- * \brief Adds wireformat to temporary list of rdata items.
- *
- * \param data Wireformat to be added.
- */
-void zadd_rdata_wireformat(uint16_t *data);
-
-/*!
- * \brief Adds TXT wireformat to temporary list of rdata items.
- *
- * \param data Wireformat to be added.
- * \param first This is first text to be added.
- */
-void zadd_rdata_txt_wireformat(uint16_t *data, int first);
-
-/*!
- * \brief Cleans after using zadd_rdata_txt_wireformat().
- */
-void zadd_rdata_txt_clean_wireformat();
-
-/*!
- * \brief Adds domain name to temporary list of rdata items.
- *
- * \param domain Domain name to be added.
- */
-void zadd_rdata_domain(knot_dname_t *domain);
-
-/*!
- * \brief Sets bit in NSEC bitmap.
- *
- * \param bits[][] NSEC bitmaps.
- * \param index Index on which bit is to be set.
- */
-void set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE],
- uint16_t index);
-
-/*!
- * \brief Allocate and init wireformat.
- *
- * \param data Data to be copied into newly created wireformat.
- * \param size Size of data.
- *
- * \return Allocated wireformat.
- */
-uint16_t *alloc_rdata_init(const void *data, size_t size);
-uint16_t rrsig_type_covered(knot_rrset_t *rrset);
-
-
-#endif /* _KNOTD_PARSER_UTIL_H_ */
-
-/*! @} */
diff --git a/src/zcompile/tests/unittests_zp_main.c b/src/zcompile/tests/unittests_zp_main.c
deleted file mode 100644
index 5d8c5e9..0000000
--- a/src/zcompile/tests/unittests_zp_main.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-#include "knot/common.h"
-#include "common/libtap/tap_unit.h"
-
-// Units to test
-#include "zcompile_tests.c"
-
-// Run all loaded units
-int main(int argc, char *argv[])
-{
- // Open log
- //log_init(LOG_UPTO(LOG_ERR), LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING));
-
- // Build test set
- unit_api *tests[] = {
- &zoneparser_tests_api, //! Zoneparser unit
- NULL
- };
-
- // Plan number of tests
- int id = 0;
- int test_count = 0;
- note("Units:");
- while (tests[id] != NULL) {
- note("- %s : %d tests", tests[id]->name,
- tests[id]->count(argc, argv));
- test_count += tests[id]->count(argc, argv);
- ++id;
- }
-
- plan(test_count);
-
- // Run tests
- id = 0;
- while (tests[id] != NULL) {
- diag("Testing unit: %s", tests[id]->name);
- tests[id]->run(argc, argv);
- ++id;
- }
-
- //log_close();
-
- // Evaluate
- return exit_status();
-}
-
diff --git a/src/zcompile/tests/zcompile_tests.c b/src/zcompile/tests/zcompile_tests.c
deleted file mode 100644
index 5d3dce6..0000000
--- a/src/zcompile/tests/zcompile_tests.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/* Copyright (C) 2011 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 <assert.h>
-
-#include "libknot/zone/zone.h"
-#include "knot/zone/zone-load.h"
-#include "knot/common.h"
-#include "libknot/rrset.h"
-#include "libknot/util/descriptor.h"
-#include "zcompile/zcompile.h"
-
-#ifdef TEST_WITH_LDNS
-#include "ldns/ldns.h"
-#endif
-
-static int zoneparser_tests_count(int argc, char *argv[]);
-static int zoneparser_tests_run(int argc, char *argv[]);
-
-/*
- * Unit API.
- */
-unit_api zoneparser_tests_api = {
- "Zoneparser",
- &zoneparser_tests_count,
- &zoneparser_tests_run
-};
-
-#ifdef TEST_WITH_LDNS
-/*
- * Unit implementation.
- */static int compare_wires_simple_zp(uint8_t *wire1,
- uint8_t *wire2, uint count)
-{
- int i = 0;
- while (i < count &&
- wire1[i] == wire2[i]) {
- i++;
- }
- return (!(count == i));
-}
-
-/* compares only one rdata */
-static int compare_rr_rdata_silent(knot_rdata_t *rdata, ldns_rr *rr,
- uint16_t type)
-{
- knot_rrtype_descriptor_t *desc =
- knot_rrtype_descriptor_by_type(type);
- for (int i = 0; i < rdata->count; i++) {
- /* TODO check for ldns "descriptors" as well */
- if (desc->wireformat[i] == KNOT_RDATA_WF_COMPRESSED_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_LITERAL_DNAME ||
- desc->wireformat[i] == KNOT_RDATA_WF_UNCOMPRESSED_DNAME) {
- assert(ldns_rr_rdf(rr, i));
- if (rdata->items[i].dname->size !=
- ldns_rdf_size(ldns_rr_rdf(rr, i))) {
- return 1;
- }
- if (compare_wires_simple_zp(rdata->items[i].dname->name,
- ldns_rdf_data(ldns_rr_rdf(rr, i)),
- rdata->items[i].dname->size) != 0) {
- return 1;
- }
- } else {
- if (ldns_rr_rdf(rr, i) == NULL &&
- rdata->items[i].raw_data[0] != 0) {
- return 1;
- } else {
- continue;
- }
- if (rdata->items[i].raw_data[0] !=
- ldns_rdf_size(ldns_rr_rdf(rr, i))) {
-
- /* ldns stores the size including the
- * length, dnslib does not */
- if (abs(rdata->items[i].raw_data[0] -
- ldns_rdf_size(ldns_rr_rdf(rr, i))) != 1) {
- return 1;
- }
- }
- if (compare_wires_simple_zp((uint8_t *)
- (rdata->items[i].raw_data + 1),
- ldns_rdf_data(ldns_rr_rdf(rr, i)),
- rdata->items[i].raw_data[0]) != 0) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-static int compare_rrset_w_ldns_rrset(const knot_rrset_t *rrset,
- ldns_rr_list *rrs,
- char check_rdata, char verbose)
-{
- /* We should have only one rrset from ldns, although it is
- * represented as rr_list ... */
-
- /* TODO errors */
-
- assert(rrs);
- assert(rrset);
-
- ldns_rr_list_sort(rrs);
-
- /* compare headers */
-
- ldns_rr *rr = ldns_rr_list_rr(rrs, 0);
-
- if (rrset->owner->size != ldns_rdf_size(ldns_rr_owner(rr))) {
- diag("RRSet owner names differ in length");
- if (!verbose) {
- return 1;
- }
- diag("ldns: %d, dnslib: %d", ldns_rdf_size(ldns_rr_owner(rr)),
- rrset->owner->size);
- diag("%s", knot_dname_to_str(rrset->owner));
- diag("%s", ldns_rdf_data(ldns_rr_owner(rr)));
- return 1;
- }
-
- if (compare_wires_simple_zp(rrset->owner->name,
- ldns_rdf_data(ldns_rr_owner(rr)),
- rrset->owner->size) != 0) {
- diag("RRSet owner wireformats differ");
- return 1;
- }
-
- if (rrset->type != ldns_rr_get_type(rr)) {
- diag("RRset types differ");
- if (!verbose) {
- return 1;
- }
- diag("Dnslib type: %d Ldns type: %d", rrset->type,
- ldns_rr_get_type(rr));
- return 1;
- }
-
- if (rrset->rclass != ldns_rr_get_class(rr)) {
- diag("RRset classes differ");
- return 1;
- }
-
- if (rrset->ttl != ldns_rr_ttl(rr)) {
- diag("RRset TTLs differ");
- if (!verbose) {
- return 1;
- }
- diag("dnslib: %d ldns: %d", rrset->ttl, ldns_rr_ttl(rr));
- return 1;
- }
-
- if (!check_rdata) {
- return 0;
- }
-
- /* compare rdatas */
-
- /* sort dnslib rdata */
-
- knot_rdata_t *tmp_rdata = rrset->rdata;
-
- rr = ldns_rr_list_pop_rr(rrs);
-
- char found;
-
- while (rr != NULL) {
- found = 0;
- tmp_rdata = rrset->rdata;
- while (!found &&
- tmp_rdata->next != rrset->rdata) {
- if (compare_rr_rdata_silent(tmp_rdata, rr,
- rrset->type) == 0) {
- found = 1;
- }
- tmp_rdata = tmp_rdata->next;
- }
-
- if (!found &&
- compare_rr_rdata_silent(tmp_rdata, rr, rrset->type) == 0) {
- found = 1;
- }
-
- /* remove the found rdata from list */
- if (!found) {
- diag("RRsets rdata differ");
- return 1;
- }
- ldns_rr_free(rr);
-
- rr = ldns_rr_list_pop_rr(rrs);
- }
-
- return 0;
-}
-
-int compare_zones(knot_zone_contents_t *zone,
- ldns_rr_list *ldns_list, char verbose)
-{
- /* TODO currently test fail when encountering first error -
- * it should finish going through the zone */
- knot_rrset_t *tmp_rrset = NULL;
-
- knot_dname_t *tmp_dname = NULL;
-
- knot_node_t *node = NULL;
-
- ldns_rr_list *ldns_rrset = ldns_rr_list_pop_rrset(ldns_list);
-
- if (ldns_rrset == NULL) {
- diag("Error: empty node");
- return 1;
- }
-
- ldns_rr *rr = NULL;
-
- /*
- * Following cycle works like this: First, we get RR from ldns rrset,
- * then we search for the node containing the rrset, then we get the
- * rrset, which is then compared with whole ldns rrset.
- */
-
- /* ldns_rr_list_pop_rrset should pop the first rrset */
- while (ldns_rrset != NULL) {
- rr = ldns_rr_list_rr(ldns_rrset, 0);
- tmp_dname =
- knot_dname_new_from_wire(ldns_rdf_data(ldns_rr_owner(rr)),
- ldns_rdf_size(ldns_rr_owner(rr)),
- NULL);
-
- node = knot_zone_contents_get_node(zone, tmp_dname);
-
- if (node == NULL) {
- node = knot_zone_contents_get_nsec3_node(zone,
- tmp_dname);
- }
-
- if (node == NULL) {
- diag("Could not find node");
- diag("%s", knot_dname_to_str(tmp_dname));
- return 1;
- }
-
- knot_dname_free(&tmp_dname);
-
- tmp_rrset = knot_node_get_rrset(node,
- ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset,
- 0)));
-
- if (tmp_rrset == NULL &&
- (uint)(ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset, 0))) !=
- (uint)KNOT_RRTYPE_RRSIG) {
- diag("Could not find rrset");
- if (!verbose) {
- return 1;
- }
- ldns_rr_list_print(stdout, ldns_rrset);
- diag("%s", knot_dname_to_str(node->owner));
- return 1;
- } else if ((uint)(ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset,
- 0))) ==
- (uint)KNOT_RRTYPE_RRSIG) {
- knot_rrset_t *rrsigs = NULL;
- /* read type covered from ldns rrset */
- for (int i = 0; i < ldns_rrset->_rr_count; i++) {
- uint16_t type_covered =
- ldns_rdf_data(ldns_rr_rdf(
- ldns_rr_list_rr(ldns_rrset, i), 0))[1];
-
- /*
- * Dnslib stores RRSIGs separately -
- * we have to find get it from its "parent"
- * rrset.
- */
-
- tmp_rrset = knot_node_get_rrset(node,
- type_covered);
-
- if (tmp_rrset == NULL) {
- if (!verbose) {
- return 1;
- }
- diag("following rrset "
- "could not be found");
- ldns_rr_list_print(stdout, ldns_rrset);
- return 1;
- }
-
- if (rrsigs == NULL) {
- rrsigs = tmp_rrset->rrsigs;
- } else {
- knot_rrset_merge((void *)&rrsigs,
- (void *)&(tmp_rrset->rrsigs));
- }
- }
- tmp_rrset = rrsigs;
- }
-
-/* diag("dnslib type: %d", tmp_rrset->type);
- diag("dnslib dname: %s", tmp_rrset->owner->name);
-
- diag("ldns type: %d",
- ldns_rr_get_type(ldns_rr_list_rr(ldns_rrset, 0)));
- diag("ldns dname : %s", ldns_rdf_data(ldns_rr_owner(
- ldns_rr_list_rr(ldns_rrset, 0)))); */
-
-// knot_rrset_dump(tmp_rrset, 1);
-
- if (compare_rrset_w_ldns_rrset(tmp_rrset, ldns_rrset,
- 1, 0) != 0) {
- diag("RRSets did not match");
-// knot_rrset_dump(tmp_rrset, 1);
- return 1;
- }
-
- ldns_rr_list_deep_free(ldns_rrset);
-
- ldns_rrset = ldns_rr_list_pop_rrset(ldns_list);
-
- if (ldns_rrset == NULL) {
- ldns_rrset = ldns_rr_list_pop_rrset(ldns_list);
- }
- }
-
- return 0;
-}
-
-#endif
-
-static int test_zoneparser_zone_read(const char *origin, const char *filename,
- const char *outfile)
-{
-#ifndef TEST_WITH_LDNS
- diag("Zoneparser tests without usage of ldns are not implemented");
- return 0;
-#endif
-
-#ifdef TEST_WITH_LDNS
- /* Calls zcompile. */
- parser = zparser_create();
- int ret = zone_read(origin, filename, outfile, 0);
- if (ret != 0) {
- diag("Could not load zone from file: %s", filename);
- return 0;
- }
-
- knot_zone_t *dnsl_zone = NULL;
- zloader_t *loader = NULL;
- if (knot_zload_open(&loader, outfile) != 0) {
- diag("Could not create zone loader.\n");
- return 0;
- }
- dnsl_zone = knot_zload_load(loader);
- remove(outfile);
- if (!dnsl_zone) {
- diag("Could not load dumped zone.\n");
- return 0;
- }
-
- ldns_zone *ldns_zone = NULL;
- FILE *f = fopen(filename, "r");
- if (ldns_zone_new_frm_fp(&ldns_zone, f, NULL,
- 0, LDNS_RR_CLASS_IN) != LDNS_STATUS_OK) {
- diag("Could not load zone from file: %s (ldns)", filename);
- return 0;
- }
-
-// ldns_zone_sort(ldns_zone);
-
- /*
- * LDNS stores SOA record independently - create a list with all
- * records in it.
- */
-
- ldns_rr_list *ldns_list = ldns_zone_rrs(ldns_zone);
-
- ldns_rr_list_push_rr(ldns_list, ldns_zone_soa(ldns_zone));
-
- if (compare_zones(dnsl_zone->contents, ldns_list, 0) != 0) {
- return 0;
- }
-
- knot_zone_deep_free(&dnsl_zone, 0);
- ldns_zone_free(ldns_zone);
- fclose(f);
- return 1;
-#endif
-}
-
-static const int ZONEPARSER_TEST_COUNT = 1;
-
-/*! API: return number of tests. */
-static int zoneparser_tests_count(int argc, char *argv[])
-{
- return ZONEPARSER_TEST_COUNT;
-}
-
-/*! API: run tests. */
-static int zoneparser_tests_run(int argc, char *argv[])
-{
- if (argc == 3) {
- ok(test_zoneparser_zone_read(argv[1], argv[2],
- "foo_test_zone"),
- "zoneparser: read (%s)",
- argv[2]);
- } else {
- diag("Wrong parameters\n usage: "
- "knot-zcompile-unittests origin zonefile");
- return 0;
- }
- return 1;
-}
diff --git a/src/zcompile/zcompile-error.c b/src/zcompile/zcompile-error.c
deleted file mode 100644
index 9357cde..0000000
--- a/src/zcompile/zcompile-error.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright (C) 2011 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 "zcompile/zcompile-error.h"
-
-#include "common/errors.h"
-
-/*! \brief Table linking error messages to error codes. */
-const error_table_t knot_zcompile_error_msgs[KNOTDZCOMPILE_ERROR_COUNT] = {
-
- /* Mapped errors. */
- {KNOTDZCOMPILE_EOK, "OK"},
- {KNOTDZCOMPILE_ENOMEM, "Not enough memory."},
- {KNOTDZCOMPILE_EINVAL, "Invalid parameter passed."},
- {KNOTDZCOMPILE_ENOTSUP, "Parameter not supported."},
- {KNOTDZCOMPILE_EBUSY, "Requested resource is busy."},
- {KNOTDZCOMPILE_EAGAIN,
- "The system lacked the necessary resource, try again."},
- {KNOTDZCOMPILE_EACCES,
- "Permission to perform requested operation is denied."},
- {KNOTDZCOMPILE_ECONNREFUSED, "Connection is refused."},
- {KNOTDZCOMPILE_EISCONN, "Already connected."},
- {KNOTDZCOMPILE_EADDRINUSE, "Address already in use."},
- {KNOTDZCOMPILE_ENOENT, "Resource not found."},
- {KNOTDZCOMPILE_ERANGE, "Value is out of range."},
-
- /* Custom errors. */
- {KNOTDZCOMPILE_ERROR, "Generic error."},
- {KNOTDZCOMPILE_EBRDATA, "Malformed RDATA."},
- {KNOTDZCOMPILE_ESOA, "Multiple SOA records."},
- {KNOTDZCOMPILE_EBADSOA, "SOA record has different owner "
- "than in config - parser will not continue!"},
- {KNOTDZCOMPILE_EBADNODE, "Error handling node."},
- {KNOTDZCOMPILE_EZONEINVAL, "Invalid zone file."},
- {KNOTDZCOMPILE_EPARSEFAIL, "Parser failed."},
- {KNOTDZCOMPILE_ENOIPV6, "IPv6 support disabled."},
- {KNOTDZCOMPILE_ESYNT, "Parser syntactic error."},
- {KNOTDZCOMPILE_ERROR, 0}
-};
diff --git a/src/zcompile/zcompile-error.h b/src/zcompile/zcompile-error.h
deleted file mode 100644
index c6d999c..0000000
--- a/src/zcompile/zcompile-error.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*!
- * \file zcompile-error.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- * \author Marek Vavrusa <marek.vavrusa@nic.cz>
- * \author Jan Kadlec <jan.kadlec@nic.cz>
- *
- * \brief Error codes and function for getting error message.
- *
- * \addtogroup zoneparser
- * @{
- */
-/* Copyright (C) 2011 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/>.
- */
-
-#ifndef _KNOTD_ZCOMPILE_ERROR_H_
-#define _KNOTD_ZCOMPILE_ERROR_H_
-
-#include "common/errors.h"
-
-/*!
- * \brief Error codes used in the server.
- *
- * Some viable errors are directly mapped
- * to libc errno codes.
- */
-enum knot_zcompile_error {
-
- /* Directly mapped error codes. */
- KNOTDZCOMPILE_EOK = 0,
- KNOTDZCOMPILE_ENOMEM = -ENOMEM, /*!< \brief Out of memory. */
- KNOTDZCOMPILE_EINVAL = -EINVAL, /*!< \brief Invalid parameter passed. */
- /*!
- * \brief Parameter not supported.
- */
- KNOTDZCOMPILE_ENOTSUP = -ENOTSUP,
- KNOTDZCOMPILE_EBUSY = -EBUSY, /*!< \brief Requested resource is busy. */
- /*!
- * \brief OS lacked necessary resources.
- */
- KNOTDZCOMPILE_EAGAIN = -EAGAIN,
- KNOTDZCOMPILE_EACCES = -EACCES, /*!< \brief Permission is denied. */
- /*!
- * \brief Connection is refused.
- */
- KNOTDZCOMPILE_ECONNREFUSED = -ECONNREFUSED,
- KNOTDZCOMPILE_EISCONN = -EISCONN, /*!< \brief Already connected. */
- /*!
- * \brief Address already in use.
- */
- KNOTDZCOMPILE_EADDRINUSE = -EADDRINUSE,
- KNOTDZCOMPILE_ENOENT = -ENOENT, /*!< \brief Resource not found. */
- KNOTDZCOMPILE_ERANGE = -ERANGE, /*!< \brief Value is out of range. */
-
- /* Custom error codes. */
- KNOTDZCOMPILE_ERROR = -16384, /*!< \brief Generic error. */
- KNOTDZCOMPILE_ESYNT, /*!< \brief Syntax error. */
- KNOTDZCOMPILE_EBADNODE, /*!< \brief Node error. */
- KNOTDZCOMPILE_EBRDATA, /*!< \brief RDATA error. */
- KNOTDZCOMPILE_EBADSOA, /*!< \brief SOA owner error. */
- KNOTDZCOMPILE_ESOA, /*!< \brief Multiple SOA records. */
-
- KNOTDZCOMPILE_EZONEINVAL, /*!< \brief Invalid zone file. */
- KNOTDZCOMPILE_EPARSEFAIL, /*!< \brief Parser fail. */
- KNOTDZCOMPILE_ENOIPV6, /*! \brief No IPv6 support. */
-
- KNOTDZCOMPILE_ERROR_COUNT = 22
-};
-
-typedef enum knot_zcompile_error knot_zcompile_error_t;
-
-/*! \brief Table linking error messages to error codes. */
-extern const error_table_t knot_zcompile_error_msgs[KNOTDZCOMPILE_ERROR_COUNT];
-
-#endif /* _KNOTD_ZCOMPILE_ERROR_H_ */
-
-/*! @} */
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
deleted file mode 100644
index 636a877..0000000
--- a/src/zcompile/zcompile.c
+++ /dev/null
@@ -1,694 +0,0 @@
-/*!
- * \file zcompile.c
- *
- * \author Jan Kadlec <jan.kadlec@nic.cz>. Minor portions of code taken from
- * NSD.
- *
- * \brief Zone compiler.
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/* Copyright (C) 2011 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 <config.h>
-#include <assert.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/stat.h>
-
-#include "common/base32hex.h"
-#include "common/log.h"
-#include "knot/other/debug.h"
-#include "zcompile/zcompile.h"
-#include "zcompile/parser-util.h"
-#include "zcompile/zcompile-error.h"
-#include "knot/zone/zone-dump.h"
-#include "libknot/zone/zone-diff.h"
-#include "libknot/libknot.h"
-#include "libknot/util/utils.h"
-
-/* Some global flags... */
-static int vflag = 0;
-/* if -v then print progress each 'progress' RRs */
-static int progress = 10000;
-
-/* Total errors counter */
-static long int totalerrors = 0;
-static long int totalrrs = 0;
-
-extern FILE *zp_get_in(void *scanner);
-
-/*!
- * \brief Adds RRSet to list.
- *
- * \param head Head of list.
- * \param rrsig RRSet to be added.
- */
-static int rrset_list_add(rrset_list_t **head, knot_rrset_t *rrsig)
-{
- if (*head == NULL) {
- *head = malloc(sizeof(rrset_list_t));
- if (*head == NULL) {
- ERR_ALLOC_FAILED;
- return KNOTDZCOMPILE_ENOMEM;
- }
- (*head)->next = NULL;
- (*head)->data = rrsig;
- } else {
- rrset_list_t *tmp = malloc(sizeof(*tmp));
- if (tmp == NULL) {
- ERR_ALLOC_FAILED;
- return KNOTDZCOMPILE_ENOMEM;
- }
- tmp->next = *head;
- tmp->data = rrsig;
- *head = tmp;
- }
-
- dbg_zp_verb("zp: rrset_add: Added RRSIG %p to list.\n", rrsig);
-
- return KNOTDZCOMPILE_EOK;
-}
-
-/*!
- * \brief Deletes RRSet list. Sets pointer to NULL.
- *
- * \param head Head of list to be deleted.
- */
-static void rrset_list_delete(rrset_list_t **head)
-{
- rrset_list_t *tmp;
- if (*head == NULL) {
- return;
- }
-
- while (*head != NULL) {
- tmp = *head;
- *head = (*head)->next;
- free(tmp);
- }
-
- *head = NULL;
-
- dbg_zp("zp: list_delete: List deleleted.\n");
-}
-
-static int find_rrset_for_rrsig_in_node(knot_zone_contents_t *zone,
- knot_node_t *node,
- knot_rrset_t *rrsig)
-{
- assert(rrsig != NULL);
- assert(rrsig->rdata->items[0].raw_data);
- assert(node);
-
- assert(knot_dname_compare(rrsig->owner, node->owner) == 0);
-
- knot_rrset_t *tmp_rrset =
- knot_node_get_rrset(node, rrsig_type_covered(rrsig));
-
- int ret;
-
- if (tmp_rrset == NULL) {
- dbg_zp("zp: find_rr_for_sig_in_node: Node does not contain "
- "RRSet of type %s.\n",
- knot_rrtype_to_string(rrsig_type_covered(rrsig)));
- tmp_rrset = knot_rrset_new(rrsig->owner,
- rrsig_type_covered(rrsig),
- rrsig->rclass,
- rrsig->ttl);
- if (tmp_rrset == NULL) {
- dbg_zp("zp: find_rr_for_sig_in_node: Cannot create "
- "dummy RRSet.\n");
- return KNOT_ERROR;
- }
-
- ret = knot_zone_contents_add_rrset(zone, tmp_rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1);
- assert(ret <= 0);
- if (ret < 0) {
- dbg_zp("zp: Failed to add new dummy RRSet to the zone."
- "\n");
- return KNOT_ERROR;
- }
- }
-
- assert(tmp_rrset);
-
- if (tmp_rrset->ttl != rrsig->ttl) {
- char *name = knot_dname_to_str(tmp_rrset->owner);
- assert(name);
- log_zone_warning("RRSIG owned by: %s cannot be added to "
- "its RRSet, because their TTLs differ. "
- "Changing TTL to value=%d.\n",
- name, tmp_rrset->ttl);
- free(name);
- }
-
- ret = knot_zone_contents_add_rrsigs(zone, rrsig, &tmp_rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1);
- if (ret < 0) {
- dbg_zp("zp: find_rr_for_sig: Cannot add RRSIG.\n");
- return KNOTDZCOMPILE_EINVAL;
- } else if (ret > 0) {
- knot_rrset_free(&rrsig);
- }
-
- assert(tmp_rrset->rrsigs != NULL);
-
- return KNOTDZCOMPILE_EOK;
-}
-
-static knot_node_t *create_node(knot_zone_contents_t *zone,
- knot_rrset_t *current_rrset,
- int (*node_add_func)(knot_zone_contents_t *zone, knot_node_t *node,
- int create_parents, uint8_t, int),
- knot_node_t *(*node_get_func)(const knot_zone_contents_t *zone,
- const knot_dname_t *owner))
-{
- dbg_zp_verb("zp: create_node: Creating node using RRSet: %p.\n",
- current_rrset);
- knot_node_t *node =
- knot_node_new(current_rrset->owner, NULL, 0);
- if (node_add_func(zone, node, 1, 0, 1) != 0) {
- return NULL;
- }
-
- current_rrset->owner = node->owner;
-
- return node;
-}
-
-static void process_rrsigs_in_node(knot_zone_contents_t *zone,
- knot_node_t *node)
-{
- dbg_zp_verb("zp: process_rrsigs: Processing RRSIGS in node: %p.\n",
- node);
- rrset_list_t *tmp = parser->node_rrsigs;
- while (tmp != NULL) {
- if (find_rrset_for_rrsig_in_node(zone, node,
- tmp->data) != KNOT_EOK) {
- zc_error_prev_line("Could not add RRSIG to zone!\n");
- return;
- }
- tmp = tmp->next;
- }
-}
-
-int process_rr(void)
-{
- knot_zone_t *zone = parser->current_zone;
- assert(zone != NULL);
- knot_zone_contents_t *contents = knot_zone_get_contents(zone);
- assert(contents != NULL);
- knot_rrset_t *current_rrset = parser->current_rrset;
- knot_rrset_t *rrset;
- knot_rrtype_descriptor_t *descriptor =
- knot_rrtype_descriptor_by_type(current_rrset->type);
-
-dbg_zp_exec_detail(
- char *name = knot_dname_to_str(parser->current_rrset->owner);
- dbg_zp_detail("zp: process_rr: Processing RR owned by: %s .\n",
- name);
- free(name);
-);
- dbg_zp_verb("zp: process_rr: Processing type: %s.\n",
- knot_rrtype_to_string(parser->current_rrset->type));
- dbg_zp_verb("zp: process_rr: RDATA count: %d.\n",\
- parser->current_rrset->rdata->count);
-
- if (descriptor->fixed_items) {
- assert(current_rrset->rdata->count == descriptor->length);
- }
-
-
- assert(current_rrset->rdata->count > 0);
- assert(knot_dname_is_fqdn(current_rrset->owner));
-
- int (*node_add_func)(knot_zone_contents_t *, knot_node_t *, int,
- uint8_t, int);
- knot_node_t *(*node_get_func)(const knot_zone_contents_t *,
- const knot_dname_t *);
-
-
- /* If we have RRSIG of NSEC3 type first node will have
- * to be created in NSEC3 part of the zone */
-
- uint16_t type_covered = 0;
- if (current_rrset->type == KNOT_RRTYPE_RRSIG) {
- type_covered = rrsig_type_covered(current_rrset);
- }
-
- if (current_rrset->type != KNOT_RRTYPE_NSEC3 &&
- type_covered != KNOT_RRTYPE_NSEC3) {
- node_add_func = &knot_zone_contents_add_node;
- node_get_func = &knot_zone_contents_get_node;
- } else {
- node_add_func = &knot_zone_contents_add_nsec3_node;
- node_get_func = &knot_zone_contents_get_nsec3_node;
- }
-
- if ((current_rrset->type == KNOT_RRTYPE_SOA) && (zone != NULL)) {
- if (knot_node_rrset(knot_zone_contents_apex(contents),
- KNOT_RRTYPE_SOA) != NULL) {
- /* Receiving another SOA. */
- if (!knot_rrset_match(current_rrset,
- knot_node_rrset(knot_zone_contents_apex(contents),
- KNOT_RRTYPE_SOA), KNOT_RRSET_COMPARE_WHOLE)) {
- return KNOTDZCOMPILE_ESOA;
- } else {
- zc_warning_prev_line("encountered identical "
- "extra SOA record");
- return KNOTDZCOMPILE_EOK;
- }
- }
- }
-
- /*!< \todo Make sure the maximum RDLENGTH does not exceed 65535 bytes.*/
-
- if (current_rrset->type == KNOT_RRTYPE_SOA) {
- if (knot_dname_compare(current_rrset->owner,
- parser->origin_from_config) != 0) {
- zc_error_prev_line("SOA record has a different "
- "owner than the one specified "
- "in config! \n");
- /* Such SOA cannot even be added, because
- * it would not be in the zone apex. */
- return KNOTDZCOMPILE_EBADSOA;
- }
- }
-
- if (current_rrset->type == KNOT_RRTYPE_RRSIG) {
- /*!< \todo Use deep copy function here! */
- knot_rrset_t *tmp_rrsig =
- knot_rrset_new(current_rrset->owner,
- KNOT_RRTYPE_RRSIG,
- current_rrset->rclass,
- current_rrset->ttl);
- if (tmp_rrsig == NULL) {
- dbg_zp("zp: process_rr: Cannot create tmp RRSIG.\n");
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (knot_rrset_add_rdata(tmp_rrsig,
- current_rrset->rdata) != KNOT_EOK) {
- knot_rrset_free(&tmp_rrsig);
- dbg_zp("zp: process_rr: Cannot add data to tmp"
- " RRSIG.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- if (parser->last_node &&
- knot_dname_compare(parser->last_node->owner,
- current_rrset->owner) != 0) {
- /* RRSIG is first in the node, so we have to create it
- * before we return
- */
- if (parser->node_rrsigs != NULL) {
- process_rrsigs_in_node(contents,
- parser->last_node);
- rrset_list_delete(&parser->node_rrsigs);
- }
-
- /* The node might however been created previously. */
- parser->last_node =
- knot_zone_contents_get_node(contents,
- knot_rrset_owner(current_rrset));
-
- if (parser->last_node == NULL) {
- /* Try NSEC3 tree. */
- parser->last_node =
- knot_zone_contents_get_nsec3_node(
- contents,
- knot_rrset_owner(
- current_rrset));
- }
-
- if (parser->last_node == NULL) {
- /* Still NULL, node has to be created. */
- if ((parser->last_node = create_node(contents,
- current_rrset, node_add_func,
- node_get_func)) == NULL) {
- knot_rrset_free(&tmp_rrsig);
- dbg_zp("zp: process_rr: Cannot "
- "create new node.\n");
- return KNOTDZCOMPILE_EBADNODE;
- }
- }
- }
-
- if (rrset_list_add(&parser->node_rrsigs, tmp_rrsig) != 0) {
- dbg_zp("zp: process_rr: Cannot "
- "create new node.\n");
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- dbg_zp_verb("zp: process_rr: RRSIG proccesed successfully.\n");
- return KNOTDZCOMPILE_EOK;
- }
-
- /*! \todo Move RRSIG and RRSet handling to funtions. */
- assert(current_rrset->type != KNOT_RRTYPE_RRSIG);
-
- knot_node_t *node = NULL;
- /* \note this could probably be much simpler */
- if (parser->last_node && current_rrset->type != KNOT_RRTYPE_SOA &&
- knot_dname_compare(parser->last_node->owner,
- current_rrset->owner) ==
- 0) {
- node = parser->last_node;
- } else {
- if (parser->last_node && parser->node_rrsigs) {
- process_rrsigs_in_node(contents,
- parser->last_node);
- }
-
- rrset_list_delete(&parser->node_rrsigs);
-
- /* new node */
- node = node_get_func(contents, current_rrset->owner);
- }
-
- if (node == NULL) {
- if (parser->last_node && parser->node_rrsigs) {
- process_rrsigs_in_node(contents,
- parser->last_node);
- }
-
- if ((node = create_node(contents, current_rrset,
- node_add_func,
- node_get_func)) == NULL) {
- dbg_zp("zp: process_rr: Cannot "
- "create new node.\n");
- return KNOTDZCOMPILE_EBADNODE;
- }
- }
-
- rrset = knot_node_get_rrset(node, current_rrset->type);
- if (!rrset) {
- rrset = knot_rrset_new(current_rrset->owner,
- current_rrset->type,
- current_rrset->rclass,
- current_rrset->ttl);
- if (rrset == NULL) {
- dbg_zp("zp: process_rr: Cannot "
- "create new RRSet.\n");
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (knot_rrset_add_rdata(rrset, current_rrset->rdata) != 0) {
- knot_rrset_free(&rrset);
- dbg_zp("zp: process_rr: Cannot "
- "add RDATA to RRSet.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
-
- /* Selected merge option does not really matter here. */
- if (knot_zone_contents_add_rrset(contents, rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1) < 0) {
- knot_rrset_free(&rrset);
- dbg_zp("zp: process_rr: Cannot "
- "add RDATA to RRSet.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
- } else {
- if (current_rrset->type !=
- KNOT_RRTYPE_RRSIG && rrset->ttl !=
- current_rrset->ttl) {
- zc_warning_prev_line(
- "TTL does not match the TTL of the RRSet. "
- "Changing to %lu.\n", rrset->ttl);
- }
-
- if (knot_zone_contents_add_rrset(contents, current_rrset,
- &node,
- KNOT_RRSET_DUPL_MERGE, 1) < 0) {
- dbg_zp("zp: process_rr: Cannot "
- "merge RRSets.\n");
- return KNOTDZCOMPILE_EBRDATA;
- }
- }
-
- if (vflag > 1 && totalrrs > 0 && (totalrrs % progress == 0)) {
- zc_error_prev_line("Total errors: %ld\n", totalrrs);
- }
-
- parser->last_node = node;
- ++totalrrs;
-
- dbg_zp_verb("zp: process_rr: RRSet %p processed successfully.\n",
- parser->current_rrset);
- return KNOTDZCOMPILE_EOK;
-}
-
-static int zone_open(const char *filename, uint32_t ttl, uint16_t rclass,
- knot_node_t *origin, void *scanner, knot_dname_t *origin_from_config)
-{
- /*!< \todo #1676 Implement proper locking. */
- zparser_init(filename, ttl, rclass, origin, origin_from_config);
-
-
- /* Open the zone file... */
- if (strcmp(filename, "-") == 0) {
- zp_set_in(stdin, scanner);
- filename = "<stdin>";
- } else {
- FILE *f = fopen(filename, "r");
- if (f == NULL) {
- return 0;
- }
- zp_set_in(f, scanner);
- if (zp_get_in(scanner) == 0) {
- return 0;
- }
- }
-
- return 1;
-}
-
-int zone_read(const char *name, const char *zonefile, const char *outfile,
- int semantic_checks)
-{
- if (!outfile) {
- zc_error_prev_line("Missing output file for '%s'\n",
- zonefile);
- return KNOTDZCOMPILE_EINVAL;
- }
-
- dbg_zp("zp: zone_read: Reading zone: %s.\n", zonefile);
-
- /* Check that we can write to outfile. */
- FILE *f = fopen(outfile, "wb");
- if (f == NULL) {
- log_zone_error("Cannot write zone db to file '%s' (%s).\n",
- outfile, strerror(errno));
- return KNOTDZCOMPILE_EINVAL;
- }
- fclose(f);
-
- knot_dname_t *dname =
- knot_dname_new_from_str(name, strlen(name), NULL);
- if (dname == NULL) {
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (!knot_dname_is_fqdn(dname)) {
- log_zone_error("Error: given zone origin is not FQDN.\n");
- knot_dname_release(dname);
- return KNOTDZCOMPILE_EINVAL;
- }
-
- knot_node_t *origin_node = knot_node_new(dname, NULL, 0);
- knot_dname_release(dname); /* Stored in node or should be freed. */
- if (origin_node == NULL) {
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- assert(knot_node_parent(origin_node) == NULL);
-
- /*!< \todo Another copy is probably not needed. */
- knot_dname_t *origin_from_config =
- knot_dname_new_from_str(name, strlen(name), NULL);
- if (origin_from_config == NULL) {
- knot_node_free(&origin_node);
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- void *scanner = NULL;
- zp_lex_init(&scanner);
- if (scanner == NULL) {
- knot_dname_release(origin_from_config);
- knot_node_free(&origin_node);
- return KNOTDZCOMPILE_ENOMEM;
- }
-
- if (!zone_open(zonefile, 3600, KNOT_CLASS_IN, origin_node, scanner,
- origin_from_config)) {
- zc_error_prev_line("Cannot open '%s' (%s).",
- zonefile, strerror(errno));
- zp_lex_destroy(scanner);
- knot_dname_release(origin_from_config);
-// knot_node_free(&origin_node, 0);
- return KNOTDZCOMPILE_EZONEINVAL;
- }
-
- /* Lock zone file. There should not be any modifications. */
- struct flock lock;
- lock.l_type = F_RDLCK;
- lock.l_start = 0;
- lock.l_whence = SEEK_SET;
- lock.l_len = 0;
- lock.l_pid = getpid();
- if (fcntl(fileno(zp_get_in(scanner)), F_SETLK, &lock) == -1) {
- log_zone_error("Cannot obtain zone source file lock (%d).\n",
- errno);
- FILE *in_file = (FILE *)zp_get_in(scanner);
- fclose(in_file);
- zp_lex_destroy(scanner);
- knot_dname_release(origin_from_config);
- return KNOTDZCOMPILE_EINVAL;
- }
-
- /* Change lock type to unlock rigth away. */
- lock.l_type = F_UNLCK;
-
- if (zp_parse(scanner) != 0) {
- log_zone_error("Parse failed.\n");
- FILE *in_file = (FILE *)zp_get_in(scanner);
- fclose(in_file);
- knot_dname_release(origin_from_config);
-// knot_node_free(&origin_node, 0);
- /* Release file lock. */
- if (fcntl(fileno(zp_get_in(scanner)), F_SETLK, &lock) == -1) {
- log_zone_error("Cannot release zone source file "
- "lock (%d).\n",
- errno);
- }
- zp_lex_destroy(scanner);
- return KNOTDZCOMPILE_ESYNT;
- }
-
- knot_zone_contents_t *contents =
- knot_zone_get_contents(parser->current_zone);
-
- /* Release file lock. */
- if (fcntl(fileno(zp_get_in(scanner)), F_SETLK, &lock) == -1) {
- log_zone_error("Cannot release zone source file lock (%d).\n",
- errno);
- }
-
- FILE *in_file = (FILE *)zp_get_in(scanner);
- fclose(in_file);
- zp_lex_destroy(scanner);
-
- dbg_zp("zp: zone_read: Parse complete for %s.\n",
- zonefile);
-
- if (parser->last_node && parser->node_rrsigs != NULL) {
- /* assign rrsigs to last node in the zone*/
- process_rrsigs_in_node(contents,
- parser->last_node);
- rrset_list_delete(&parser->node_rrsigs);
- }
-
- dbg_zp("zp: zone_read: RRSIGs processed.\n");
-
- if (!(parser->current_zone &&
- knot_node_rrset(parser->current_zone->contents->apex,
- KNOT_RRTYPE_SOA))) {
- zc_error_prev_line("Zone file does not contain SOA record!\n");
-// knot_zone_deep_free(&parser->current_zone, 1);
- knot_dname_release(origin_from_config);
-// knot_node_free(&origin_node, 0);
- return KNOTDZCOMPILE_EZONEINVAL;
- }
-
- int ret = knot_zone_contents_adjust(contents);
- if (ret != KNOT_EOK) {
- fprintf(stderr, "Zone could not be adjusted, error: %s.\n",
- knot_strerror(ret));
- parser->errors++;
- }
-
- dbg_zp("zp: zone_read: Zone adjusted.\n");
-
- if (parser->errors != 0) {
- log_zone_error("Parser finished with %d error(s), "
- "not dumping the zone!\n",
- parser->errors);
- } else {
- int fd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG);
- if (fd < 0) {
- log_zone_error("Could not open destination file for db: %s.\n",
- outfile);
- totalerrors++;
- } else {
- crc_t crc;
- int ret = knot_zdump_binary(contents, fd,
- semantic_checks,
- zonefile, &crc);
- if (ret != KNOT_EOK) {
- log_zone_error("Could not dump zone, reason: "
- "%s.\n", knot_strerror(ret));
- if (remove(outfile) != 0) {
- log_zone_error("Could not remove "
- "db file!\n");
- }
- totalerrors++;
- } else {
- /* Write CRC file. */
- char *crc_path = knot_zdump_crc_file(outfile);
- if (crc_path == NULL) {
- log_zone_error(
- "Could not get crc file path.\n");
- remove(outfile);
- totalerrors++;
- } else {
- FILE *f_crc = fopen(crc_path, "w");
- if (f_crc == NULL) {
- log_zone_error(
- "Could not open crc file \n");
- remove(outfile);
- totalerrors++;
- } else {
- fprintf(f_crc,
- "%lu",
- (unsigned long)crc);
- fclose(f_crc);
- }
- }
- free(crc_path);
- }
- }
-
-
- dbg_zp("zp: zone_read: Zone %s dumped successfully.\n",
- zonefile);
- }
-
- fflush(stdout);
- totalerrors += parser->errors;
- knot_dname_release(origin_from_config);
-
- return totalerrors;
-}
-
-/*! @} */
diff --git a/src/zcompile/zcompile.h b/src/zcompile/zcompile.h
deleted file mode 100644
index d19ef4c..0000000
--- a/src/zcompile/zcompile.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*!
- * \file zoneparser.h
- *
- * \author modifications by Jan Kadlec <jan.kadlec@nic.cz>, most of the code
- * by NLnet Labs.
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \brief Zone compiler.
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _KNOTD_ZONEPARSER_H_
-#define _KNOTD_ZONEPARSER_H_
-
-#include <stdio.h>
-
-#include "libknot/dname.h"
-#include "libknot/rrset.h"
-#include "libknot/zone/node.h"
-#include "libknot/rdata.h"
-#include "libknot/zone/zone.h"
-#include "libknot/zone/dname-table.h"
-#include "libknot/zone/dname-table.h"
-#include "common/slab/slab.h"
-
-#define MAXRDATALEN 64 /*!< Maximum number of RDATA items. */
-#define MAXLABELLEN 63 /*!< Maximum label length. */
-#define MAXDOMAINLEN 255 /*!< Maximum domain name length */
-#define MAX_RDLENGTH 65535 /*!< Maximum length of RDATA item */
-#define MAXTOKENSLEN 512 /*!< Maximum number of tokens per entry. */
-#define B64BUFSIZE 65535 /*!< Buffer size for b64 conversion. */
-#define ROOT (const uint8_t *)"\001" /*!< Root domain name. */
-
-#define NSEC_WINDOW_COUNT 256 /*!< Number of NSEC windows. */
-#define NSEC_WINDOW_BITS_COUNT 256 /*!< Number of bits in NSEC window. */
-/*! \brief Size of NSEC window in bytes. */
-#define NSEC_WINDOW_BITS_SIZE (NSEC_WINDOW_BITS_COUNT / 8)
-
-/*
- * RFC 4025 - codes for different types that IPSECKEY can hold.
- */
-#define IPSECKEY_NOGATEWAY 0
-#define IPSECKEY_IP4 1
-#define IPSECKEY_IP6 2
-#define IPSECKEY_DNAME 3
-
-#define LINEBUFSZ 1024 /*!< Buffer size for one line in zone file. */
-
-struct lex_data {
- size_t len; /*!< holds the label length */
- char *str; /*!< holds the data */
-};
-
-#define DEFAULT_TTL 3600
-
-int yylex_destroy(void *scanner);
-int zp_parse(void *scanner);
-void zp_set_in(FILE *f, void *scanner);
-int zp_lex_init(void **scanner);
-int zp_lex_destroy(void *scanner);
-
-/*! \todo Implement ZoneDB. */
-typedef void namedb_type;
-
-/*!
- * \brief One-purpose linked list holding pointers to RRSets.
- */
-struct rrset_list {
- knot_rrset_t *data; /*!< List data. */
- struct rrset_list *next; /*!< Next node. */
-};
-
-typedef struct rrset_list rrset_list_t;
-
-/*!
- * \brief Main zoneparser structure.
- */
-struct zparser {
- const char *filename; /*!< File with zone. */
- uint32_t default_ttl; /*!< Default TTL. */
- uint16_t default_class; /*!< Default class. */
- knot_zone_t *current_zone; /*!< Current zone. */
- knot_node_t *origin; /*!< Origin node. */
- knot_dname_t *prev_dname; /*!< Previous dname. */
- knot_dname_t *origin_from_config; /*!< Zone origin from config. */
- knot_node_t *default_apex; /*!< Zone default apex. */
-
- knot_node_t *last_node; /*!< Last processed node. */
-
- char *dname_str; /*!< Temporary dname. */
-
- int error_occurred; /*!< Error occured flag */
- unsigned int errors; /*!< Number of errors. */
- unsigned int line; /*!< Current line */
-
- knot_rrset_t *current_rrset; /*!< Current RRSet. */
- knot_rdata_item_t *temporary_items; /*!< Temporary rdata items. */
-
- knot_dname_t *root_domain; /*!< Root domain name. */
- slab_cache_t *parser_slab; /*!< Slab for parser. */
- rrset_list_t *node_rrsigs; /*!< List of RRSIGs in current node. */
-
- int rdata_count; /*!< Count of parsed rdata. */
-};
-
-typedef struct zparser zparser_type;
-
-extern zparser_type *parser;
-
-extern void zc_error_prev_line(const char *fmt, ...);
-
-/* used in zonec.lex */
-
-void zc_error_prev_line(const char *fmt, ...);
-void zc_warning_prev_line(const char *fmt, ...);
-
-/*!
- * \brief Does all the processing of RR - saves to zone, assigns RRSIGs etc.
- */
-int process_rr();
-
-/*!
- * \brief Parses and creates zone from given file.
- *
- * \param name Origin domain name string.
- * \param zonefile File containing the zone.
- * \param outfile File to save dump of the zone to.
- * \param semantic_checks Enables or disables sematic checks.
- *
- * \retval 0 on success.
- * \retval -1 on error.
- */
-int zone_read(const char *name, const char *zonefile, const char *outfile,
- int semantic_checks);
-
-/*!
- * \brief Creates zparser instance.
- *
- *
- * \return Created zparser instance.
- */
-zparser_type *zparser_create();
-
-/*!
- * \brief Inits zoneparser structure.
- *
- * \param filename Name of file with zone.
- * \param ttl Default TTL.
- * \param rclass Default class.
- * \param origin Zone origin.
- */
-void zparser_init(const char *filename, uint32_t ttl, uint16_t rclass,
- knot_node_t *origin, knot_dname_t *owner_from_config);
-
-/*!
- * \brief Frees zoneparser structure.
- *
- */
-void zparser_free();
-
-int save_dnames_in_table(knot_dname_table_t *table,
- knot_rrset_t *rrset);
-
-#endif /* _KNOTD_ZONEPARSER_H_ */
-
-/*! @} */
diff --git a/src/zcompile/zcompile_main.c b/src/zcompile/zcompile_main.c
deleted file mode 100644
index 983376a..0000000
--- a/src/zcompile/zcompile_main.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright (C) 2011 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 <config.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "zcompile/zcompile.h"
-#include "common/log.h"
-#include <config.h>
-
-static void help(int argc, char **argv)
-{
- printf("Usage: %s [parameters] origin zonefile\n",
- argv[0]);
- printf("\n:Parameters:\n"
- " -o <outfile> Override output file.\n"
- " -v Verbose mode - additional runtime information.\n"
- " -s Enable semantic checks.\n"
- " -V Print version of the server.\n"
- " -h Print help and usage.\n");
-}
-
-int main(int argc, char **argv)
-{
- // Parse command line arguments
- int c = 0;
- int verbose = 0;
- int semantic_checks = 0;
- const char* origin = 0;
- const char* zonefile = 0;
- const char* outfile = 0;
- while ((c = getopt (argc, argv, "o:vVsh")) != -1) {
- switch (c)
- {
- case 'o':
- outfile = optarg;
- break;
- case 'v':
- verbose = 1;
- break;
- case 'V':
- printf("%s, version %s\n", "Knot DNS", PACKAGE_VERSION);
- return 0;
- case 's':
- semantic_checks = 1;
- break;
- case 'h':
- case '?':
- default:
- if (optopt == 'o') {
- fprintf (stderr,
- "Option -%c requires an argument.\n",
- optopt);
- }
- help(argc, argv);
- return 1;
- }
- }
-
- UNUSED(verbose);
-
- // Check if there's at least two remaining non-option
- if (argc - optind < 2) {
- help(argc, argv);
- return 1;
- }
-
- origin = argv[optind];
- zonefile = argv[optind + 1];
-
- // Initialize log (no syslog)
- log_init();
- log_levels_set(LOGT_SYSLOG, LOG_ANY, 0);
- if (outfile != NULL) {
- log_zone_info("Parsing file '%s', origin '%s' ...\n",
- zonefile, origin);
- }
-
- parser = zparser_create();
- if (!parser) {
- log_server_error("Failed to create parser.\n");
- //log_close();
- return 1;
- }
-
- int error = zone_read(origin, zonefile, outfile, semantic_checks);
- zparser_free();
-
- if (error != 0) {
- /* FIXME! */
-// if (error < 0) {
-// fprintf(stderr, "Finished with error: %s.\n",
-// error_to_str(knot_zcompile_error_msgs, error));
-// } else {
-// fprintf(stderr, "Finished with %u errors.\n");
-// }
- return 1;
- } else if (outfile != NULL) {
- log_zone_info("Compilation of '%s' successful.\n", origin);
- } else {
- log_zone_info("Zone file for '%s' is OK.\n", origin);
- }
-
- return 0;
-}
diff --git a/src/zcompile/zlexer.l b/src/zcompile/zlexer.l
deleted file mode 100644
index 58e6439..0000000
--- a/src/zcompile/zlexer.l
+++ /dev/null
@@ -1,532 +0,0 @@
-%{
-/*!
- * \file zlexer.l
- *
- * \author minor modifications by Jan Kadlec <jan.kadlec@nic.cz>,
- * most of the code by NLnet Labs
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \brief lexical analyzer for (DNS) zone files.
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-//#include "common.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <string.h>
-#include <strings.h>
-#include <assert.h>
-
-#include "zcompile/zcompile.h"
-#include "libknot/dname.h"
-#include "zcompile/parser-descriptor.h"
-#include "zparser.h"
-
-#define YY_NO_INPUT
-
-/* Utils */
-extern void zc_error(const char *fmt, ...);
-extern void zc_warning(const char *fmt, ...);
-
-void strip_string(char *str)
-{
- char *start = str;
- char *end = str + strlen(str) - 1;
-
- while (isspace(*start))
- ++start;
- if (start > end) {
- /* Completely blank. */
- str[0] = '\0';
- } else {
- while (isspace(*end))
- --end;
- *++end = '\0';
-
- if (str != start)
- memmove(str, start, end - start + 1);
- }
-}
-
-int hexdigit_to_int(char ch)
-{
- switch (ch) {
- case '0': return 0;
- case '1': return 1;
- case '2': return 2;
- case '3': return 3;
- case '4': return 4;
- case '5': return 5;
- case '6': return 6;
- case '7': return 7;
- case '8': return 8;
- case '9': return 9;
- case 'a': case 'A': return 10;
- case 'b': case 'B': return 11;
- case 'c': case 'C': return 12;
- case 'd': case 'D': return 13;
- case 'e': case 'E': return 14;
- case 'f': case 'F': return 15;
- default:
- abort();
- }
-}
-
-extern uint32_t strtottl(const char *nptr, const char **endptr);
-
-#define YY_NO_UNPUT
-#define MAXINCLUDES 10
-
-#define scanner yyscanner
-extern int zp_lex(YYSTYPE *lvalp, void *scanner);
-
-#if 0
-#define LEXOUT(s) printf s /* used ONLY when debugging */
-#else
-#define LEXOUT(s)
-#endif
-
-enum lexer_state {
- EXPECT_OWNER,
- PARSING_OWNER,
- PARSING_TTL_CLASS_TYPE,
- PARSING_RDATA
-};
-
-static YY_BUFFER_STATE include_stack[MAXINCLUDES];
-static zparser_type zparser_stack[MAXINCLUDES];
-static int include_stack_ptr = 0;
-
-static void pop_parser_state(void *scanner);
-static void push_parser_state(FILE *input, void *scanner);
-static int parse_token(void *scanner, int token, char *in_str,
- enum lexer_state *lexer_state);
-
-
-/*!< \todo does not compile */
-#ifndef yy_set_bol // compat definition, for flex 2.4.6
-#define yy_set_bol(at_bol) \
-{ \
- if (!yy_current_buffer ) \
- yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
- yy_current_buffer->yy_ch_buf[0] = ((at_bol)?'\n':' '); \
-}
-#endif
-
-%}
-
-%option nounput
-%option reentrant bison-bridge
-%option prefix = "zp_"
-%option outfile = "lex.yy.c"
-
-SPACE [ \t]
-LETTER [a-zA-Z]
-NEWLINE [\n\r]
-ZONESTR [^ \t\n\r();.\"\$]
-DOLLAR \$
-COMMENT ;
-DOT \.
-BIT [^\]\n]|\\.
-ANY [^\"\n\\]|\\.
-
-%x incl bitlabel quotedstring
-
-%%
- static int paren_open = 0;
- static enum lexer_state lexer_state = EXPECT_OWNER;
-
-{SPACE}*{COMMENT}.* /* ignore */
-^{DOLLAR}TTL { lexer_state = PARSING_RDATA; return DOLLAR_TTL; }
-^{DOLLAR}ORIGIN { lexer_state = PARSING_RDATA; return DOLLAR_ORIGIN; }
-
- /*
- * Handle $INCLUDE directives. See
- * http://dinosaur.compilertools.net/flex/flex_12.html#SEC12.
- */
-^{DOLLAR}INCLUDE {
- BEGIN(incl);
-}
-<incl>\n |
-<incl><<EOF>> {
- int error_occurred = parser->error_occurred;
- BEGIN(INITIAL);
- zc_error("missing file name in $INCLUDE directive");
- yy_set_bol(1); /* Set beginning of line, so "^" rules match. */
- ++parser->line;
- parser->error_occurred = error_occurred;
-}
-<incl>.+ {
- char *tmp;
- /*! \todo pointer to origin. */
- void *origin = parser->origin;
- /* domain_type *origin = parser->origin; */
- int error_occurred = parser->error_occurred;
-
- BEGIN(INITIAL);
- if (include_stack_ptr >= MAXINCLUDES ) {
- zc_error("includes nested too deeply, skipped (>%d)",
- MAXINCLUDES);
- } else {
- FILE *input;
-
- /* Remove trailing comment. */
- tmp = strrchr(yytext, ';');
- if (tmp) {
- *tmp = '\0';
- }
- strip_string(yytext);
-
- /* Parse origin for include file. */
- tmp = strrchr(yytext, ' ');
- if (!tmp) {
- tmp = strrchr(yytext, '\t');
- }
- if (tmp) {
- /* split the original yytext */
- *tmp = '\0';
- strip_string(yytext);
-
- /*! \todo knot_dname_new_from_wire() (dname.h)
- * which knot_node to pass as node?
- */
- knot_dname_t *dname;
- dname = knot_dname_new_from_wire((uint8_t*)tmp + 1,
- strlen(tmp + 1),
- NULL);
- if (!dname) {
- zc_error("incorrect include origin '%s'",
- tmp + 1);
- } else {
- /*! \todo insert to zonedb. */
- /* origin = domain_table_insert(
- parser->db->domains, dname); */
- }
- }
-
- if (strlen(yytext) == 0) {
- zc_error("missing file name in $INCLUDE directive");
- } else if (!(input = fopen(yytext, "r"))) {
- char ebuf[256] = {0};
- strerror_r(errno, ebuf, sizeof(ebuf));
- zc_error("cannot open include file '%s': %s",
- yytext, ebuf);
- } else {
- /* Initialize parser for include file. */
- char *filename = strdup(yytext);
- push_parser_state(input, scanner); /* Destroys yytext. */
- parser->filename = filename;
- parser->line = 1;
- parser->origin = origin;
- lexer_state = EXPECT_OWNER;
- }
- }
-
- parser->error_occurred = error_occurred;
-}
-<INITIAL><<EOF>> {
- yy_set_bol(1); /* Set beginning of line, so "^" rules match. */
- if (include_stack_ptr == 0) {
- // from: http://stackoverflow.com/questions/1756275/bison-end-of-file
- static int once = 0;
- once++;
- if (once > 1) {
- yyterminate();
- } else {
- return NL;
- }
- } else {
- fclose(yyin);
- pop_parser_state(scanner);
- }
-}
-^{DOLLAR}{LETTER}+ { zc_warning("Unknown directive: %s", yytext); }
-{DOT} {
- LEXOUT((". "));
- return parse_token(scanner, '.', yytext, &lexer_state);
-}
-@ {
- LEXOUT(("@ "));
- return parse_token(scanner, '@', yytext, &lexer_state);
-}
-\\# {
- LEXOUT(("\\# "));
- return parse_token(scanner, URR, yytext, &lexer_state);
-}
-{NEWLINE} {
- ++parser->line;
- if (!paren_open) {
- lexer_state = EXPECT_OWNER;
- LEXOUT(("NL\n"));
- return NL;
- } else {
- LEXOUT(("SP "));
- return SP;
- }
-}
-\( {
- if (paren_open) {
- zc_error("nested parentheses");
- yyterminate();
- }
- LEXOUT(("( "));
- paren_open = 1;
- return SP;
-}
-\) {
- if (!paren_open) {
- zc_error("closing parentheses without opening parentheses");
- yyterminate();
- }
- LEXOUT((") "));
- paren_open = 0;
- return SP;
-}
-{SPACE}+ {
- if (!paren_open && lexer_state == EXPECT_OWNER) {
- lexer_state = PARSING_TTL_CLASS_TYPE;
- LEXOUT(("PREV "));
- return PREV;
- }
- if (lexer_state == PARSING_OWNER) {
- lexer_state = PARSING_TTL_CLASS_TYPE;
- }
- LEXOUT(("SP "));
- return SP;
-}
-
- /* Bitlabels. Strip leading and ending brackets. */
-\\\[ { BEGIN(bitlabel); }
-<bitlabel><<EOF>> {
- zc_error("EOF inside bitlabel");
- BEGIN(INITIAL);
-}
-<bitlabel>{BIT}* { yymore(); }
-<bitlabel>\n { ++parser->line; yymore(); }
-<bitlabel>\] {
- BEGIN(INITIAL);
- yytext[yyleng - 1] = '\0';
- return parse_token(scanner, BITLAB, yytext, &lexer_state);
-}
-
- /* Quoted strings. Strip leading and ending quotes. */
-\" { BEGIN(quotedstring); LEXOUT(("\" ")); }
-<quotedstring><<EOF>> {
- zc_error("EOF inside quoted string");
- BEGIN(INITIAL);
-}
-<quotedstring>{ANY}* { LEXOUT(("STR ")); yymore(); }
-<quotedstring>\n { ++parser->line; yymore(); }
-<quotedstring>\" {
- LEXOUT(("\" "));
- BEGIN(INITIAL);
- yytext[yyleng - 1] = '\0';
- return parse_token(scanner, STR, yytext, &lexer_state);
-}
-
-({ZONESTR}|\\.|\\\n)+ {
- /* Any allowed word. */
- return parse_token(scanner, STR, yytext, &lexer_state);
-}
-. {
- zc_error("unknown character '%c' (\\%03d) seen - is this a zonefile?",
- (int) yytext[0], (int) yytext[0]);
-}
-%%
-
-/*
- * Analyze "word" to see if it matches an RR type, possibly by using
- * the "TYPExxx" notation. If it matches, the corresponding token is
- * returned and the TYPE parameter is set to the RR type value.
- */
-static int
-rrtype_to_token(const char *word, uint16_t *type)
-{
- uint16_t t = parser_rrtype_from_string(word);
- if (t != 0) {
- parser_rrtype_descriptor_t *entry = 0;
- entry = parser_rrtype_descriptor_by_type(t);
- *type = t;
-
- /*! \todo entry should return associated token.
- see nsd/dns.c */
- return entry->token;
- }
-
- return 0;
-}
-
-
-/*
- * Remove \DDD constructs from the input. See RFC 1035, section 5.1.
- */
-static size_t
-zoctet(char *text)
-{
- /*
- * s follows the string, p lags behind and rebuilds the new
- * string
- */
- char *s;
- char *p;
-
- for (s = p = text; *s; ++s, ++p) {
- assert(p <= s);
- if (s[0] != '\\') {
- /* Ordinary character. */
- *p = *s;
- } else if (isdigit((int)s[1]) && isdigit((int)s[2]) && isdigit((int)s[3])) {
- /* \DDD escape. */
- int val = (hexdigit_to_int(s[1]) * 100 +
- hexdigit_to_int(s[2]) * 10 +
- hexdigit_to_int(s[3]));
- if (0 <= val && val <= 255) {
- s += 3;
- *p = val;
- } else {
- zc_warning("text escape \\DDD overflow");
- *p = *++s;
- }
- } else if (s[1] != '\0') {
- /* \X where X is any character, keep X. */
- *p = *++s;
- } else {
- /* Trailing backslash, ignore it. */
- zc_warning("trailing backslash ignored");
- --p;
- }
- }
- *p = '\0';
- return p - text;
-}
-
-static int parse_token(void *scanner, int token, char *in_str,
- enum lexer_state *lexer_state)
-{
- size_t len = 0;
- char *str = NULL;
-
- struct yyguts_t *yyg = (struct yyguts_t *)scanner;
-
- if (*lexer_state == EXPECT_OWNER) {
- *lexer_state = PARSING_OWNER;
- } else if (*lexer_state == PARSING_TTL_CLASS_TYPE) {
- const char *t;
- int token;
- uint16_t rrclass;
-
- /* type */
- token = rrtype_to_token(in_str, &yylval->type);
- if (token != 0) {
- *lexer_state = PARSING_RDATA;
- LEXOUT(("%d[%s] ", token, in_str));
- return token;
- }
-
- /* class */
- rrclass = parser_rrclass_from_string(in_str);
- if (rrclass != 0) {
- yylval->rclass = rrclass;
- LEXOUT(("CLASS "));
- return T_RRCLASS;
- }
-
- /* ttl */
- yylval->ttl = strtottl(in_str, &t);
- if (*t == '\0') {
- LEXOUT(("TTL "));
- return T_TTL;
- }
- }
-
- str = strdup(yytext);
- if (str == NULL) {
- /* Out of memory */
- ERR_ALLOC_FAILED;
- return NO_MEM;
- }
- len = zoctet(str);
-
- yylval->data.str = str;
- assert(yylval->data.str != NULL);
- yylval->data.len = len;
-
- if (strcmp(yytext, ".") == 0) {
- free(str);
- yylval->data.str=".";
- } else if (strcmp(str, "@") == 0) {
- free(str);
- yylval->data.str="@";
- } else if (strcmp(str, "\\#") == 0) {
- free(str);
- yylval->data.str="\\#";
- }
-
- LEXOUT(("%d[%s] ", token, in_str));
- return token;
-}
-
-/*
- * Saves the file specific variables on the include stack.
- */
-static void push_parser_state(FILE *input, void *scanner)
-{
- struct yyguts_t *yyg = (struct yyguts_t *)scanner;
- zparser_stack[include_stack_ptr].filename = parser->filename;
- zparser_stack[include_stack_ptr].line = parser->line;
- zparser_stack[include_stack_ptr].origin = parser->origin;
- include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
- yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE, scanner),
- scanner);
- ++include_stack_ptr;
-}
-
-/*
- * Restores the file specific variables from the include stack.
- */
-void pop_parser_state(void *scanner)
-{
- struct yyguts_t *yyg = (struct yyguts_t *)scanner;
- --include_stack_ptr;
- parser->filename = zparser_stack[include_stack_ptr].filename;
- parser->line = zparser_stack[include_stack_ptr].line;
- parser->origin = zparser_stack[include_stack_ptr].origin;
- yy_delete_buffer(YY_CURRENT_BUFFER, scanner);
- yy_switch_to_buffer(include_stack[include_stack_ptr], scanner);
-}
diff --git a/src/zcompile/zparser.y b/src/zcompile/zparser.y
deleted file mode 100644
index c35060e..0000000
--- a/src/zcompile/zparser.y
+++ /dev/null
@@ -1,1774 +0,0 @@
-%{
-/*!
- * \file zparser.y
- *
- * \author modifications by Jan Kadlec <jan.kadlec@nic.cz>,
- * notable changes: normal allocation, parser is reentrant.
- * most of the code by NLnet Labs
- * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
- *
- * \brief yacc grammar for (DNS) zone files
- *
- * \addtogroup zoneparser
- * @{
- */
-
-/*
- * Copyright (c) 2001-2011, 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 REGENTS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-//#include "common.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-
-#include "zcompile/parser-util.h"
-#include "common/log.h"
-
-#include "libknot/libknot.h"
-#include "zcompile/zcompile.h"
-#include "zcompile/parser-descriptor.h"
-#include "zcompile/zcompile-error.h"
-#include "zparser.h"
-
-/* these need to be global, otherwise they cannot be used inside yacc */
-zparser_type *parser;
-
-#ifdef __cplusplus
-extern "C"
-#endif /* __cplusplus */
-int zp_wrap(void);
-
-/* this hold the nxt bits */
-static uint8_t nxtbits[16];
-static int dlv_warn = 1;
-
-/* 256 windows of 256 bits (32 bytes) */
-/* still need to reset the bastard somewhere */
-static uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE];
-
-/* hold the highest rcode seen in a NSEC rdata , BUG #106 */
-uint16_t nsec_highest_rcode;
-
-void zp_error(void *scanner, const char *message);
-int zp_lex(YYSTYPE *lvalp, void *scanner);
-
-/* helper functions */
-void zc_error(const char *fmt, ...);
-void zc_warning(const char *fmt, ...);
-void zc_error_prev_line(const char *fmt, ...);
-void zc_warning_prev_line(const char *fmt, ...);
-
-#define NSEC3
-#ifdef NSEC3
-/* parse nsec3 parameters and add the (first) rdata elements */
-static void
-nsec3_add_params(const char* hash_algo_str, const char* flag_str,
- const char* iter_str, const char* salt_str, int salt_len);
-#endif /* NSEC3 */
-
-knot_dname_t *error_dname; //XXX used to be const
-knot_dname_t *error_domain;
-
-%}
-%union {
- knot_dname_t *domain;
- knot_dname_t *dname;
- struct lex_data data;
- uint32_t ttl;
- uint16_t rclass;
- uint16_t type;
- uint16_t *unknown;
-}
-
-%pure-parser
-%parse-param {void *scanner}
-%lex-param {void *scanner}
-%name-prefix = "zp_"
-
-/*
- * Tokens to represent the known RR types of DNS.
- */
-%token <type> T_A T_NS T_MX T_TXT T_CNAME T_AAAA T_PTR T_NXT T_KEY T_SOA T_SIG
-%token <type> T_SRV T_CERT T_LOC T_MD T_MF T_MB T_MG T_MR T_NULL T_WKS T_HINFO
-%token <type> T_MINFO T_RP T_AFSDB T_X25 T_ISDN T_RT T_NSAP T_NSAP_PTR T_PX
-%token <type> T_GPOS T_EID T_NIMLOC T_ATMA T_NAPTR T_KX T_A6 T_DNAME T_SINK
-%token <type> T_OPT T_APL T_UINFO T_UID T_GID T_UNSPEC T_TKEY T_TSIG T_IXFR
-%token <type> T_AXFR T_MAILB T_MAILA T_DS T_DLV T_SSHFP T_RRSIG T_NSEC T_DNSKEY
-%token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA
-
-/* other tokens */
-%token DOLLAR_TTL DOLLAR_ORIGIN NL SP NO_MEM
-%token <data> STR PREV BITLAB
-%token <ttl> T_TTL
-%token <rclass> T_RRCLASS
-
-/* unknown RRs */
-%token URR
-%token <type> T_UTYPE
-
-%type <type> type_and_rdata
-%type <domain> owner dname abs_dname
-%type <dname> rel_dname label
-%type <data> wire_dname wire_abs_dname wire_rel_dname wire_label
-%type <data> concatenated_str_seq str_sp_seq str_dot_seq dotted_str
-%type <data> nxt_seq nsec_more
-%type <unknown> rdata_unknown
-
-%%
-lines: /* empty file */
- | lines line
- ;
-
-line: NL
- | sp NL
- | NO_MEM {
- zc_error_prev_line("Parser ran out of memory!");
- YYABORT;
- }
- | PREV NL {} /* Lines containing only whitespace. */
- | ttl_directive
- {
- parser->error_occurred = 0;
- }
- | origin_directive
- {
- parser->error_occurred = 0;
- }
- | rr
- { /* rr should be fully parsed */
- if (!parser->error_occurred) {
- /*!< \todo assign error to error occurred */
- /*! \todo Make sure this does not crash */
- if (parser->current_rrset->owner == NULL) {
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- knot_rdata_t *tmp_rdata = knot_rdata_new();
- if (tmp_rdata == NULL) {
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
-
- if (knot_rdata_set_items(tmp_rdata,
- parser->temporary_items,
- parser->rdata_count) != 0) {
- knot_rdata_free(&tmp_rdata);
- knot_rrset_deep_free(&(parser->current_rrset), 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone), 1);
- YYABORT;
- }
-
- assert(parser->current_rrset->rdata == NULL);
- if (knot_rrset_add_rdata(parser->current_rrset, tmp_rdata)
- != 0) {
- log_zone_error("Could not add rdata!\n");
- }
-// tmp_rdata->next = tmp_rdata;
-// parser->current_rrset->rdata = tmp_rdata;
-
- if (!knot_dname_is_fqdn(parser->current_rrset->owner)) {
- knot_dname_t *tmp_dname =
- knot_dname_cat(parser->current_rrset->owner,
- parser->root_domain);
- if (tmp_dname == NULL) {
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
-// knot_rrset_set_owner(parser->current_rrset, tmp_dname);
- }
-
- assert(parser->current_rrset->owner != NULL);
- knot_dname_retain(parser->current_rrset->owner);
- int ret = 0;
- if ((ret = process_rr()) != 0) {
- char *name =
- knot_dname_to_str(parser->current_rrset->owner);
- log_zone_error("Error: could not process RRSet\n"
- "owner: %s reason: %s\n",
- name,
- error_to_str(knot_zcompile_error_msgs, ret));
- free(name);
-
- /* If the owner is not already in the table, free it. */
-// if (dnslib_dname_table_find_dname(parser->dname_table,
-// parser->current_rrset->owner) == NULL) {
-// dnslib_dname_free(&parser->
-// current_rrset->owner);
-// } /* This would never happen */
-
- if (ret == KNOTDZCOMPILE_EBADSOA) {
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- } else {
- YYABORT;
- /* Free rdata, it will not be added
- * and hence cannot be
- * freed with rest of the zone. */
-/* knot_rdata_deep_free(&tmp_rdata,
- parser->
- current_rrset->type,
- 0); */
- }
- }
- } else {
- /* Error occured. This could either be lack of memory, or one
- * of the converting function was not able to convert. */
- if (parser->error_occurred == KNOTDZCOMPILE_ENOMEM) {
- /* Ran out of memory in converting functions. */
- log_zone_error("Parser ran out "
- "of memory, aborting!\n");
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- }
-
-// printf("Current rrset name: %p (%s)\n", parser->current_rrset->owner->name,
-// knot_dname_to_str(parser->current_rrset->owner));
-
-// knot_dname_release(parser->current_rrset->owner);
-
- parser->current_rrset->type = 0;
- parser->rdata_count = 0;
- parser->current_rrset->rdata = NULL;
- parser->error_occurred = 0;
- }
- | error NL
- ;
-
-/* needed to cope with ( and ) in arbitary places */
-sp: SP
- | sp SP
- ;
-
-trail: NL
- | sp NL
- ;
-
-ttl_directive: DOLLAR_TTL sp STR trail
- {
- parser->default_ttl = zparser_ttl2int($3.str,
- &(parser->error_occurred));
- if (parser->error_occurred == 1) {
- parser->default_ttl = DEFAULT_TTL;
- parser->error_occurred = 0;
- }
-
- free($3.str);
- }
- ;
-
-
-
-origin_directive: DOLLAR_ORIGIN sp abs_dname trail
- {
- /*!< \todo this will leak. */
- knot_node_t *origin_node = knot_node_new($3 ,NULL, 0);
- if (parser->origin != NULL) {
-// knot_node_free(&parser->origin, 1);
- }
- parser->origin = origin_node;
- }
- | DOLLAR_ORIGIN sp rel_dname trail
- {
- zc_error_prev_line("$ORIGIN directive requires"
- "absolute domain name");
- }
- ;
-
-rr: owner classttl type_and_rdata
- {
- /* Save the pointer, it might get freed! */
- parser->current_rrset->owner = $1;
-// parser->current_rrset->owner = $1;
-// printf("new owner assigned: %p\n", $1);
- parser->current_rrset->type = $3;
- }
- ;
-
-owner: dname sp
- {
-// char *name = knot_dname_to_str($1);
-// printf("Totally new dname: %p %s\n", $1,
-// name);
-// free(name);
- if (parser->prev_dname != NULL) {
- // knot_dname_release(parser->prev_dname);
- }
- parser->prev_dname = $1;//knot_dname_deep_copy($1);
- knot_dname_retain(parser->prev_dname);
- $$ = $1;
- }
- | PREV
- {
-// printf("Name from prev_dname!: %p %s\n", parser->prev_dname,
-// knot_dname_to_str(parser->prev_dname));
- knot_dname_retain(parser->prev_dname);
- $$ = parser->prev_dname;//knot_dname_deep_copy(parser->prev_dname);
- }
- ;
-
-classttl: /* empty - fill in the default, def. ttl and IN class */
- {
- parser->current_rrset->ttl = parser->default_ttl;
- parser->current_rrset->rclass = parser->default_class;
- }
- | T_RRCLASS sp /* no ttl */
- {
- parser->current_rrset->ttl = parser->default_ttl;
- parser->current_rrset->rclass = $1;
- }
- | T_TTL sp /* no class */
- {
- parser->current_rrset->ttl = $1;
- parser->current_rrset->rclass = parser->default_class;
- }
- | T_TTL sp T_RRCLASS sp /* the lot */
- {
- parser->current_rrset->ttl = $1;
- parser->current_rrset->rclass = $3;
- }
- | T_RRCLASS sp T_TTL sp /* the lot - reversed */
- {
- parser->current_rrset->ttl = $3;
- parser->current_rrset->rclass = $1;
- }
- ;
-
-dname: abs_dname
- | rel_dname
- {
- if ($1 == error_dname) {
- $$ = error_domain;
- } else if ($1->size + parser->origin->owner->size - 1 >
- MAXDOMAINLEN) {
- zc_error("domain name exceeds %d character limit",
- MAXDOMAINLEN);
- $$ = error_domain;
- } else {
- $$ = knot_dname_cat($1,
- parser->origin->owner);
- }
- }
- ;
-
-abs_dname: '.'
- {
- $$ = parser->root_domain;
- /* TODO how about concatenation now? */
- }
- | '@'
- {
- assert(parser->origin != NULL);
- $$ = parser->origin->owner;
- }
- | rel_dname '.'
- {
- if ($1 != error_dname) {
- $$ = $1;
- } else {
- $$ = error_domain;
- }
- }
- ;
-
-label: STR
- {
- if ($1.len > MAXLABELLEN) {
- zc_error("label exceeds %d character limit", MAXLABELLEN);
- $$ = error_dname;
- } else {
- $$ = knot_dname_new_from_str($1.str, $1.len, NULL);
- $$->ref.count = 0;
- }
-
- free($1.str);
-
- }
- | BITLAB
- {
- zc_error("bitlabels are not supported."
- "RFC2673 has status experimental.");
- $$ = error_dname;
- }
- ;
-
-rel_dname: label
- | rel_dname '.' label
- {
- if ($1 == error_dname || $3 == error_dname) {
- $$ = error_dname;
- } else if ($1->size + $3->size - 1 > MAXDOMAINLEN) {
- zc_error("domain name exceeds %d character limit",
- MAXDOMAINLEN);
- $$ = error_dname;
- } else {
- $$ = knot_dname_cat($1, $3);
-// knot_dname_release($1); /*!< \todo check! */
- knot_dname_free(&$3);
- }
- }
- ;
-
-/*
- * Some dnames in rdata are handled as opaque blobs
- */
-
-wire_dname: wire_abs_dname
- | wire_rel_dname
- ;
-
-wire_abs_dname: '.'
- {
- char *result = malloc(2 * sizeof(char));
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- result[0] = 0;
- result[1] = '\0';
- $$.str = result;
- $$.len = 1;
- }
- | wire_rel_dname '.'
- {
- char *result = malloc($1.len + 2 * sizeof(char));
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- memcpy(result, $1.str, $1.len);
- result[$1.len] = 0;
- result[$1.len+1] = '\0';
- $$.str = result;
- $$.len = $1.len + 1;
-
- free($1.str);
-;
- }
- ;
-
-wire_label: STR
- {
- char *result = malloc($1.len + sizeof(char));
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
-
- if ($1.len > MAXLABELLEN)
- zc_error("label exceeds %d character limit", MAXLABELLEN);
-
- /* make label anyway */
- result[0] = $1.len;
- memcpy(result+1, $1.str, $1.len);
-
- $$.str = result;
- $$.len = $1.len + 1;
-
- free($1.str);
- }
- ;
-
-wire_rel_dname: wire_label
- | wire_rel_dname '.' wire_label
- {
- if ($1.len + $3.len - 3 > MAXDOMAINLEN)
- zc_error("domain name exceeds %d character limit",
- MAXDOMAINLEN);
-
- /* make dname anyway */
- $$.len = $1.len + $3.len;
- $$.str = malloc($$.len + sizeof(char));
- if ($$.str == NULL) {
- ERR_ALLOC_FAILED;
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- memcpy($$.str, $1.str, $1.len);
- memcpy($$.str + $1.len, $3.str, $3.len);
- $$.str[$$.len] = '\0';
-
- free($1.str);
- free($3.str);
- }
- ;
-
-
-
-str_seq: STR
- {
- zadd_rdata_txt_wireformat(zparser_conv_text($1.str, $1.len), 1);
-
- if(strcmp($1.str, ".") && strcmp($1.str, "@")
- && strcmp($1.str, "\\#")) { // Lexer freed that
- free($1.str);
- }
- }
- | str_seq sp STR
- {
- zadd_rdata_txt_wireformat(zparser_conv_text($3.str, $3.len), 0);
-
- if(strcmp($3.str, ".") && strcmp($3.str, "@")
- && strcmp($3.str, "\\#")) { // Lexer freed that
- free($3.str);
- }
- }
- ;
-
-/*
- * Generate a single string from multiple STR tokens, separated by
- * spaces or dots.
- */
-concatenated_str_seq: STR
- | '.'
- {
- $$.len = 1;
- $$.str = strdup(".");
- }
- | concatenated_str_seq sp STR
- {
- $$.len = $1.len + $3.len + 1;
- $$.str = malloc($$.len + 1);
- if ($$.str == NULL) {
- ERR_ALLOC_FAILED;
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
-
- memcpy($$.str, $1.str, $1.len);
- memcpy($$.str + $1.len, " ", 1);
- memcpy($$.str + $1.len + 1, $3.str, $3.len);
- $$.str[$$.len] = '\0';
-
- free($1.str);
- free($3.str);
- }
- | concatenated_str_seq '.' STR
- {
- $$.len = $1.len + $3.len + 1;
- $$.str = malloc($$.len + 1);
- if ($$.str == NULL) {
- ERR_ALLOC_FAILED;
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- memcpy($$.str, $1.str, $1.len);
- memcpy($$.str + $1.len, ".", 1);
- memcpy($$.str + $1.len + 1, $3.str, $3.len);
-
- free($1.str);
- free($3.str);
-
- $$.str[$$.len] = '\0';
- }
- ;
-
-/* used to convert a nxt list of types */
-nxt_seq: STR
- {
- uint16_t type = knot_rrtype_from_string($1.str);
- if (type != 0 && type < 128) {
- set_bit(nxtbits, type);
- } else {
- zc_error("bad type %d in NXT record", (int) type);
- }
-
- free($1.str);
- }
- | nxt_seq sp STR
- {
- uint16_t type = knot_rrtype_from_string($3.str);
- if (type != 0 && type < 128) {
- set_bit(nxtbits, type);
- } else {
- zc_error("bad type %d in NXT record", (int) type);
- }
-
- free($3.str);
- }
- ;
-
-nsec_more: SP nsec_more
- {
- }
- | NL
- {
- }
- | STR nsec_seq
- {
- uint16_t type = knot_rrtype_from_string($1.str);
- if (type != 0) {
- if (type > nsec_highest_rcode) {
- nsec_highest_rcode = type;
- }
- set_bitnsec(nsecbits, type);
- } else {
- zc_error("bad type %d in NSEC record", (int) type);
- }
-
- free($1.str);
- }
- ;
-
-nsec_seq: NL
- | SP nsec_more
- ;
-
-/*
- * Sequence of STR tokens separated by spaces. The spaces are not
- * preserved during concatenation.
- */
-str_sp_seq: STR
- | str_sp_seq sp STR
- {
- char *result = malloc($1.len + $3.len + 1);
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- log_zone_error("Parser ran out of memory, aborting!\n");
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- memcpy(result, $1.str, $1.len);
- memcpy(result + $1.len, $3.str, $3.len);
- $$.str = result;
- $$.len = $1.len + $3.len;
- $$.str[$$.len] = '\0';
-
- free($1.str);
- free($3.str);
- }
- ;
-
-/*
- * Sequence of STR tokens separated by dots. The dots are not
- * preserved during concatenation.
- */
-str_dot_seq: STR
- | str_dot_seq '.' STR
- {
- char *result = malloc($1.len + $3.len + 1);
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- log_zone_error("Parser ran out of memory, aborting!\n");
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- memcpy(result, $1.str, $1.len);
- memcpy(result + $1.len, $3.str, $3.len);
- $$.str = result;
- $$.len = $1.len + $3.len;
- $$.str[$$.len] = '\0';
-
- free($1.str);
- free($3.str);
- }
- ;
-
-/*
- * A string that can contain dots.
- */
-dotted_str: STR
- | '.'
- {
- $$.str = ".";
- $$.len = 1;
- }
- | dotted_str '.'
- {
- char *result = malloc($1.len + 2);
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- log_zone_error("Parser ran out of memory, aborting!\n");
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- memcpy(result, $1.str, $1.len);
- result[$1.len] = '.';
- $$.str = result;
- $$.len = $1.len + 1;
- $$.str[$$.len] = '\0';
-
- free($1.str);
- }
- | dotted_str '.' STR
- {
- char *result = malloc($1.len + $3.len + 2);
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- log_zone_error("Parser ran out of memory, aborting!\n");
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
- memcpy(result, $1.str, $1.len);
- result[$1.len] = '.';
- memcpy(result + $1.len + 1, $3.str, $3.len);
- $$.str = result;
- $$.len = $1.len + $3.len + 1;
- $$.str[$$.len] = '\0';
-
-
- free($1.str);
- free($3.str);
- }
- ;
-
-/* define what we can parse */
-type_and_rdata:
- /*
- * All supported RR types. We don't support NULL and types marked obsolete.
- */
- T_A sp rdata_a
- | T_A sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_NS sp rdata_domain_name
- | T_NS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_MD sp rdata_domain_name { zc_warning_prev_line("MD is obsolete"); }
- | T_MD sp rdata_unknown
- {
- zc_warning_prev_line("MD is obsolete");
- $$ = $1; parse_unknown_rdata($1, $3);
- }
- | T_MF sp rdata_domain_name { zc_warning_prev_line("MF is obsolete"); }
- | T_MF sp rdata_unknown
- {
- zc_warning_prev_line("MF is obsolete");
- $$ = $1;
- parse_unknown_rdata($1, $3);
- }
- | T_CNAME sp rdata_domain_name
- | T_CNAME sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_SOA sp rdata_soa
- | T_SOA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_MB sp rdata_domain_name { zc_warning_prev_line("MB is obsolete"); }
- | T_MB sp rdata_unknown
- {
- zc_warning_prev_line("MB is obsolete");
- $$ = $1;
- parse_unknown_rdata($1, $3);
- }
- | T_MG sp rdata_domain_name
- | T_MG sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_MR sp rdata_domain_name
- | T_MR sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- /* NULL */
- | T_WKS sp rdata_wks
- | T_WKS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_PTR sp rdata_domain_name
- | T_PTR sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_HINFO sp rdata_hinfo
- | T_HINFO sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_MINFO sp rdata_minfo /* Experimental */
- | T_MINFO sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_MX sp rdata_mx
- | T_MX sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_TXT sp rdata_txt
- | T_TXT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_SPF sp rdata_txt
- | T_SPF sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_RP sp rdata_rp /* RFC 1183 */
- | T_RP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_AFSDB sp rdata_afsdb /* RFC 1183 */
- | T_AFSDB sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_X25 sp rdata_x25 /* RFC 1183 */
- | T_X25 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_ISDN sp rdata_isdn /* RFC 1183 */
- | T_ISDN sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_IPSECKEY sp rdata_ipseckey /* RFC 4025 */
- | T_IPSECKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_DHCID sp rdata_dhcid
- | T_DHCID sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_RT sp rdata_rt /* RFC 1183 */
- | T_RT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_NSAP sp rdata_nsap /* RFC 1706 */
- | T_NSAP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_SIG sp rdata_rrsig
- | T_SIG sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_KEY sp rdata_dnskey
- | T_KEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_PX sp rdata_px /* RFC 2163 */
- | T_PX sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_AAAA sp rdata_aaaa
- | T_AAAA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_LOC sp rdata_loc
- | T_LOC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_NXT sp rdata_nxt
- | T_NXT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_SRV sp rdata_srv
- | T_SRV sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_NAPTR sp rdata_naptr /* RFC 2915 */
- | T_NAPTR sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_KX sp rdata_kx /* RFC 2230 */
- | T_KX sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_CERT sp rdata_cert /* RFC 2538 */
- | T_CERT sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_DNAME sp rdata_domain_name /* RFC 2672 */
- | T_DNAME sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_APL trail /* RFC 3123 */
- | T_APL sp rdata_apl /* RFC 3123 */
- | T_APL sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_DS sp rdata_ds
- | T_DS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_DLV sp rdata_dlv
- {
- if (dlv_warn) {
- dlv_warn = 0;
- zc_warning_prev_line("DLV is experimental");
- }
- }
- | T_DLV sp rdata_unknown
- {
- if (dlv_warn) {
- dlv_warn = 0;
- zc_warning_prev_line("DLV is experimental");
- }
- $$ = $1;
- parse_unknown_rdata($1, $3);
- }
- | T_SSHFP sp rdata_sshfp
- | T_SSHFP sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_RRSIG sp rdata_rrsig
- | T_RRSIG sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_NSEC sp rdata_nsec
- | T_NSEC sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_NSEC3 sp rdata_nsec3
- | T_NSEC3 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_NSEC3PARAM sp rdata_nsec3_param
- | T_NSEC3PARAM sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_TLSA sp rdata_tlsa
- | T_TLSA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_DNSKEY sp rdata_dnskey
- | T_DNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
- | T_UTYPE sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
-
- | STR error NL
- {
- zc_error_prev_line("unrecognized RR type '%s'", $1.str);
- free($1.str);
- }
- | NO_MEM
- {
- zc_error_prev_line("parser ran out of memory!");
- YYABORT;
- }
- ;
-
-/*
- *
- * below are all the definition for all the different rdata
- *
- */
-
-rdata_a: dotted_str trail
- {
- zadd_rdata_wireformat(zparser_conv_a($1.str));
- free($1.str);
- }
- ;
-
-rdata_domain_name: dname trail
- {
- /* convert a single dname record */
- if ($1 != NULL) {
- if (!knot_dname_is_fqdn($1)) {
- knot_dname_cat($1, parser->root_domain);
-// parser->current_rrset->owner =
-// knot_dname_cat($1, parser->root_domain);
- }
- }
- zadd_rdata_domain($1);
- }
- ;
-
-rdata_soa: dname sp dname sp STR sp STR sp STR sp STR sp STR trail
- {
- /* convert the soa data */
- if (!knot_dname_is_fqdn($1)) {
- knot_dname_cat($1, parser->root_domain);
-// parser->current_rrset->owner =
-// knot_dname_cat($1, parser->root_domain);
-
- }
- if (!knot_dname_is_fqdn($3)) {
- knot_dname_cat($3, parser->root_domain);
-// parser->current_rrset->owner =
-// knot_dname_cat($3, parser->root_domain);
-
- }
- zadd_rdata_domain($1); /* prim. ns */
- zadd_rdata_domain($3); /* email */
- zadd_rdata_wireformat(zparser_conv_serial($5.str)); /* serial */
- zadd_rdata_wireformat(zparser_conv_period($7.str)); /* refresh */
- zadd_rdata_wireformat(zparser_conv_period($9.str)); /* retry */
- zadd_rdata_wireformat(zparser_conv_period($11.str)); /* expire */
- zadd_rdata_wireformat(zparser_conv_period($13.str)); /* minimum */
-
- free($5.str);
- free($7.str);
- free($9.str);
- free($11.str);
- free($13.str);
- }
- ;
-
-rdata_wks: dotted_str sp STR sp concatenated_str_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_a($1.str)); /* address */
- zadd_rdata_wireformat(zparser_conv_services($3.str, $5.str));
- /* protocol and services */
-
- free($1.str);
- free($3.str);
- free($5.str);
- }
- ;
-
-rdata_hinfo: STR sp STR trail
- {
- zadd_rdata_wireformat(zparser_conv_text($1.str, $1.len)); /* CPU */
- zadd_rdata_wireformat(zparser_conv_text($3.str, $3.len)); /* OS*/
-
- free($1.str);
- free($3.str);
- }
- ;
-
-rdata_minfo: dname sp dname trail
- {
- if (!knot_dname_is_fqdn($1)) {
-
- knot_dname_cat($1, parser->root_domain);
-
- }
- if (!knot_dname_is_fqdn($3)) {
-
- knot_dname_cat($3, parser->root_domain);
-
- }
-
- /* convert a single dname record */
- zadd_rdata_domain($1);
- zadd_rdata_domain($3);
- }
- ;
-
-rdata_mx: STR sp dname trail
- {
- if (!knot_dname_is_fqdn($3)) {
- knot_dname_cat($3, parser->root_domain);
- }
-
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* priority */
- zadd_rdata_domain($3); /* MX host */
-
- free($1.str);
- }
- ;
-
-rdata_txt: str_seq trail
- {
- ; //zadd_rdata_txt_clean_wireformat();
- }
- ;
-
-/* RFC 1183 */
-rdata_rp: dname sp dname trail
- {
- if (!knot_dname_is_fqdn($1)) {
- knot_dname_cat($1, parser->root_domain);
- }
- if (!knot_dname_is_fqdn($3)) {
- knot_dname_cat($3, parser->root_domain);
- }
-
- zadd_rdata_domain($1); /* mbox d-name */
- zadd_rdata_domain($3); /* txt d-name */
- }
- ;
-
-/* RFC 1183 */
-rdata_afsdb: STR sp dname trail
- {
- if (!knot_dname_is_fqdn($3)) {
- knot_dname_cat($3, parser->root_domain);
- }
-
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* subtype */
- zadd_rdata_domain($3); /* domain name */
-
- free($1.str);
- }
- ;
-
-/* RFC 1183 */
-rdata_x25: STR trail
- {
- zadd_rdata_wireformat(zparser_conv_text($1.str, $1.len));
- /* X.25 address. */
-
- free($1.str);
- }
- ;
-
-/* RFC 1183 */
-rdata_isdn: STR trail
- {
- zadd_rdata_wireformat(zparser_conv_text($1.str, $1.len));
- /* address */
-
- free($1.str);
- }
- | STR sp STR trail
- {
- zadd_rdata_wireformat(zparser_conv_text($1.str, $1.len));
- /* address */
- zadd_rdata_wireformat(zparser_conv_text($3.str, $3.len));
- /* sub-address */
-
- free($1.str);
- free($3.str);
- }
- ;
-
-/* RFC 1183 */
-rdata_rt: STR sp dname trail
- {
- if (!knot_dname_is_fqdn($3)) {
- knot_dname_cat($3, parser->root_domain);
- }
-
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* preference */
- zadd_rdata_domain($3); /* intermediate host */
-
- free($1.str);
- }
- ;
-
-/* RFC 1706 */
-rdata_nsap: str_dot_seq trail
- {
- /* String must start with "0x" or "0X". */
- if (strncasecmp($1.str, "0x", 2) != 0) {
- zc_error_prev_line("NSAP rdata must start with '0x'");
- } else {
- zadd_rdata_wireformat(zparser_conv_hex($1.str + 2,
- $1.len - 2));
- /* NSAP */
- }
-
- free($1.str);
- }
- ;
-
-/* RFC 2163 */
-rdata_px: STR sp dname sp dname trail
- {
- if (!knot_dname_is_fqdn($3)) {
- knot_dname_cat($3, parser->root_domain);
- }
- if (!knot_dname_is_fqdn($5)) {
- knot_dname_cat($5, parser->root_domain);
- }
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* preference */
- zadd_rdata_domain($3); /* MAP822 */
- zadd_rdata_domain($5); /* MAPX400 */
-
- free($1.str);
- }
- ;
-
-rdata_aaaa: dotted_str trail
- {
- zadd_rdata_wireformat(zparser_conv_aaaa($1.str));
- /* IPv6 address */
-
- free($1.str);
- }
- ;
-
-rdata_loc: concatenated_str_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_loc($1.str)); /* Location */
-
- free($1.str);
- }
- ;
-
-rdata_nxt: dname sp nxt_seq trail
- {
- if (!knot_dname_is_fqdn($1)) {
- knot_dname_cat($1, parser->root_domain);
- }
- zadd_rdata_domain($1); /* nxt name */
- zadd_rdata_wireformat(zparser_conv_nxt(nxtbits)); /* nxt bitlist */
- memset(nxtbits, 0, sizeof(nxtbits));
- }
- ;
-
-rdata_srv: STR sp STR sp STR sp dname trail
- {
- if (!knot_dname_is_fqdn($7)) {
- knot_dname_cat($7, parser->root_domain);
-
- }
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* prio */
- zadd_rdata_wireformat(zparser_conv_short($3.str)); /* weight */
- zadd_rdata_wireformat(zparser_conv_short($5.str)); /* port */
- zadd_rdata_domain($7); /* target name */
-
- free($1.str);
- free($3.str);
- free($5.str);
- }
- ;
-
-/* RFC 2915 */
-rdata_naptr: STR sp STR sp STR sp STR sp STR sp dname trail
- {
- if (!knot_dname_is_fqdn($11)) {
- knot_dname_cat($11, parser->root_domain);
-
- }
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* order */
- zadd_rdata_wireformat(zparser_conv_short($3.str)); /* preference */
- zadd_rdata_wireformat(zparser_conv_text($5.str, $5.len));
- /* flags */
- zadd_rdata_wireformat(zparser_conv_text($7.str, $7.len));
- /* service */
- zadd_rdata_wireformat(zparser_conv_text($9.str, $9.len));
- /* regexp */
- zadd_rdata_domain($11); /* target name */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- free($9.str);
- }
- ;
-
-/* RFC 2230 */
-rdata_kx: STR sp dname trail
- {
- if (!knot_dname_is_fqdn($3)) {
- knot_dname_cat($3, parser->root_domain);
- }
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* preference */
- zadd_rdata_domain($3); /* exchanger */
-
- free($1.str);
- }
- ;
-
-/* RFC 2538 */
-rdata_cert: STR sp STR sp STR sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_certificate_type($1.str));
- /* type */
- zadd_rdata_wireformat(zparser_conv_short($3.str)); /* key tag */
- zadd_rdata_wireformat(zparser_conv_algorithm($5.str));
- /* algorithm */
- zadd_rdata_wireformat(zparser_conv_b64($7.str));
- /* certificate or CRL */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- }
- ;
-
-/* RFC 3123 */
-rdata_apl: rdata_apl_seq trail
- ;
-
-rdata_apl_seq: dotted_str
- {
- zadd_rdata_txt_wireformat(zparser_conv_apl_rdata($1.str), 1);
-
- free($1.str);
- }
- | rdata_apl_seq sp dotted_str
- {
- zadd_rdata_txt_wireformat(zparser_conv_apl_rdata($3.str), 0);
-
- free($3.str);
- }
- ;
-
-rdata_ds: STR sp STR sp STR sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* keytag */
- zadd_rdata_wireformat(zparser_conv_algorithm($3.str)); /* alg */
- zadd_rdata_wireformat(zparser_conv_byte($5.str)); /* type */
- zadd_rdata_wireformat(zparser_conv_hex($7.str, $7.len)); /* hash */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- }
- ;
-
-rdata_dlv: STR sp STR sp STR sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* keytag */
- zadd_rdata_wireformat(zparser_conv_algorithm($3.str)); /* alg */
- zadd_rdata_wireformat(zparser_conv_byte($5.str)); /* type */
- zadd_rdata_wireformat(zparser_conv_hex($7.str, $7.len)); /* hash */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- }
- ;
-
-rdata_sshfp: STR sp STR sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_byte($1.str)); /* alg */
- zadd_rdata_wireformat(zparser_conv_byte($3.str)); /* fp type */
- zadd_rdata_wireformat(zparser_conv_hex($5.str, $5.len)); /* hash */
-
- free($1.str);
- free($3.str);
- free($5.str);
- }
- ;
-
-rdata_dhcid: str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_b64($1.str)); /* data blob */
-
- free($1.str);
- }
- ;
-
-rdata_rrsig: STR sp STR sp STR sp STR sp STR sp STR
- sp STR sp wire_dname sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_rrtype($1.str));
- /* rr covered */
- zadd_rdata_wireformat(zparser_conv_algorithm($3.str)); /* alg */
- zadd_rdata_wireformat(zparser_conv_byte($5.str)); /* # labels */
- zadd_rdata_wireformat(zparser_conv_period($7.str));
- /* # orig TTL */
- zadd_rdata_wireformat(zparser_conv_time($9.str)); /* sig exp */
- zadd_rdata_wireformat(zparser_conv_time($11.str)); /* sig inc */
- zadd_rdata_wireformat(zparser_conv_short($13.str)); /* key id */
-/* zadd_rdata_wireformat(zparser_conv_dns_name((const uint8_t*)
- $15.str,
- $15.len));*/
- knot_dname_t *dname =
- knot_dname_new_from_wire((uint8_t *)$15.str, $15.len, NULL);
- knot_dname_retain(dname);
- if (dname == NULL) {
- parser->error_occurred = KNOTDZCOMPILE_ENOMEM;
- } else {
- knot_dname_cat(dname, parser->root_domain);
- }
-
- zadd_rdata_domain(dname);
- /* sig name */
- zadd_rdata_wireformat(zparser_conv_b64($17.str)); /* sig data */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- free($9.str);
- free($11.str);
- free($13.str);
- free($15.str);
- free($17.str);
- }
- ;
-
-rdata_nsec: wire_dname nsec_seq
- {
-/* zadd_rdata_wireformat(zparser_conv_dns_name((const uint8_t*)
- $1.str,
- $1.len));*/
-
- knot_dname_t *dname =
- knot_dname_new_from_wire((uint8_t *)$1.str, $1.len, NULL);
- knot_dname_retain(dname);
- free($1.str);
-
- knot_dname_cat(dname, parser->root_domain);
-
- zadd_rdata_domain(dname);
- /* nsec name */
- zadd_rdata_wireformat(zparser_conv_nsec(nsecbits));
- /* nsec bitlist */
- memset(nsecbits, 0, sizeof(nsecbits));
- nsec_highest_rcode = 0;
- }
- ;
-
-rdata_nsec3: STR sp STR sp STR sp STR sp STR nsec_seq
- {
-#ifdef NSEC3
- nsec3_add_params($1.str, $3.str, $5.str, $7.str, $7.len);
-
-/* knot_dname_t *dname =
- knot_dname_new_from_str($9.str, $9.len, NULL);
-
- zadd_rdata_domain(dname); */
-
- zadd_rdata_wireformat(zparser_conv_b32($9.str));
- /* next hashed name */
- zadd_rdata_wireformat(zparser_conv_nsec(nsecbits));
- /* nsec bitlist */
- memset(nsecbits, 0, sizeof(nsecbits));
- nsec_highest_rcode = 0;
-#else
- zc_error_prev_line("nsec3 not supported");
-#endif /* NSEC3 */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- free($9.str);
- }
- ;
-
-rdata_nsec3_param: STR sp STR sp STR sp STR trail
- {
-#ifdef NSEC3
- nsec3_add_params($1.str, $3.str, $5.str, $7.str, $7.len);
-#else
- zc_error_prev_line("nsec3 not supported");
-#endif /* NSEC3 */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- }
- ;
-
-rdata_tlsa: STR sp STR sp STR sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_byte($1.str));
- zadd_rdata_wireformat(zparser_conv_byte($3.str));
- zadd_rdata_wireformat(zparser_conv_byte($5.str));
- zadd_rdata_wireformat(zparser_conv_hex($7.str, $7.len));
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- }
- ;
-
-rdata_dnskey: STR sp STR sp STR sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_short($1.str)); /* flags */
- zadd_rdata_wireformat(zparser_conv_byte($3.str)); /* proto */
- zadd_rdata_wireformat(zparser_conv_algorithm($5.str)); /* alg */
- zadd_rdata_wireformat(zparser_conv_b64($7.str)); /* hash */
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
- }
- ;
-
-rdata_ipsec_base: STR sp STR sp STR sp dotted_str
- {
- knot_dname_t* name = 0;
- zadd_rdata_wireformat(zparser_conv_byte($1.str)); /* precedence */
- zadd_rdata_wireformat(zparser_conv_byte($3.str));
- /* gateway type */
- zadd_rdata_wireformat(zparser_conv_byte($5.str)); /* algorithm */
- switch(atoi($3.str)) {
- case IPSECKEY_NOGATEWAY:
- zadd_rdata_wireformat(alloc_rdata_init("", 0));
- break;
- case IPSECKEY_IP4:
- zadd_rdata_wireformat(zparser_conv_a($7.str));
- break;
- case IPSECKEY_IP6:
- zadd_rdata_wireformat(zparser_conv_aaaa($7.str));
- break;
- case IPSECKEY_DNAME:
- /* convert and insert the dname */
- if(strlen($7.str) == 0)
- zc_error_prev_line("IPSECKEY must specify"
- "gateway name");
- name = knot_dname_new_from_str($7.str,
- strlen($7.str),
- NULL);
- if(!name) {
- zc_error_prev_line("IPSECKEY bad gateway"
- "dname %s", $7.str);
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
-
- if(!knot_dname_is_fqdn(name)) {
- assert(parser->origin);
- name = knot_dname_cat(name,
- parser->origin->owner);
- if (name == NULL) {
- zc_error_prev_line("Cannot concatenete dnames, probably run out of memory!\n");
- YYABORT;
- }
- }
-
- free($1.str);
- free($3.str);
- free($5.str);
- free($7.str);
-
- uint16_t* dncpy = malloc(sizeof(uint8_t) * name->size + 2);
- dncpy[0] = name->size;
- if (dncpy == NULL) {
- ERR_ALLOC_FAILED;
- knot_rrset_deep_free(&(parser->current_rrset),
- 0, 0, 0);
- knot_zone_deep_free(&(parser->current_zone),
- 1);
- YYABORT;
- }
-
- memcpy((uint8_t *)(dncpy + 1), name->name, name->size);
- zadd_rdata_wireformat(dncpy);
- knot_dname_free(&name);
- break;
- default:
- zc_error_prev_line("unknown IPSECKEY gateway type");
- }
- }
- ;
-
-rdata_ipseckey: rdata_ipsec_base sp str_sp_seq trail
- {
- zadd_rdata_wireformat(zparser_conv_b64($3.str)); /* public key */
-
- free($3.str);
- }
- | rdata_ipsec_base trail
- ;
-
-rdata_unknown: URR sp STR sp str_sp_seq trail
- {
- /* $2 is the number of octects, currently ignored */
- $$ = zparser_conv_hex($5.str, $5.len);
- free($5.str);
- free($3.str);
- }
- | URR sp STR trail
- {
- $$ = zparser_conv_hex("", 0);
- free($3.str);
- }
- | URR error NL
- {
- $$ = zparser_conv_hex("", 0);
- }
- ;
-%%
-
-int zp_wrap(void)
-{
- return 1;
-}
-
-/*
- * Create the parser.
- */
-zparser_type *zparser_create()
-{
- zparser_type *result = malloc(sizeof(zparser_type));
- if (result == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
-
- result->temporary_items = malloc(MAXRDATALEN *
- sizeof(knot_rdata_item_t));
- if (result->temporary_items == NULL) {
- ERR_ALLOC_FAILED;
- free(result);
- return NULL;
- }
-
- result->current_rrset = knot_rrset_new(NULL, 0, 0, 0);
- if (result->current_rrset == NULL) {
- free(result->temporary_items);
- free(result);
- return NULL;
- }
-
- result->root_domain = knot_dname_new_from_str(".", 1, NULL);
- if (result->root_domain == NULL) {
- free(result->temporary_items);
- free(result->current_rrset);
- free(result);
- return NULL;
- }
-
- return result;
-}
-
-/*
- * Initialize the parser for a new zone file.
- */
-void
-zparser_init(const char *filename, uint32_t ttl, uint16_t rclass,
- knot_node_t *origin, knot_dname_t *origin_from_config)
-{
- memset(nxtbits, 0, sizeof(nxtbits));
- memset(nsecbits, 0, sizeof(nsecbits));
- nsec_highest_rcode = 0;
-
- parser->current_zone = NULL;
- parser->prev_dname = NULL;
-
- parser->default_ttl = ttl;
- parser->default_class = rclass;
-
- parser->origin = origin;
- parser->prev_dname = NULL;//parser->origin->owner;
-
- parser->default_apex = origin;
- parser->error_occurred = 0;
- parser->errors = 0;
- parser->line = 1;
- parser->filename = filename;
- parser->rdata_count = 0;
- parser->origin_from_config = origin_from_config;
- knot_dname_retain(origin_from_config);
-
- parser->last_node = origin;
-// parser->root_domain = NULL;
-
- /* Create zone */
- parser->current_zone = knot_zone_new(origin, 0, 1);
-
- parser->node_rrsigs = NULL;
-
- parser->current_rrset->rclass = parser->default_class;
- parser->current_rrset->rdata = NULL;
-}
-
-
-void zparser_free()
-{
- knot_dname_release(parser->root_domain);
-// knot_dname_release(parser->prev_dname);
- knot_zone_deep_free(&parser->current_zone, 1);
- knot_dname_release(parser->origin_from_config);
- free(parser->temporary_items);
- if (parser->current_rrset != NULL) {
- free(parser->current_rrset);
- }
- free(parser);
-}
-
-void
-yyerror(void *scanner, const char *message)
-{
- zc_error("%s", message);
-}
-
-static void
-error_va_list(unsigned line, const char *fmt, va_list args)
-{
- char sbuf[4096] = {0};
- size_t buflen = sizeof(sbuf) - 1;
- char *buf = sbuf;
- int wb = 0;
- if (parser->filename) {
- wb = snprintf(buf, buflen, "%s:%u: ",
- parser->filename, line);
- if (wb > 0) {
- buf += wb;
- buflen -= wb;
- }
- }
-
- wb = vsnprintf(buf, buflen, fmt, args);
- if (wb > 0) {
- buf += wb;
- buflen -= wb;
- *buf = '\n';
- *(buf + 1) = '\0';
- }
-
- log_zone_error("%s", sbuf);
-
- ++parser->errors;
- parser->error_occurred = 1;
-}
-
-/* the line counting sux, to say the least
- * with this grose hack we try do give sane
- * numbers back */
-void
-zc_error_prev_line(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- error_va_list(parser->line - 1, fmt, args);
- va_end(args);
-}
-
-void
-zc_error(const char *fmt, ...)
-{
- /* send an error message to stderr */
- va_list args;
- va_start(args, fmt);
- error_va_list(parser->line, fmt, args);
- va_end(args);
-}
-
-static void
-warning_va_list(unsigned line, const char *fmt, va_list args)
-{
- char sbuf[4096] = {0};
- size_t buflen = sizeof(sbuf) - 1;
- char *buf = sbuf;
- int wb = 0;
- if (parser->filename) {
- wb = snprintf(buf, buflen, "%s:%u: ",
- parser->filename, line);
- if (wb > 0) {
- buf += wb;
- buflen -= wb;
- }
- }
-
- wb = vsnprintf(buf, buflen, fmt, args);
- if (wb > 0) {
- buf += wb;
- buflen -= wb;
- *buf = '\n';
- *(buf + 1) = '\0';
- }
-
- log_zone_warning("%s", sbuf);
-}
-
-void
-zc_warning_prev_line(const char *fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- warning_va_list(parser->line - 1, fmt, args);
- va_end(args);
-}
-
-void
-zc_warning(const char *fmt, ... )
-{
- va_list args;
- va_start(args, fmt);
- warning_va_list(parser->line, fmt, args);
- va_end(args);
-}
-
-#ifdef NSEC3
-static void
-nsec3_add_params(const char* hashalgo_str, const char* flag_str,
- const char* iter_str, const char* salt_str, int salt_len)
-{
- zadd_rdata_wireformat(zparser_conv_byte(hashalgo_str));
- zadd_rdata_wireformat(zparser_conv_byte(flag_str));
- zadd_rdata_wireformat(zparser_conv_short(iter_str));
-
- /* salt */
- if(strcmp(salt_str, "-") != 0)
- zadd_rdata_wireformat(zparser_conv_hex_length(salt_str,
- salt_len));
- else
- zadd_rdata_wireformat(alloc_rdata_init("", 1));
-
-}
-#endif /* NSEC3 */
diff --git a/src/zscanner/file_loader.c b/src/zscanner/file_loader.c
new file mode 100644
index 0000000..ce44dbe
--- /dev/null
+++ b/src/zscanner/file_loader.c
@@ -0,0 +1,255 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "zscanner/file_loader.h"
+
+#include <inttypes.h> // PRIu64
+#include <unistd.h> // sysconf
+#include <stdio.h> // sprintf
+#include <stdlib.h> // free
+#include <stdbool.h> // bool
+#include <string.h> // strlen
+#include <fcntl.h> // open
+#include <sys/stat.h> // fstat
+#include <sys/mman.h> // mmap
+
+#include "common/errcode.h" // error codes
+
+/*! \brief Mmap block size in bytes. */
+#define BLOCK_SIZE 30000000
+
+/*!
+ * \brief Processes zone settings block.
+ *
+ * Before zone file processing via scanner it's necessary to process first
+ * settings block using this function. Settings block contains ORIGIN and
+ * TTL directive.
+ *
+ * \param fl File loader structure.
+ *
+ * \retval 0 if success.
+ * \retval -1 if error.
+ */
+static int load_settings(file_loader_t *fl)
+{
+ int ret;
+ char *settings_name;
+ scanner_t *settings_scanner;
+
+ // Creating name for zone defaults.
+ size_t buf_len = strlen(fl->file_name) + 100;
+ settings_name = malloc(buf_len);
+ ret = snprintf(settings_name, buf_len, "ZONE DEFAULTS <%s>",
+ fl->file_name);
+ if (ret < 0 || (size_t)ret >= buf_len) {
+ free(settings_name);
+ return -1;
+ }
+
+ // Temporary scanner for zone settings.
+ settings_scanner = scanner_create(settings_name);
+
+ // Use parent processing functions.
+ settings_scanner->process_record = fl->scanner->process_record;
+ settings_scanner->process_error = fl->scanner->process_error;
+
+ // Scanning zone settings.
+ ret = scanner_process(fl->settings_buffer,
+ fl->settings_buffer + fl->settings_length,
+ true,
+ settings_scanner);
+
+ // If no error occured, then copy scanned settings to actual context.
+ if (ret == 0) {
+ memcpy(fl->scanner->zone_origin,
+ settings_scanner->zone_origin,
+ settings_scanner->zone_origin_length);
+ fl->scanner->zone_origin_length =
+ settings_scanner->zone_origin_length;
+ fl->scanner->default_ttl = settings_scanner->default_ttl;
+ }
+
+ // Destroying temporary scanner.
+ scanner_free(settings_scanner);
+
+ free(settings_name);
+
+ return ret;
+}
+
+file_loader_t* file_loader_create(const char *file_name,
+ const char *zone_origin,
+ const uint16_t default_class,
+ const uint32_t default_ttl,
+ void (*process_record)(const scanner_t *),
+ void (*process_error)(const scanner_t *),
+ void *data)
+{
+ int ret;
+
+ // Creating zeroed structure.
+ file_loader_t *fl = calloc(1, sizeof(file_loader_t));
+
+ if (fl == NULL) {
+ return NULL;
+ }
+
+ // Copying file name.
+ fl->file_name = strdup(file_name);
+
+ // Opening zone file.
+ fl->fd = open(fl->file_name, O_RDONLY);
+
+ if (fl->fd == -1) {
+ free(fl->file_name);
+ free(fl);
+ return NULL;
+ }
+
+ // Creating zone scanner.
+ fl->scanner = scanner_create(file_name);
+
+ // Setting processing functions and data pointer.
+ fl->scanner->process_record = process_record;
+ fl->scanner->process_error = process_error;
+ fl->scanner->data = data;
+
+ // Default class initialization.
+ fl->scanner->default_class = default_class;
+
+ // Filling zone settings buffer.
+ ret = snprintf(fl->settings_buffer,
+ sizeof(fl->settings_buffer),
+ "$ORIGIN %s\n"
+ "$TTL %u\n",
+ zone_origin, default_ttl);
+ if (ret <= 0 || (size_t)ret >= sizeof(fl->settings_buffer)) {
+ file_loader_free(fl);
+ return NULL;
+ }
+
+ fl->settings_length = ret;
+
+ return fl;
+}
+
+void file_loader_free(file_loader_t *fl)
+{
+ close(fl->fd);
+ free(fl->file_name);
+ scanner_free(fl->scanner);
+ free(fl);
+}
+
+int file_loader_process(file_loader_t *fl)
+{
+ int ret;
+ char *data; // Mmaped data.
+ bool is_last_block;
+ long page_size;
+ uint64_t n_blocks;
+ uint64_t block_id;
+ uint64_t default_block_size;
+ uint64_t scanner_start; // Current block start to scan.
+ uint64_t block_size; // Current block size to scan.
+ struct stat file_stat;
+
+ // Last block - secure termination of zone file.
+ char *zone_termination = "\n";
+
+ // Getting OS page size.
+ page_size = sysconf(_SC_PAGESIZE);
+
+ // Getting file information.
+ if (fstat(fl->fd, &file_stat) == -1) {
+ return FLOADER_EFSTAT;
+ }
+
+ // Check for directory.
+ if (S_ISDIR(file_stat.st_mode)) {
+ return FLOADER_EDIRECTORY;
+ }
+
+ // Check for empty file.
+ if (file_stat.st_size == 0) {
+ return FLOADER_EEMPTY;
+ }
+
+ // Block size adjustment to multiple of page size.
+ default_block_size = (BLOCK_SIZE / page_size) * page_size;
+
+ // Number of blocks which cover the whole file (ceiling operation).
+ n_blocks = 1 + ((file_stat.st_size - 1) / default_block_size);
+
+ // Process settings using scanner (like initial ORIGIN and TTL).
+ ret = load_settings(fl);
+
+ if (ret != 0) {
+ return FLOADER_EDEFAULTS;
+ }
+
+ // Loop over zone file blocks.
+ for (block_id = 0; block_id < n_blocks; block_id++) {
+ scanner_start = block_id * default_block_size;
+ is_last_block = false;
+ block_size = default_block_size;
+
+ // The last block is probably shorter.
+ if (block_id == (n_blocks - 1)) {
+ block_size = file_stat.st_size - scanner_start;
+ is_last_block = true;
+ }
+
+ // Zone file block mapping.
+ data = mmap(0,
+ block_size,
+ PROT_READ,
+ MAP_SHARED,
+ fl->fd,
+ scanner_start);
+
+ if (data == MAP_FAILED) {
+ return FLOADER_EMMAP;
+ }
+
+ // Scan zone file.
+ ret = scanner_process(data,
+ data + block_size,
+ false,
+ fl->scanner);
+
+ // Artificial last block containing newline char only.
+ if (is_last_block == true && fl->scanner->stop == 0) {
+ ret = scanner_process(zone_termination,
+ zone_termination + 1,
+ true,
+ fl->scanner);
+ }
+
+ // Zone file block unmapping.
+ if (munmap(data, block_size) == -1) {
+ return FLOADER_EMUNMAP;
+ }
+ }
+
+ // Check for scanner return.
+ if (ret != 0) {
+ return FLOADER_ESCANNER;
+ }
+
+ return KNOT_EOK;
+}
diff --git a/src/zscanner/file_loader.h b/src/zscanner/file_loader.h
new file mode 100644
index 0000000..6bca297
--- /dev/null
+++ b/src/zscanner/file_loader.h
@@ -0,0 +1,105 @@
+/* Copyright (C) 2011 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 file_loader.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Zone file loader.
+ *
+ * \addtogroup zone_scanner
+ * @{
+ */
+
+#ifndef _ZSCANNER__FILE_LOADER_H_
+#define _ZSCANNER__FILE_LOADER_H_
+
+#include <stdint.h> // uint32_t
+
+#include "common/descriptor.h" // KNOT_CLASS_IN
+#include "zscanner/scanner.h" // scanner_t
+
+/*! \brief Settings block size in bytes. */
+#define SETTINGS_BUFFER_LENGTH 1024
+/*! \brief Default ttl value. */
+#define DEFAULT_TTL 3600
+/*! \brief Default class value. */
+#define DEFAULT_CLASS KNOT_CLASS_IN
+
+/*! \brief Structure for zone file loader (each included file has one). */
+typedef struct {
+ /*!< File descriptor. */
+ int fd;
+ /*!< Zone file name this loader belongs to. */
+ char *file_name;
+ /*!< Zone scanner context stucture. */
+ scanner_t *scanner;
+ /*!< Zone settings buffer. */
+ char settings_buffer[SETTINGS_BUFFER_LENGTH];
+ /*!< Length of zone settings buffer. */
+ uint32_t settings_length;
+} file_loader_t;
+
+/*!
+ * \brief Creates file loader structure.
+ *
+ * \param file_name Name of file to process.
+ * \param zone_origin Initial zone origin (used in settings block).
+ * \param default_class Default class value.
+ * \param default_ttl Default ttl value (used in settings block).
+ * \param process_record Processing callback function.
+ * \param process_error Error callback function.
+ * \param data Arbitrary data useful in callback functions.
+ *
+ * \retval file_loader if success.
+ * \retval 0 if error.
+ */
+file_loader_t* file_loader_create(const char *file_name,
+ const char *zone_origin,
+ const uint16_t default_class,
+ const uint32_t default_ttl,
+ void (*process_record)(const scanner_t *),
+ void (*process_error)(const scanner_t *),
+ void *data);
+
+/*!
+ * \brief Destroys file loader structure.
+ *
+ * \param file_loader File loader structure.
+ */
+void file_loader_free(file_loader_t *file_loader);
+
+/*!
+ * \brief Processes zone file.
+ *
+ * Launches zone file processing using zone scanner. For each correctly
+ * recognized record data process_record callback function is called. If any
+ * syntax error occures, then process_error callback function is called.
+ *
+ * \note Zone scanner error code and other information are stored in
+ * fl.scanner context.
+ *
+ * \param file_loader File loader structure.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval error_code if error.
+ */
+int file_loader_process(file_loader_t *file_loader);
+
+
+#endif // _ZSCANNER__FILE_LOADER_H_
+
+/*! @} */
diff --git a/src/zscanner/scanner.c b/src/zscanner/scanner.c
new file mode 100644
index 0000000..4236ad4
--- /dev/null
+++ b/src/zscanner/scanner.c
@@ -0,0 +1,7803 @@
+
+#line 1 "./zscanner/scanner.rl"
+/* Copyright (C) 2011 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 "zscanner/scanner.h"
+
+#include <stdint.h> // uint32_t
+#include <stdlib.h> // calloc
+#include <stdio.h> // sprintf
+#include <libgen.h> // dirname
+#include <stdbool.h> // bool
+#include <math.h> // pow
+#include <string.h> // strdup
+#include <sys/types.h> // (OpenBSD)
+#include <sys/socket.h> // AF_INET (BSD)
+#include <netinet/in.h> // in_addr (BSD)
+#include <arpa/inet.h> // inet_pton
+
+#include "common/errcode.h" // error codes
+#include "common/descriptor.h" // KNOT_RRTYPE_A
+#include "zscanner/file_loader.h" // file_loader
+#include "zscanner/scanner_functions.h" // Base64
+
+/*! \brief Shorthand for setting warning data. */
+#define SCANNER_WARNING(code) { s->error_code = code; }
+/*! \brief Shorthand for setting error data. */
+#define SCANNER_ERROR(code) { s->error_code = code; s->stop = true; }
+
+/*!
+ * \brief Writes record type number to r_data.
+ *
+ * \param type Type number.
+ * \param rdata_tail Position where to write type number to.
+ */
+static inline void type_num(const uint16_t type, uint8_t **rdata_tail)
+{
+ *((uint16_t *)*rdata_tail) = htons(type);
+ *rdata_tail += 2;
+}
+
+/*!
+ * \brief Sets bit to bitmap window.
+ *
+ * \param type Type number.
+ * \param s Scanner context.
+ */
+static inline void window_add_bit(const uint16_t type, scanner_t *s) {
+ uint8_t win = type / 256;
+ uint8_t bit_pos = type % 256;
+ uint8_t byte_pos = bit_pos / 8;
+
+ ((s->windows[win]).bitmap)[byte_pos] |= 128 >> (bit_pos % 8);
+
+ if ((s->windows[win]).length < byte_pos + 1) {
+ (s->windows[win]).length = byte_pos + 1;
+ }
+
+ if (s->last_window < win) {
+ s->last_window = win;
+ }
+}
+
+// Include scanner file (in Ragel).
+
+#line 80 "zscanner/scanner.c"
+static const short _zone_scanner_actions[] = {
+ 0, 1, 0, 1, 1, 1, 2, 1,
+ 3, 1, 4, 1, 6, 1, 9, 1,
+ 10, 1, 11, 1, 13, 1, 14, 1,
+ 16, 1, 19, 1, 20, 1, 22, 1,
+ 23, 1, 26, 1, 27, 1, 28, 1,
+ 30, 1, 31, 1, 40, 1, 41, 1,
+ 42, 1, 44, 1, 46, 1, 47, 1,
+ 48, 1, 49, 1, 51, 1, 53, 1,
+ 54, 1, 56, 1, 58, 1, 60, 1,
+ 61, 1, 65, 1, 66, 1, 69, 1,
+ 70, 1, 72, 1, 73, 1, 76, 1,
+ 78, 1, 79, 1, 80, 1, 81, 1,
+ 82, 1, 83, 1, 84, 1, 85, 1,
+ 87, 1, 89, 1, 91, 1, 95, 1,
+ 96, 1, 100, 1, 101, 1, 105, 1,
+ 106, 1, 107, 1, 108, 1, 109, 1,
+ 110, 1, 111, 1, 112, 1, 113, 1,
+ 114, 1, 115, 1, 116, 1, 117, 1,
+ 118, 1, 120, 1, 121, 1, 122, 1,
+ 123, 1, 148, 1, 149, 1, 150, 1,
+ 151, 1, 152, 1, 153, 1, 154, 1,
+ 155, 1, 156, 1, 157, 1, 158, 1,
+ 159, 1, 160, 1, 161, 1, 162, 1,
+ 163, 1, 164, 1, 165, 1, 166, 1,
+ 167, 1, 168, 1, 169, 1, 170, 1,
+ 171, 1, 172, 1, 173, 1, 174, 1,
+ 175, 1, 176, 1, 177, 1, 178, 1,
+ 179, 1, 180, 1, 181, 1, 182, 1,
+ 183, 1, 184, 1, 185, 1, 186, 1,
+ 187, 1, 188, 1, 189, 1, 190, 1,
+ 191, 1, 192, 1, 193, 1, 194, 1,
+ 195, 1, 196, 1, 197, 1, 198, 1,
+ 199, 1, 200, 1, 201, 1, 202, 1,
+ 203, 1, 204, 1, 205, 1, 206, 1,
+ 207, 1, 208, 1, 209, 1, 210, 1,
+ 211, 1, 212, 1, 213, 1, 214, 1,
+ 215, 1, 216, 1, 217, 1, 218, 1,
+ 219, 1, 220, 1, 221, 1, 222, 1,
+ 223, 1, 224, 1, 225, 1, 227, 1,
+ 229, 1, 230, 1, 231, 1, 232, 1,
+ 239, 1, 240, 1, 245, 1, 247, 1,
+ 252, 1, 255, 1, 256, 1, 257, 1,
+ 258, 1, 260, 1, 261, 1, 262, 1,
+ 263, 1, 265, 2, 0, 44, 2, 1,
+ 0, 2, 1, 27, 2, 1, 261, 2,
+ 1, 304, 2, 2, 27, 2, 2, 263,
+ 2, 3, 27, 2, 3, 263, 2, 4,
+ 65, 2, 4, 69, 2, 5, 6, 2,
+ 9, 10, 2, 12, 13, 2, 14, 10,
+ 2, 14, 11, 2, 15, 20, 2, 15,
+ 69, 2, 15, 76, 2, 16, 0, 2,
+ 16, 2, 2, 16, 3, 2, 16, 75,
+ 2, 18, 0, 2, 19, 9, 2, 22,
+ 63, 2, 22, 100, 2, 22, 111, 2,
+ 23, 0, 2, 23, 1, 2, 23, 2,
+ 2, 23, 3, 2, 23, 24, 2, 23,
+ 228, 2, 25, 21, 2, 26, 1, 2,
+ 26, 2, 2, 26, 3, 2, 26, 85,
+ 2, 26, 263, 2, 27, 1, 2, 27,
+ 2, 2, 27, 3, 2, 28, 4, 2,
+ 28, 260, 2, 28, 265, 2, 29, 21,
+ 2, 30, 0, 2, 30, 1, 2, 30,
+ 2, 2, 30, 3, 2, 30, 24, 2,
+ 31, 36, 2, 32, 31, 2, 33, 65,
+ 2, 33, 245, 2, 33, 260, 2, 33,
+ 265, 2, 37, 233, 2, 37, 234, 2,
+ 37, 235, 2, 37, 236, 2, 37, 237,
+ 2, 37, 238, 2, 40, 0, 2, 40,
+ 1, 2, 40, 2, 2, 40, 3, 2,
+ 41, 0, 2, 41, 1, 2, 41, 2,
+ 2, 41, 3, 2, 41, 24, 2, 42,
+ 0, 2, 42, 1, 2, 42, 2, 2,
+ 42, 3, 2, 43, 259, 2, 44, 1,
+ 2, 44, 2, 2, 44, 3, 2, 51,
+ 2, 2, 51, 3, 2, 51, 42, 2,
+ 51, 85, 2, 52, 53, 2, 54, 1,
+ 2, 54, 2, 2, 54, 3, 2, 55,
+ 260, 2, 56, 0, 2, 57, 58, 2,
+ 59, 60, 2, 61, 0, 2, 61, 56,
+ 2, 67, 19, 2, 71, 63, 2, 72,
+ 2, 2, 72, 3, 2, 73, 4, 2,
+ 74, 19, 2, 76, 4, 2, 80, 1,
+ 2, 80, 27, 2, 82, 83, 2, 84,
+ 1, 2, 84, 2, 2, 84, 3, 2,
+ 85, 1, 2, 85, 2, 2, 85, 3,
+ 2, 85, 263, 2, 86, 87, 2, 88,
+ 260, 2, 89, 90, 2, 91, 92, 2,
+ 93, 94, 2, 93, 95, 2, 93, 96,
+ 2, 97, 98, 2, 99, 260, 2, 102,
+ 260, 2, 103, 0, 2, 119, 260, 2,
+ 121, 0, 2, 122, 0, 2, 123, 0,
+ 2, 124, 0, 2, 125, 0, 2, 126,
+ 0, 2, 127, 0, 2, 128, 0, 2,
+ 129, 0, 2, 130, 0, 2, 131, 0,
+ 2, 132, 0, 2, 133, 0, 2, 134,
+ 0, 2, 135, 0, 2, 136, 0, 2,
+ 137, 0, 2, 138, 0, 2, 139, 0,
+ 2, 140, 0, 2, 141, 0, 2, 142,
+ 0, 2, 143, 0, 2, 144, 0, 2,
+ 145, 260, 2, 146, 260, 2, 147, 260,
+ 2, 148, 1, 2, 148, 2, 2, 148,
+ 3, 2, 149, 1, 2, 149, 2, 2,
+ 149, 3, 2, 150, 1, 2, 150, 2,
+ 2, 150, 3, 2, 151, 1, 2, 151,
+ 2, 2, 151, 3, 2, 152, 1, 2,
+ 152, 2, 2, 152, 3, 2, 153, 1,
+ 2, 153, 2, 2, 153, 3, 2, 154,
+ 1, 2, 154, 2, 2, 154, 3, 2,
+ 155, 1, 2, 155, 2, 2, 155, 3,
+ 2, 156, 1, 2, 156, 2, 2, 156,
+ 3, 2, 157, 1, 2, 157, 2, 2,
+ 157, 3, 2, 158, 1, 2, 158, 2,
+ 2, 158, 3, 2, 159, 1, 2, 159,
+ 2, 2, 159, 3, 2, 160, 1, 2,
+ 160, 2, 2, 160, 3, 2, 161, 1,
+ 2, 161, 2, 2, 161, 3, 2, 162,
+ 1, 2, 162, 2, 2, 162, 3, 2,
+ 163, 1, 2, 163, 2, 2, 163, 3,
+ 2, 164, 1, 2, 164, 2, 2, 164,
+ 3, 2, 165, 1, 2, 165, 2, 2,
+ 165, 3, 2, 166, 1, 2, 166, 2,
+ 2, 166, 3, 2, 167, 1, 2, 167,
+ 2, 2, 167, 3, 2, 168, 1, 2,
+ 168, 2, 2, 168, 3, 2, 169, 1,
+ 2, 169, 2, 2, 169, 3, 2, 170,
+ 1, 2, 170, 2, 2, 170, 3, 2,
+ 171, 1, 2, 171, 2, 2, 171, 3,
+ 2, 172, 1, 2, 172, 2, 2, 172,
+ 3, 2, 173, 1, 2, 173, 2, 2,
+ 173, 3, 2, 174, 1, 2, 174, 2,
+ 2, 174, 3, 2, 175, 1, 2, 175,
+ 2, 2, 175, 3, 2, 176, 1, 2,
+ 176, 2, 2, 176, 3, 2, 177, 1,
+ 2, 177, 2, 2, 177, 3, 2, 178,
+ 1, 2, 178, 2, 2, 178, 3, 2,
+ 179, 1, 2, 179, 2, 2, 179, 3,
+ 2, 180, 1, 2, 180, 2, 2, 180,
+ 3, 2, 181, 1, 2, 181, 2, 2,
+ 181, 3, 2, 182, 1, 2, 182, 2,
+ 2, 182, 3, 2, 183, 1, 2, 183,
+ 2, 2, 183, 3, 2, 184, 1, 2,
+ 184, 2, 2, 184, 3, 2, 185, 1,
+ 2, 185, 2, 2, 185, 3, 2, 186,
+ 1, 2, 186, 2, 2, 186, 3, 2,
+ 187, 1, 2, 187, 2, 2, 187, 3,
+ 2, 188, 1, 2, 188, 2, 2, 188,
+ 3, 2, 189, 1, 2, 189, 2, 2,
+ 189, 3, 2, 190, 1, 2, 190, 2,
+ 2, 190, 3, 2, 191, 1, 2, 191,
+ 2, 2, 191, 3, 2, 192, 1, 2,
+ 192, 2, 2, 192, 3, 2, 193, 1,
+ 2, 193, 2, 2, 193, 3, 2, 194,
+ 1, 2, 194, 2, 2, 194, 3, 2,
+ 195, 1, 2, 195, 2, 2, 195, 3,
+ 2, 196, 1, 2, 196, 2, 2, 196,
+ 3, 2, 197, 1, 2, 197, 2, 2,
+ 197, 3, 2, 198, 1, 2, 198, 2,
+ 2, 198, 3, 2, 199, 1, 2, 199,
+ 2, 2, 199, 3, 2, 200, 1, 2,
+ 200, 2, 2, 200, 3, 2, 201, 1,
+ 2, 201, 2, 2, 201, 3, 2, 202,
+ 1, 2, 202, 2, 2, 202, 3, 2,
+ 203, 1, 2, 203, 2, 2, 203, 3,
+ 2, 204, 1, 2, 204, 2, 2, 204,
+ 3, 2, 205, 1, 2, 205, 2, 2,
+ 205, 3, 2, 206, 1, 2, 206, 2,
+ 2, 206, 3, 2, 207, 1, 2, 207,
+ 2, 2, 207, 3, 2, 208, 1, 2,
+ 208, 2, 2, 208, 3, 2, 209, 1,
+ 2, 209, 2, 2, 209, 3, 2, 210,
+ 1, 2, 210, 2, 2, 210, 3, 2,
+ 211, 1, 2, 211, 2, 2, 211, 3,
+ 2, 212, 1, 2, 212, 2, 2, 212,
+ 3, 2, 213, 1, 2, 213, 2, 2,
+ 213, 3, 2, 214, 1, 2, 214, 2,
+ 2, 214, 3, 2, 215, 1, 2, 215,
+ 2, 2, 215, 3, 2, 216, 1, 2,
+ 216, 2, 2, 216, 3, 2, 217, 1,
+ 2, 217, 2, 2, 217, 3, 2, 218,
+ 1, 2, 218, 2, 2, 218, 3, 2,
+ 219, 1, 2, 219, 2, 2, 219, 3,
+ 2, 220, 1, 2, 220, 2, 2, 220,
+ 3, 2, 221, 1, 2, 221, 2, 2,
+ 221, 3, 2, 222, 1, 2, 222, 2,
+ 2, 222, 3, 2, 223, 1, 2, 223,
+ 2, 2, 223, 3, 2, 224, 1, 2,
+ 224, 2, 2, 224, 3, 2, 225, 1,
+ 2, 225, 2, 2, 225, 3, 2, 226,
+ 0, 2, 229, 1, 2, 229, 2, 2,
+ 229, 3, 2, 230, 1, 2, 230, 2,
+ 2, 230, 3, 2, 231, 1, 2, 231,
+ 2, 2, 231, 3, 2, 232, 1, 2,
+ 232, 2, 2, 232, 3, 2, 239, 1,
+ 2, 239, 2, 2, 239, 3, 2, 240,
+ 1, 2, 240, 2, 2, 240, 3, 2,
+ 243, 0, 2, 244, 260, 2, 246, 100,
+ 2, 251, 100, 2, 260, 4, 2, 261,
+ 1, 2, 261, 27, 2, 263, 2, 2,
+ 263, 3, 2, 264, 261, 2, 265, 4,
+ 2, 265, 260, 2, 266, 259, 2, 267,
+ 259, 2, 268, 259, 2, 269, 259, 2,
+ 270, 259, 2, 271, 259, 2, 272, 259,
+ 2, 273, 259, 2, 274, 259, 2, 275,
+ 259, 2, 276, 259, 2, 277, 259, 2,
+ 278, 259, 2, 279, 259, 2, 280, 259,
+ 2, 281, 259, 2, 282, 259, 2, 283,
+ 259, 2, 284, 259, 2, 285, 259, 2,
+ 286, 259, 2, 287, 259, 2, 288, 259,
+ 2, 289, 259, 2, 290, 259, 2, 291,
+ 259, 2, 292, 259, 2, 293, 259, 2,
+ 294, 259, 2, 295, 259, 2, 296, 259,
+ 2, 297, 259, 2, 298, 259, 2, 299,
+ 259, 2, 300, 259, 2, 301, 259, 2,
+ 302, 259, 2, 303, 259, 2, 304, 1,
+ 3, 0, 44, 1, 3, 0, 44, 2,
+ 3, 0, 44, 3, 3, 1, 77, 0,
+ 3, 1, 103, 0, 3, 1, 226, 0,
+ 3, 1, 243, 0, 3, 1, 261, 27,
+ 3, 1, 261, 304, 3, 1, 263, 304,
+ 3, 1, 304, 27, 3, 7, 1, 8,
+ 3, 11, 17, 0, 3, 16, 75, 2,
+ 3, 16, 75, 3, 3, 19, 9, 10,
+ 3, 23, 1, 0, 3, 23, 24, 1,
+ 3, 23, 24, 2, 3, 23, 24, 3,
+ 3, 26, 1, 85, 3, 26, 2, 85,
+ 3, 26, 2, 263, 3, 26, 3, 85,
+ 3, 26, 3, 263, 3, 26, 85, 263,
+ 3, 26, 264, 261, 3, 26, 266, 259,
+ 3, 28, 81, 4, 3, 28, 260, 4,
+ 3, 28, 265, 4, 3, 28, 265, 260,
+ 3, 30, 1, 0, 3, 30, 24, 1,
+ 3, 30, 24, 2, 3, 30, 24, 3,
+ 3, 30, 24, 228, 3, 32, 31, 261,
+ 3, 33, 145, 260, 3, 33, 147, 260,
+ 3, 33, 265, 4, 3, 33, 265, 260,
+ 3, 35, 37, 233, 3, 35, 37, 234,
+ 3, 35, 37, 235, 3, 35, 37, 236,
+ 3, 35, 37, 237, 3, 35, 37, 238,
+ 3, 37, 233, 1, 3, 37, 233, 2,
+ 3, 37, 233, 3, 3, 37, 234, 1,
+ 3, 37, 234, 2, 3, 37, 234, 3,
+ 3, 37, 235, 1, 3, 37, 235, 2,
+ 3, 37, 235, 3, 3, 37, 236, 1,
+ 3, 37, 236, 2, 3, 37, 236, 3,
+ 3, 37, 237, 1, 3, 37, 237, 2,
+ 3, 37, 237, 3, 3, 37, 238, 1,
+ 3, 37, 238, 2, 3, 37, 238, 3,
+ 3, 41, 24, 1, 3, 41, 24, 2,
+ 3, 41, 24, 3, 3, 43, 259, 1,
+ 3, 43, 259, 2, 3, 43, 259, 3,
+ 3, 43, 259, 261, 3, 45, 33, 65,
+ 3, 45, 33, 260, 3, 45, 33, 265,
+ 3, 50, 32, 31, 3, 51, 42, 0,
+ 3, 51, 42, 1, 3, 51, 42, 2,
+ 3, 51, 42, 3, 3, 51, 85, 1,
+ 3, 51, 85, 2, 3, 51, 85, 3,
+ 3, 61, 56, 0, 3, 62, 57, 58,
+ 3, 64, 0, 1, 3, 67, 19, 9,
+ 3, 68, 0, 1, 3, 74, 19, 9,
+ 3, 77, 0, 1, 3, 80, 25, 21,
+ 3, 80, 27, 1, 3, 80, 27, 2,
+ 3, 80, 27, 3, 3, 82, 25, 21,
+ 3, 82, 83, 261, 3, 85, 2, 263,
+ 3, 85, 3, 263, 3, 88, 99, 260,
+ 3, 88, 145, 260, 3, 89, 90, 0,
+ 3, 89, 90, 1, 3, 89, 90, 2,
+ 3, 89, 90, 3, 3, 91, 92, 0,
+ 3, 91, 92, 1, 3, 91, 92, 2,
+ 3, 91, 92, 3, 3, 97, 98, 0,
+ 3, 97, 98, 1, 3, 97, 98, 2,
+ 3, 97, 98, 3, 3, 102, 104, 245,
+ 3, 102, 254, 260, 3, 145, 146, 260,
+ 3, 186, 226, 0, 3, 187, 226, 0,
+ 3, 188, 226, 0, 3, 189, 226, 0,
+ 3, 190, 226, 0, 3, 191, 226, 0,
+ 3, 192, 226, 0, 3, 193, 226, 0,
+ 3, 194, 226, 0, 3, 195, 226, 0,
+ 3, 196, 226, 0, 3, 197, 226, 0,
+ 3, 198, 226, 0, 3, 199, 226, 0,
+ 3, 200, 226, 0, 3, 201, 226, 0,
+ 3, 202, 226, 0, 3, 203, 226, 0,
+ 3, 204, 226, 0, 3, 205, 226, 0,
+ 3, 206, 226, 0, 3, 207, 226, 0,
+ 3, 208, 226, 0, 3, 209, 226, 0,
+ 3, 210, 226, 0, 3, 211, 226, 0,
+ 3, 212, 226, 0, 3, 213, 226, 0,
+ 3, 214, 226, 0, 3, 215, 226, 0,
+ 3, 216, 226, 0, 3, 217, 226, 0,
+ 3, 218, 226, 0, 3, 219, 226, 0,
+ 3, 220, 226, 0, 3, 221, 226, 0,
+ 3, 222, 226, 0, 3, 223, 226, 0,
+ 3, 224, 226, 0, 3, 225, 226, 0,
+ 3, 242, 32, 31, 3, 247, 248, 0,
+ 3, 247, 249, 0, 3, 250, 102, 260,
+ 3, 252, 253, 0, 3, 254, 102, 260,
+ 3, 260, 4, 81, 3, 261, 25, 21,
+ 3, 261, 304, 1, 3, 263, 304, 1,
+ 3, 265, 260, 4, 3, 266, 259, 1,
+ 3, 266, 259, 2, 3, 266, 259, 3,
+ 3, 266, 259, 261, 3, 266, 259, 263,
+ 3, 267, 259, 1, 3, 267, 259, 2,
+ 3, 267, 259, 3, 3, 267, 259, 261,
+ 3, 268, 259, 1, 3, 268, 259, 2,
+ 3, 268, 259, 3, 3, 268, 259, 261,
+ 3, 269, 259, 1, 3, 269, 259, 2,
+ 3, 269, 259, 3, 3, 269, 259, 261,
+ 3, 270, 259, 1, 3, 270, 259, 2,
+ 3, 270, 259, 3, 3, 270, 259, 261,
+ 3, 271, 259, 1, 3, 271, 259, 2,
+ 3, 271, 259, 3, 3, 271, 259, 261,
+ 3, 272, 259, 1, 3, 272, 259, 2,
+ 3, 272, 259, 3, 3, 272, 259, 261,
+ 3, 273, 259, 1, 3, 273, 259, 2,
+ 3, 273, 259, 3, 3, 273, 259, 261,
+ 3, 274, 259, 1, 3, 274, 259, 2,
+ 3, 274, 259, 3, 3, 274, 259, 261,
+ 3, 275, 259, 1, 3, 275, 259, 2,
+ 3, 275, 259, 3, 3, 275, 259, 261,
+ 3, 276, 259, 1, 3, 276, 259, 2,
+ 3, 276, 259, 3, 3, 276, 259, 261,
+ 3, 277, 259, 1, 3, 277, 259, 2,
+ 3, 277, 259, 3, 3, 277, 259, 261,
+ 3, 278, 259, 1, 3, 278, 259, 2,
+ 3, 278, 259, 3, 3, 278, 259, 261,
+ 3, 279, 259, 1, 3, 279, 259, 2,
+ 3, 279, 259, 3, 3, 279, 259, 261,
+ 3, 280, 259, 1, 3, 280, 259, 2,
+ 3, 280, 259, 3, 3, 280, 259, 261,
+ 3, 281, 259, 1, 3, 281, 259, 2,
+ 3, 281, 259, 3, 3, 281, 259, 261,
+ 3, 282, 259, 1, 3, 282, 259, 2,
+ 3, 282, 259, 3, 3, 282, 259, 261,
+ 3, 283, 259, 1, 3, 283, 259, 2,
+ 3, 283, 259, 3, 3, 283, 259, 261,
+ 3, 284, 259, 1, 3, 284, 259, 2,
+ 3, 284, 259, 3, 3, 284, 259, 261,
+ 3, 285, 259, 1, 3, 285, 259, 2,
+ 3, 285, 259, 3, 3, 285, 259, 261,
+ 3, 286, 259, 1, 3, 286, 259, 2,
+ 3, 286, 259, 3, 3, 286, 259, 261,
+ 3, 287, 259, 1, 3, 287, 259, 2,
+ 3, 287, 259, 3, 3, 287, 259, 261,
+ 3, 288, 259, 1, 3, 288, 259, 2,
+ 3, 288, 259, 3, 3, 288, 259, 261,
+ 3, 289, 259, 1, 3, 289, 259, 2,
+ 3, 289, 259, 3, 3, 289, 259, 261,
+ 3, 290, 259, 1, 3, 290, 259, 2,
+ 3, 290, 259, 3, 3, 290, 259, 261,
+ 3, 291, 259, 1, 3, 291, 259, 2,
+ 3, 291, 259, 3, 3, 291, 259, 261,
+ 3, 292, 259, 1, 3, 292, 259, 2,
+ 3, 292, 259, 3, 3, 292, 259, 261,
+ 3, 293, 259, 1, 3, 293, 259, 2,
+ 3, 293, 259, 3, 3, 293, 259, 261,
+ 3, 294, 259, 1, 3, 294, 259, 2,
+ 3, 294, 259, 3, 3, 294, 259, 261,
+ 3, 295, 259, 1, 3, 295, 259, 2,
+ 3, 295, 259, 3, 3, 295, 259, 261,
+ 3, 296, 259, 1, 3, 296, 259, 2,
+ 3, 296, 259, 3, 3, 296, 259, 261,
+ 3, 297, 259, 1, 3, 297, 259, 2,
+ 3, 297, 259, 3, 3, 297, 259, 261,
+ 3, 298, 259, 1, 3, 298, 259, 2,
+ 3, 298, 259, 3, 3, 298, 259, 261,
+ 3, 299, 259, 1, 3, 299, 259, 2,
+ 3, 299, 259, 3, 3, 299, 259, 261,
+ 3, 300, 259, 1, 3, 300, 259, 2,
+ 3, 300, 259, 3, 3, 300, 259, 261,
+ 3, 301, 259, 1, 3, 301, 259, 2,
+ 3, 301, 259, 3, 3, 301, 259, 261,
+ 3, 302, 259, 1, 3, 302, 259, 2,
+ 3, 302, 259, 3, 3, 302, 259, 261,
+ 3, 303, 259, 1, 3, 303, 259, 2,
+ 3, 303, 259, 3, 3, 303, 259, 261,
+ 3, 304, 1, 27, 4, 5, 7, 1,
+ 8, 4, 14, 11, 17, 0, 4, 16,
+ 68, 0, 1, 4, 26, 1, 263, 304,
+ 4, 26, 1, 264, 261, 4, 26, 1,
+ 266, 259, 4, 26, 2, 85, 263, 4,
+ 26, 2, 264, 261, 4, 26, 2, 266,
+ 259, 4, 26, 3, 85, 263, 4, 26,
+ 3, 264, 261, 4, 26, 3, 266, 259,
+ 4, 26, 266, 259, 261, 4, 26, 266,
+ 259, 263, 4, 28, 33, 265, 4, 4,
+ 28, 45, 33, 265, 4, 28, 265, 260,
+ 4, 4, 32, 31, 25, 21, 4, 33,
+ 265, 260, 4, 4, 35, 32, 31, 36,
+ 4, 35, 37, 233, 1, 4, 35, 37,
+ 233, 2, 4, 35, 37, 233, 3, 4,
+ 35, 37, 234, 1, 4, 35, 37, 234,
+ 2, 4, 35, 37, 234, 3, 4, 35,
+ 37, 235, 1, 4, 35, 37, 235, 2,
+ 4, 35, 37, 235, 3, 4, 35, 37,
+ 236, 1, 4, 35, 37, 236, 2, 4,
+ 35, 37, 236, 3, 4, 35, 37, 237,
+ 1, 4, 35, 37, 237, 2, 4, 35,
+ 37, 237, 3, 4, 35, 37, 238, 1,
+ 4, 35, 37, 238, 2, 4, 35, 37,
+ 238, 3, 4, 37, 235, 243, 0, 4,
+ 37, 236, 243, 0, 4, 37, 237, 243,
+ 0, 4, 37, 238, 243, 0, 4, 38,
+ 34, 32, 31, 4, 39, 34, 32, 31,
+ 4, 43, 259, 1, 261, 4, 45, 33,
+ 4, 65, 4, 51, 50, 32, 31, 4,
+ 51, 64, 0, 1, 4, 67, 19, 9,
+ 10, 4, 72, 77, 0, 1, 4, 74,
+ 19, 9, 10, 4, 82, 83, 25, 21,
+ 4, 85, 1, 263, 304, 4, 88, 145,
+ 146, 260, 4, 89, 90, 1, 0, 4,
+ 91, 92, 1, 0, 4, 97, 98, 1,
+ 0, 4, 186, 1, 226, 0, 4, 187,
+ 1, 226, 0, 4, 188, 1, 226, 0,
+ 4, 189, 1, 226, 0, 4, 190, 1,
+ 226, 0, 4, 191, 1, 226, 0, 4,
+ 192, 1, 226, 0, 4, 193, 1, 226,
+ 0, 4, 194, 1, 226, 0, 4, 195,
+ 1, 226, 0, 4, 196, 1, 226, 0,
+ 4, 197, 1, 226, 0, 4, 198, 1,
+ 226, 0, 4, 199, 1, 226, 0, 4,
+ 200, 1, 226, 0, 4, 201, 1, 226,
+ 0, 4, 202, 1, 226, 0, 4, 203,
+ 1, 226, 0, 4, 204, 1, 226, 0,
+ 4, 205, 1, 226, 0, 4, 206, 1,
+ 226, 0, 4, 207, 1, 226, 0, 4,
+ 208, 1, 226, 0, 4, 209, 1, 226,
+ 0, 4, 210, 1, 226, 0, 4, 211,
+ 1, 226, 0, 4, 212, 1, 226, 0,
+ 4, 213, 1, 226, 0, 4, 214, 1,
+ 226, 0, 4, 215, 1, 226, 0, 4,
+ 216, 1, 226, 0, 4, 217, 1, 226,
+ 0, 4, 218, 1, 226, 0, 4, 219,
+ 1, 226, 0, 4, 220, 1, 226, 0,
+ 4, 221, 1, 226, 0, 4, 222, 1,
+ 226, 0, 4, 223, 1, 226, 0, 4,
+ 224, 1, 226, 0, 4, 225, 1, 226,
+ 0, 4, 266, 259, 1, 261, 4, 266,
+ 259, 2, 263, 4, 266, 259, 3, 263,
+ 4, 266, 259, 263, 261, 4, 267, 259,
+ 1, 261, 4, 268, 259, 1, 261, 4,
+ 269, 259, 1, 261, 4, 270, 259, 1,
+ 261, 4, 271, 259, 1, 261, 4, 272,
+ 259, 1, 261, 4, 273, 259, 1, 261,
+ 4, 274, 259, 1, 261, 4, 275, 259,
+ 1, 261, 4, 276, 259, 1, 261, 4,
+ 277, 259, 1, 261, 4, 278, 259, 1,
+ 261, 4, 279, 259, 1, 261, 4, 280,
+ 259, 1, 261, 4, 281, 259, 1, 261,
+ 4, 282, 259, 1, 261, 4, 283, 259,
+ 1, 261, 4, 284, 259, 1, 261, 4,
+ 285, 259, 1, 261, 4, 286, 259, 1,
+ 261, 4, 287, 259, 1, 261, 4, 288,
+ 259, 1, 261, 4, 289, 259, 1, 261,
+ 4, 290, 259, 1, 261, 4, 291, 259,
+ 1, 261, 4, 292, 259, 1, 261, 4,
+ 293, 259, 1, 261, 4, 294, 259, 1,
+ 261, 4, 295, 259, 1, 261, 4, 296,
+ 259, 1, 261, 4, 297, 259, 1, 261,
+ 4, 298, 259, 1, 261, 4, 299, 259,
+ 1, 261, 4, 300, 259, 1, 261, 4,
+ 301, 259, 1, 261, 4, 302, 259, 1,
+ 261, 4, 303, 259, 1, 261, 5, 16,
+ 75, 77, 0, 1, 5, 26, 1, 85,
+ 263, 304, 5, 26, 1, 266, 259, 261,
+ 5, 26, 2, 266, 259, 263, 5, 26,
+ 3, 266, 259, 263, 5, 26, 266, 259,
+ 263, 261, 5, 28, 33, 265, 260, 4,
+ 5, 32, 31, 261, 25, 21, 5, 35,
+ 37, 235, 243, 0, 5, 35, 37, 236,
+ 243, 0, 5, 35, 37, 237, 243, 0,
+ 5, 35, 37, 238, 243, 0, 5, 37,
+ 235, 1, 243, 0, 5, 37, 236, 1,
+ 243, 0, 5, 37, 237, 1, 243, 0,
+ 5, 37, 238, 1, 243, 0, 5, 45,
+ 33, 265, 260, 4, 5, 82, 83, 261,
+ 25, 21, 5, 241, 38, 34, 32, 31,
+ 5, 266, 259, 1, 263, 304, 6, 26,
+ 1, 266, 259, 263, 304, 6, 28, 45,
+ 33, 265, 260, 4, 6, 35, 37, 235,
+ 1, 243, 0, 6, 35, 37, 236, 1,
+ 243, 0, 6, 35, 37, 237, 1, 243,
+ 0, 6, 35, 37, 238, 1, 243, 0,
+ 6, 266, 259, 1, 263, 261, 304, 6,
+ 266, 259, 263, 261, 304, 1, 7, 26,
+ 1, 266, 259, 263, 261, 304
+};
+
+static const short _zone_scanner_cond_offsets[] = {
+ 0, 0, 2, 4, 6, 8, 10, 12,
+ 14, 14, 14, 16, 19, 21, 24, 26,
+ 28, 30, 30, 30, 30, 32, 37, 37,
+ 37, 37, 39, 39, 39, 39, 39, 41,
+ 41, 41, 41, 43, 43, 43, 43, 45,
+ 47, 47, 47, 47, 47, 49, 49, 51,
+ 51, 51, 51, 51, 53, 53, 55, 57,
+ 57, 57, 57, 57, 57, 57, 57, 59,
+ 59, 59, 61, 63, 63, 63, 65, 65,
+ 67, 67, 69, 71, 71, 71, 71, 71,
+ 73, 75, 75, 75, 75, 75, 77, 77,
+ 79, 81, 81, 83, 85, 85, 85, 85,
+ 85, 87, 87, 87, 89, 89, 91, 91,
+ 91, 91, 93, 95, 95, 95, 97, 97,
+ 99, 99, 101, 101, 101, 101, 103, 103,
+ 103, 103, 105, 105, 107, 107, 107, 107,
+ 109, 112, 114, 114, 116, 118, 120, 122,
+ 122, 124, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 129, 131, 134, 136,
+ 138, 141, 143, 143, 145, 148, 150, 152,
+ 154, 156, 158, 161, 163, 165, 167, 169,
+ 171, 173, 175, 177, 179, 181, 183, 185,
+ 187, 189, 191, 193, 196, 198, 198, 198,
+ 198, 198, 198, 198, 198, 198, 198, 200,
+ 202, 204, 207, 209, 211, 213, 215, 217,
+ 219, 221, 223, 225, 227, 229, 231, 233,
+ 235, 237, 239, 241, 246, 251, 256, 256,
+ 256, 258, 258, 258, 258, 260, 260, 262,
+ 265, 267, 269, 274, 279, 282, 287, 289,
+ 291, 293, 295, 297, 299, 301, 303, 305,
+ 307, 309, 311, 313, 316, 319, 321, 324,
+ 324, 324, 324, 324, 324, 324, 324, 324,
+ 324, 324, 324, 324, 324, 324, 324, 324,
+ 324, 324, 325, 325, 325, 325, 325, 326,
+ 328, 330, 332, 334, 334, 336, 336, 338,
+ 341, 343, 345, 345, 347, 349, 349, 349,
+ 349, 349, 349, 349, 351, 354, 356, 358,
+ 360, 362, 362, 364, 366, 366, 366, 366,
+ 366, 366, 366, 368, 371, 373, 376, 379,
+ 379, 379, 379, 379, 381, 384, 384, 386,
+ 388, 390, 390, 390, 392, 395, 395, 395,
+ 395, 397, 397, 397, 397, 399, 399, 399,
+ 399, 399, 401, 401, 401, 401, 403, 403,
+ 403, 403, 405, 407, 407, 407, 407, 407,
+ 409, 409, 411, 411, 411, 411, 411, 413,
+ 413, 413, 413, 413, 413, 413, 413, 415,
+ 415, 415, 417, 419, 419, 419, 421, 421,
+ 423, 423, 425, 427, 427, 427, 427, 427,
+ 429, 431, 431, 431, 431, 431, 433, 433,
+ 435, 437, 437, 439, 441, 441, 441, 441,
+ 441, 443, 443, 443, 445, 445, 447, 447,
+ 447, 447, 449, 451, 451, 451, 453, 453,
+ 455, 455, 457, 457, 457, 457, 459, 459,
+ 459, 459, 461, 461, 463, 463, 463, 463,
+ 465, 465, 465, 465, 467, 467, 469, 471,
+ 473, 475, 477, 477, 479, 482, 485, 488,
+ 490, 492, 494, 496, 496, 498, 501, 504,
+ 506, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 509,
+ 509, 509, 509, 509, 509, 509, 509, 511,
+ 513, 515, 517, 519, 521, 523, 525, 527,
+ 529, 531, 533, 533, 533, 533, 533, 536,
+ 538, 538, 540, 543, 545, 545, 547, 550,
+ 552, 552, 554, 557, 560, 563, 563, 565,
+ 567, 567, 570, 570, 572, 574, 574, 577,
+ 577, 579, 581, 581, 584, 584, 586, 588,
+ 591, 591, 591, 591, 593, 595, 597, 599,
+ 601, 603, 605, 607, 609, 611, 613, 615,
+ 617, 619, 621, 623, 623, 625, 627, 629,
+ 631, 633, 635, 637, 639, 642, 644, 646,
+ 649, 651, 653, 655, 658, 660, 662, 664,
+ 667, 669, 671, 673, 676, 678, 681, 683,
+ 685, 688, 691, 694, 696, 699, 701, 703,
+ 706, 709, 709, 711, 713, 715, 717, 719,
+ 721, 721, 724, 727, 730, 730, 732, 734,
+ 736, 738, 740, 742, 744, 746, 748, 750,
+ 750, 753, 756, 759, 762, 765, 765, 767,
+ 769, 771, 773, 775, 777, 779, 782, 785,
+ 788, 790, 790, 790, 790, 790, 790, 792,
+ 795, 795, 795, 795, 795, 797, 799, 801,
+ 803, 805, 807, 807, 809, 812, 815, 818,
+ 821, 821, 823, 825, 827, 829, 829, 831,
+ 834, 837, 840, 840, 842, 844, 846, 848,
+ 850, 852, 858, 869, 871, 874, 880, 883,
+ 894, 897, 900, 903, 905, 907, 909, 911,
+ 917, 920, 923, 925, 927, 929, 931, 937,
+ 940, 943, 945, 947, 949, 951, 957, 960,
+ 963, 966, 966, 968, 970, 972, 974, 976,
+ 978, 980, 982, 984, 986, 988, 990, 992,
+ 994, 996, 998, 1000, 1003, 1006, 1009, 1012,
+ 1015, 1018, 1021, 1024, 1024, 1024, 1026, 1026,
+ 1026, 1026, 1028, 1028, 1030, 1030, 1030, 1030,
+ 1032, 1032, 1032, 1032, 1034, 1034, 1034, 1034,
+ 1034, 1036, 1036, 1036, 1036, 1038, 1038, 1038,
+ 1038, 1040, 1042, 1042, 1042, 1042, 1042, 1044,
+ 1044, 1046, 1046, 1046, 1046, 1046, 1048, 1048,
+ 1048, 1048, 1048, 1048, 1048, 1048, 1050, 1050,
+ 1050, 1052, 1054, 1054, 1054, 1056, 1056, 1058,
+ 1058, 1060, 1062, 1062, 1062, 1062, 1062, 1064,
+ 1066, 1066, 1066, 1066, 1066, 1068, 1068, 1070,
+ 1072, 1072, 1074, 1076, 1076, 1076, 1076, 1076,
+ 1078, 1078, 1078, 1080, 1080, 1082, 1082, 1082,
+ 1082, 1084, 1086, 1086, 1086, 1088, 1088, 1090,
+ 1090, 1092, 1092, 1092, 1092, 1094, 1094, 1094,
+ 1094, 1096, 1096, 1098, 1098, 1098, 1098, 1100,
+ 1100, 1100, 1100, 1100, 1102, 1104, 1106, 1108,
+ 1110, 1112, 1114, 1117, 1120, 1123, 1123, 1125,
+ 1125, 1127, 1129, 1131, 1133, 1135, 1137, 1139,
+ 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1141,
+ 1141, 1141, 1141, 1141, 1141, 1141, 1141, 1144,
+ 1144, 1146, 1149, 1152, 1155, 1155, 1157, 1159,
+ 1161, 1163, 1165, 1167, 1167, 1167, 1167, 1170,
+ 1173, 1176, 1176, 1178, 1180, 1182, 1184, 1186,
+ 1188, 1188, 1190, 1193, 1196, 1199, 1202, 1202,
+ 1204, 1206, 1206, 1209, 1209, 1211, 1213, 1213,
+ 1213, 1213, 1213, 1213, 1213, 1213, 1213, 1213,
+ 1216, 1216, 1216, 1216, 1216, 1216, 1216, 1216,
+ 1216, 1216, 1216, 1216, 1216, 1218, 1220, 1222,
+ 1224, 1226, 1228, 1230, 1232, 1234, 1236, 1236,
+ 1236, 1236, 1236, 1236, 1236, 1236, 1238, 1238,
+ 1240, 1243, 1243, 1245, 1248, 1248, 1250, 1253,
+ 1255, 1255, 1257, 1260, 1263, 1263, 1263, 1263,
+ 1263, 1263, 1263, 1263, 1263, 1263, 1265, 1268,
+ 1268, 1268, 1270, 1273, 1275, 1278, 1280, 1283,
+ 1285, 1288, 1288, 1288, 1288, 1288, 1290, 1293,
+ 1293, 1295, 1298, 1298, 1300, 1303, 1303, 1309,
+ 1312, 1323, 1326, 1337, 1340, 1340, 1340, 1340,
+ 1340, 1340, 1340, 1340, 1342, 1345, 1345, 1345,
+ 1345
+};
+
+static const char _zone_scanner_cond_lengths[] = {
+ 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 2, 3, 2, 3, 2, 2,
+ 2, 0, 0, 0, 2, 5, 0, 0,
+ 0, 2, 0, 0, 0, 0, 2, 0,
+ 0, 0, 2, 0, 0, 0, 2, 2,
+ 0, 0, 0, 0, 2, 0, 2, 0,
+ 0, 0, 0, 2, 0, 2, 2, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 2, 2, 0, 0, 2, 0, 2,
+ 0, 2, 2, 0, 0, 0, 0, 2,
+ 2, 0, 0, 0, 0, 2, 0, 2,
+ 2, 0, 2, 2, 0, 0, 0, 0,
+ 2, 0, 0, 2, 0, 2, 0, 0,
+ 0, 2, 2, 0, 0, 2, 0, 2,
+ 0, 2, 0, 0, 0, 2, 0, 0,
+ 0, 2, 0, 2, 0, 0, 0, 2,
+ 3, 2, 0, 2, 2, 2, 2, 0,
+ 2, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 2, 3, 2, 2,
+ 3, 2, 0, 2, 3, 2, 2, 2,
+ 2, 2, 3, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 3, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 3, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 5, 5, 5, 0, 0,
+ 2, 0, 0, 0, 2, 0, 2, 3,
+ 2, 2, 5, 5, 3, 5, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 3, 3, 2, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 1, 2,
+ 2, 2, 2, 0, 2, 0, 2, 3,
+ 2, 2, 0, 2, 2, 0, 0, 0,
+ 0, 0, 0, 2, 3, 2, 2, 2,
+ 2, 0, 2, 2, 0, 0, 0, 0,
+ 0, 0, 2, 3, 2, 3, 3, 0,
+ 0, 0, 0, 2, 3, 0, 2, 2,
+ 2, 0, 0, 2, 3, 0, 0, 0,
+ 2, 0, 0, 0, 2, 0, 0, 0,
+ 0, 2, 0, 0, 0, 2, 0, 0,
+ 0, 2, 2, 0, 0, 0, 0, 2,
+ 0, 2, 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 2, 2, 0, 0, 2, 0, 2,
+ 0, 2, 2, 0, 0, 0, 0, 2,
+ 2, 0, 0, 0, 0, 2, 0, 2,
+ 2, 0, 2, 2, 0, 0, 0, 0,
+ 2, 0, 0, 2, 0, 2, 0, 0,
+ 0, 2, 2, 0, 0, 2, 0, 2,
+ 0, 2, 0, 0, 0, 2, 0, 0,
+ 0, 2, 0, 2, 0, 0, 0, 2,
+ 0, 0, 0, 2, 0, 2, 2, 2,
+ 2, 2, 0, 2, 3, 3, 3, 2,
+ 2, 2, 2, 0, 2, 3, 3, 2,
+ 3, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 0, 0, 0, 0, 3, 2,
+ 0, 2, 3, 2, 0, 2, 3, 2,
+ 0, 2, 3, 3, 3, 0, 2, 2,
+ 0, 3, 0, 2, 2, 0, 3, 0,
+ 2, 2, 0, 3, 0, 2, 2, 3,
+ 0, 0, 0, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 2, 2, 2, 2,
+ 2, 2, 2, 2, 3, 2, 2, 3,
+ 2, 2, 2, 3, 2, 2, 2, 3,
+ 2, 2, 2, 3, 2, 3, 2, 2,
+ 3, 3, 3, 2, 3, 2, 2, 3,
+ 3, 0, 2, 2, 2, 2, 2, 2,
+ 0, 3, 3, 3, 0, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 0,
+ 3, 3, 3, 3, 3, 0, 2, 2,
+ 2, 2, 2, 2, 2, 3, 3, 3,
+ 2, 0, 0, 0, 0, 0, 2, 3,
+ 0, 0, 0, 0, 2, 2, 2, 2,
+ 2, 2, 0, 2, 3, 3, 3, 3,
+ 0, 2, 2, 2, 2, 0, 2, 3,
+ 3, 3, 0, 2, 2, 2, 2, 2,
+ 2, 6, 11, 2, 3, 6, 3, 11,
+ 3, 3, 3, 2, 2, 2, 2, 6,
+ 3, 3, 2, 2, 2, 2, 6, 3,
+ 3, 2, 2, 2, 2, 6, 3, 3,
+ 3, 0, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 3, 3, 3, 3, 3,
+ 3, 3, 3, 0, 0, 2, 0, 0,
+ 0, 2, 0, 2, 0, 0, 0, 2,
+ 0, 0, 0, 2, 0, 0, 0, 0,
+ 2, 0, 0, 0, 2, 0, 0, 0,
+ 2, 2, 0, 0, 0, 0, 2, 0,
+ 2, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 2, 2, 0, 0, 2, 0, 2, 0,
+ 2, 2, 0, 0, 0, 0, 2, 2,
+ 0, 0, 0, 0, 2, 0, 2, 2,
+ 0, 2, 2, 0, 0, 0, 0, 2,
+ 0, 0, 2, 0, 2, 0, 0, 0,
+ 2, 2, 0, 0, 2, 0, 2, 0,
+ 2, 0, 0, 0, 2, 0, 0, 0,
+ 2, 0, 2, 0, 0, 0, 2, 0,
+ 0, 0, 0, 2, 2, 2, 2, 2,
+ 2, 2, 3, 3, 3, 0, 2, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0,
+ 2, 3, 3, 3, 0, 2, 2, 2,
+ 2, 2, 2, 0, 0, 0, 3, 3,
+ 3, 0, 2, 2, 2, 2, 2, 2,
+ 0, 2, 3, 3, 3, 3, 0, 2,
+ 2, 0, 3, 0, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 2,
+ 3, 0, 2, 3, 0, 2, 3, 2,
+ 0, 2, 3, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 3, 0,
+ 0, 2, 3, 2, 3, 2, 3, 2,
+ 3, 0, 0, 0, 0, 2, 3, 0,
+ 2, 3, 0, 2, 3, 0, 6, 3,
+ 11, 3, 11, 3, 0, 0, 0, 0,
+ 0, 0, 0, 2, 3, 0, 0, 0,
+ 0
+};
+
+static const short _zone_scanner_cond_keys[] = {
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 58, 59, 59,
+ 60, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 58,
+ 59, 59, 60, 127, -128, 9, 10, 10,
+ 11, 58, 59, 59, 60, 127, -128, 9,
+ 10, 10, 11, 58, 59, 59, 60, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 58,
+ 59, 59, 60, 127, -128, 9, 10, 10,
+ 11, 58, 59, 59, 60, 127, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 58, 59, 59, 60, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 10, 10, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 9, 9, 10, 10, 32, 32, 40, 40,
+ 41, 41, 59, 59, 9, 9, 10, 10,
+ 32, 32, 40, 40, 41, 41, 43, 43,
+ 47, 47, 48, 57, 59, 59, 65, 90,
+ 97, 122, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 9, 9, 10, 10,
+ 32, 32, 40, 40, 41, 41, 59, 59,
+ -128, 9, 10, 10, 11, 127, 9, 9,
+ 10, 10, 32, 32, 40, 40, 41, 41,
+ 43, 43, 47, 47, 48, 57, 59, 59,
+ 65, 90, 97, 122, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 9, 9,
+ 10, 10, 32, 32, 40, 40, 41, 41,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 9, 9,
+ 10, 10, 32, 32, 40, 40, 41, 41,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 9, 9,
+ 10, 10, 32, 32, 40, 40, 41, 41,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, 10, 10,
+ 59, 59, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ 10, 10, 59, 59, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 10, 10,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 10, 10, 59, 59, -128, 9,
+ 10, 10, 11, 127, 10, 10, 59, 59,
+ -128, 9, 10, 10, 11, 127, 9, 9,
+ 10, 10, 32, 32, 40, 40, 41, 41,
+ 59, 59, -128, 9, 10, 10, 11, 127,
+ 9, 9, 10, 10, 32, 32, 40, 40,
+ 41, 41, 43, 43, 47, 47, 48, 57,
+ 59, 59, 65, 90, 97, 122, -128, 9,
+ 10, 10, 11, 127, 9, 9, 10, 10,
+ 32, 32, 40, 40, 41, 41, 43, 43,
+ 47, 47, 48, 57, 59, 59, 65, 90,
+ 97, 122, -128, 9, 10, 10, 11, 127,
+ 10, 10, 59, 59, -128, 9, 10, 10,
+ 11, 127, 0
+};
+
+static const char _zone_scanner_cond_spaces[] = {
+ 0, 0, 0, 0, 0, 0, 5, 5,
+ 5, 5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 5, 0, 0, 0,
+ 5, 5, 0, 0, 0, 0, 5, 5,
+ 0, 0, 0, 0, 0, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 0, 0, 0,
+ 0, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 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, 0, 0, 0,
+ 0, 0, 0, 0, 5, 5, 5, 5,
+ 5, 5, 5, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 5, 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, 0,
+ 0, 0, 0, 0, 0, 0, 0, 5,
+ 5, 5, 5, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 5, 5, 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, 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, 2, 2, 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, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 5, 0, 0, 0,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 0, 0, 0, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 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, 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, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 5, 5, 5, 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, 0, 0, 0, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 0,
+ 0, 0, 5, 5, 5, 5, 0, 0,
+ 0, 5, 5, 5, 5, 5, 5, 0,
+ 0, 0, 5, 5, 5, 5, 5, 5,
+ 0, 0, 0, 5, 5, 5, 5, 5,
+ 5, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 5, 5, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 5,
+ 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 8, 11, 8, 8,
+ 8, 11, 3, 6, 3, 3, 3, 3,
+ 3, 3, 6, 3, 3, 1, 1, 6,
+ 6, 6, 4, 9, 4, 4, 4, 9,
+ 7, 7, 7, 8, 11, 8, 8, 8,
+ 3, 3, 3, 11, 3, 3, 10, 10,
+ 10, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 8,
+ 11, 8, 8, 8, 11, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 8, 11, 8, 8, 8,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 8,
+ 11, 8, 8, 8, 11, 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 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,
+ 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,
+ 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,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 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, 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, 5, 5, 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, 5, 5, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 5, 5,
+ 5, 5, 5, 5, 0, 0, 5, 5,
+ 0, 0, 0, 5, 5, 0, 0, 0,
+ 5, 5, 0, 0, 0, 0, 0, 5,
+ 5, 0, 0, 0, 0, 0, 0, 5,
+ 5, 0, 0, 0, 5, 5, 0, 0,
+ 0, 5, 5, 0, 0, 0, 5, 5,
+ 0, 0, 0, 5, 5, 0, 0, 0,
+ 5, 5, 0, 0, 0, 5, 5, 0,
+ 0, 0, 5, 5, 0, 0, 0, 4,
+ 9, 4, 4, 4, 9, 7, 7, 7,
+ 3, 6, 3, 3, 3, 3, 3, 3,
+ 6, 3, 3, 6, 6, 6, 8, 11,
+ 8, 8, 8, 3, 3, 3, 11, 3,
+ 3, 10, 10, 10, 5, 5, 0, 0,
+ 0, 0
+};
+
+static const short _zone_scanner_key_offsets[] = {
+ 0, 0, 38, 56, 90, 106, 123, 131,
+ 139, 140, 141, 149, 152, 171, 177, 227,
+ 247, 283, 287, 289, 291, 301, 315, 317,
+ 319, 321, 331, 337, 339, 341, 343, 353,
+ 357, 359, 361, 371, 373, 375, 377, 387,
+ 397, 399, 401, 403, 404, 414, 415, 425,
+ 427, 429, 431, 433, 443, 447, 453, 487,
+ 489, 491, 493, 495, 497, 499, 501, 511,
+ 515, 517, 527, 537, 543, 544, 554, 555,
+ 565, 567, 577, 587, 591, 593, 595, 597,
+ 607, 617, 623, 625, 627, 629, 639, 641,
+ 651, 663, 665, 676, 688, 690, 692, 694,
+ 696, 706, 708, 710, 720, 726, 736, 738,
+ 740, 742, 752, 762, 770, 772, 782, 784,
+ 794, 796, 806, 808, 810, 812, 822, 828,
+ 830, 832, 842, 844, 854, 856, 858, 860,
+ 872, 875, 913, 917, 923, 959, 977, 985,
+ 997, 1005, 1008, 1009, 1015, 1017, 1019, 1021,
+ 1023, 1025, 1027, 1033, 1039, 1075, 1078, 1096,
+ 1132, 1135, 1143, 1155, 1163, 1166, 1182, 1230,
+ 1248, 1267, 1305, 1311, 1325, 1339, 1389, 1401,
+ 1415, 1425, 1435, 1447, 1459, 1473, 1485, 1499,
+ 1509, 1523, 1539, 1553, 1559, 1573, 1575, 1577,
+ 1579, 1581, 1583, 1589, 1591, 1593, 1599, 1607,
+ 1627, 1665, 1671, 1689, 1739, 1751, 1765, 1775,
+ 1785, 1797, 1809, 1823, 1835, 1849, 1859, 1873,
+ 1889, 1903, 1918, 1956, 1970, 1984, 1998, 2000,
+ 2002, 2012, 2014, 2016, 2018, 2028, 2030, 2040,
+ 2046, 2060, 2074, 2090, 2104, 2107, 2121, 2131,
+ 2143, 2151, 2159, 2169, 2179, 2191, 2201, 2213,
+ 2221, 2233, 2247, 2259, 2265, 2271, 2281, 2287,
+ 2288, 2289, 2300, 2307, 2323, 2338, 2340, 2342,
+ 2344, 2359, 2365, 2371, 2377, 2389, 2391, 2393,
+ 2395, 2407, 2413, 2419, 2421, 2423, 2425, 2431,
+ 2437, 2445, 2465, 2473, 2474, 2484, 2496, 2506,
+ 2509, 2515, 2531, 2532, 2550, 2558, 2559, 2568,
+ 2570, 2572, 2574, 2583, 2591, 2594, 2600, 2612,
+ 2620, 2638, 2639, 2657, 2665, 2666, 2675, 2677,
+ 2679, 2681, 2690, 2698, 2704, 2720, 2723, 2726,
+ 2733, 2740, 2748, 2756, 2773, 2776, 2777, 2787,
+ 2825, 2841, 2843, 2845, 2855, 2858, 2862, 2864,
+ 2866, 2876, 2878, 2880, 2882, 2892, 2898, 2900,
+ 2902, 2904, 2914, 2918, 2920, 2922, 2932, 2934,
+ 2936, 2938, 2948, 2958, 2960, 2962, 2964, 2965,
+ 2975, 2976, 2986, 2988, 2990, 2992, 2994, 3004,
+ 3006, 3008, 3010, 3012, 3014, 3016, 3018, 3028,
+ 3032, 3034, 3044, 3054, 3060, 3061, 3071, 3072,
+ 3082, 3084, 3094, 3104, 3108, 3110, 3112, 3114,
+ 3124, 3134, 3140, 3142, 3144, 3146, 3156, 3158,
+ 3168, 3180, 3182, 3193, 3205, 3207, 3209, 3211,
+ 3213, 3223, 3225, 3227, 3237, 3243, 3253, 3255,
+ 3257, 3259, 3269, 3279, 3287, 3289, 3299, 3301,
+ 3311, 3313, 3323, 3325, 3327, 3329, 3339, 3345,
+ 3347, 3349, 3359, 3361, 3371, 3373, 3375, 3377,
+ 3389, 3391, 3393, 3395, 3405, 3407, 3417, 3423,
+ 3431, 3439, 3451, 3457, 3473, 3476, 3479, 3482,
+ 3488, 3497, 3507, 3519, 3525, 3541, 3544, 3547,
+ 3555, 3558, 3570, 3578, 3582, 3588, 3590, 3597,
+ 3599, 3601, 3603, 3605, 3606, 3607, 3609, 3611,
+ 3613, 3614, 3620, 3622, 3626, 3627, 3629, 3631,
+ 3633, 3635, 3641, 3643, 3645, 3647, 3649, 3650,
+ 3651, 3653, 3655, 3657, 3658, 3659, 3660, 3666,
+ 3667, 3668, 3670, 3672, 3674, 3675, 3676, 3677,
+ 3683, 3685, 3687, 3689, 3691, 3693, 3695, 3697,
+ 3703, 3705, 3707, 3709, 3711, 3713, 3715, 3719,
+ 3721, 3723, 3729, 3731, 3733, 3739, 3741, 3743,
+ 3747, 3749, 3750, 3756, 3758, 3760, 3763, 3770,
+ 3772, 3774, 3776, 3778, 3779, 3780, 3782, 3784,
+ 3786, 3787, 3793, 3794, 3795, 3801, 3802, 3803,
+ 3809, 3823, 3831, 3833, 3835, 3837, 3839, 3841,
+ 3847, 3853, 3855, 3857, 3859, 3861, 3863, 3869,
+ 3873, 3875, 3881, 3883, 3885, 3891, 3893, 3895,
+ 3897, 3903, 3905, 3907, 3913, 3917, 3919, 3925,
+ 3927, 3929, 3935, 3937, 3939, 3941, 3947, 3949,
+ 3951, 3957, 3960, 3969, 3978, 3984, 3993, 3999,
+ 4014, 4020, 4028, 4036, 4044, 4062, 4070, 4088,
+ 4096, 4114, 4122, 4140, 4148, 4160, 4168, 4171,
+ 4179, 4191, 4199, 4202, 4210, 4222, 4230, 4233,
+ 4241, 4253, 4261, 4264, 4267, 4270, 4276, 4282,
+ 4294, 4300, 4303, 4312, 4318, 4333, 4339, 4342,
+ 4344, 4352, 4367, 4373, 4376, 4382, 4392, 4408,
+ 4411, 4418, 4431, 4433, 4441, 4451, 4459, 4469,
+ 4478, 4486, 4492, 4500, 4508, 4518, 4526, 4536,
+ 4545, 4553, 4559, 4568, 4570, 4584, 4596, 4610,
+ 4622, 4636, 4648, 4662, 4672, 4675, 4688, 4701,
+ 4704, 4717, 4730, 4740, 4743, 4756, 4769, 4779,
+ 4782, 4795, 4808, 4818, 4821, 4827, 4830, 4838,
+ 4846, 4849, 4852, 4855, 4861, 4864, 4872, 4880,
+ 4883, 4886, 4888, 4896, 4904, 4912, 4920, 4928,
+ 4943, 4949, 4952, 4955, 4958, 4960, 4968, 4976,
+ 4984, 4996, 5002, 5014, 5020, 5032, 5038, 5053,
+ 5059, 5062, 5065, 5068, 5071, 5074, 5080, 5086,
+ 5094, 5102, 5114, 5120, 5133, 5135, 5138, 5141,
+ 5144, 5157, 5159, 5160, 5163, 5166, 5168, 5180,
+ 5183, 5184, 5191, 5198, 5200, 5208, 5220, 5226,
+ 5234, 5242, 5254, 5260, 5276, 5279, 5282, 5285,
+ 5288, 5290, 5298, 5306, 5314, 5326, 5332, 5348,
+ 5351, 5354, 5357, 5359, 5367, 5377, 5383, 5391,
+ 5399, 5406, 5440, 5453, 5455, 5458, 5472, 5475,
+ 5516, 5525, 5528, 5531, 5537, 5545, 5553, 5562,
+ 5599, 5602, 5605, 5611, 5619, 5627, 5640, 5681,
+ 5684, 5687, 5693, 5701, 5709, 5724, 5758, 5761,
+ 5764, 5767, 5795, 5807, 5819, 5825, 5833, 5841,
+ 5849, 5857, 5865, 5873, 5881, 5889, 5897, 5905,
+ 5920, 5926, 5939, 5941, 5944, 5947, 5950, 5953,
+ 5956, 5959, 5962, 5965, 5967, 5969, 5975, 5977,
+ 5979, 5981, 5987, 5989, 5995, 5999, 6001, 6003,
+ 6009, 6011, 6013, 6015, 6021, 6027, 6029, 6031,
+ 6033, 6039, 6043, 6045, 6047, 6053, 6055, 6057,
+ 6059, 6065, 6071, 6073, 6075, 6077, 6078, 6084,
+ 6085, 6091, 6093, 6095, 6097, 6099, 6105, 6107,
+ 6109, 6111, 6113, 6115, 6117, 6119, 6125, 6129,
+ 6131, 6137, 6143, 6149, 6150, 6156, 6157, 6163,
+ 6165, 6171, 6177, 6181, 6183, 6185, 6187, 6193,
+ 6199, 6205, 6207, 6209, 6211, 6217, 6219, 6225,
+ 6233, 6235, 6242, 6250, 6252, 6254, 6256, 6258,
+ 6264, 6266, 6268, 6274, 6280, 6286, 6288, 6290,
+ 6292, 6298, 6304, 6312, 6314, 6320, 6322, 6328,
+ 6330, 6336, 6338, 6340, 6342, 6348, 6354, 6356,
+ 6358, 6364, 6366, 6372, 6374, 6376, 6378, 6386,
+ 6395, 6401, 6407, 6409, 6417, 6425, 6433, 6445,
+ 6451, 6464, 6466, 6469, 6472, 6475, 6482, 6484,
+ 6486, 6494, 6502, 6510, 6518, 6526, 6539, 6545,
+ 6557, 6563, 6570, 6576, 6583, 6590, 6596, 6603,
+ 6615, 6621, 6622, 6623, 6624, 6625, 6626, 6629,
+ 6635, 6647, 6650, 6653, 6656, 6658, 6666, 6674,
+ 6682, 6690, 6698, 6711, 6717, 6723, 6735, 6738,
+ 6741, 6744, 6746, 6754, 6762, 6770, 6778, 6786,
+ 6798, 6804, 6820, 6823, 6826, 6829, 6832, 6834,
+ 6842, 6851, 6860, 6863, 6865, 6873, 6885, 6891,
+ 6897, 6903, 6904, 6910, 6916, 6922, 6928, 6935,
+ 6938, 6944, 6950, 6951, 6957, 6963, 6970, 6976,
+ 6982, 6983, 6989, 6995, 7002, 7020, 7053, 7099,
+ 7147, 7165, 7213, 7231, 7264, 7327, 7390, 7390,
+ 7390, 7390, 7402, 7402, 7402, 7402, 7418, 7418,
+ 7435, 7438, 7438, 7476, 7479, 7479, 7495, 7498,
+ 7510, 7510, 7526, 7529, 7532, 7532, 7532, 7532,
+ 7532, 7532, 7532, 7532, 7532, 7532, 7548, 7551,
+ 7551, 7551, 7561, 7564, 7576, 7579, 7591, 7594,
+ 7606, 7609, 7609, 7609, 7609, 7609, 7622, 7625,
+ 7625, 7641, 7644, 7644, 7660, 7663, 7663, 7677,
+ 7680, 7693, 7696, 7737, 7746, 7746, 7746, 7746,
+ 7746, 7746, 7746, 7746, 7762, 7765, 7765, 7765,
+ 7765
+};
+
+static const short _zone_scanner_trans_keys[] = {
+ 9, 32, 40, 41, 65, 67, 68, 69,
+ 72, 73, 75, 76, 77, 78, 80, 82,
+ 83, 84, 97, 99, 100, 101, 104, 105,
+ 107, 108, 109, 110, 112, 114, 115, 116,
+ 778, 827, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 68, 72, 77, 83, 87, 100,
+ 104, 109, 115, 119, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 65, 67, 68, 69,
+ 72, 73, 75, 76, 77, 78, 80, 82,
+ 83, 84, 97, 99, 100, 101, 104, 105,
+ 107, 108, 109, 110, 112, 114, 115, 116,
+ 1034, 1083, 9, 32, 40, 41, 65, 70,
+ 80, 97, 102, 112, 2058, 2107, 2314, 2363,
+ 2570, 2619, 9, 32, 40, 41, 92, 2058,
+ 2107, 2314, 2363, 2570, 2619, -128, 8, 11,
+ 58, 60, 127, 9, 32, 40, 41, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 778,
+ 827, 1034, 1083, 10, 35, 9, 32, 40,
+ 41, 778, 827, 1034, 1083, 1034, 896, 1151,
+ 9, 32, 40, 41, 92, 1802, 1851, 2058,
+ 2107, 2314, 2363, 2570, 2619, -128, 8, 11,
+ 58, 60, 127, 778, 1034, 640, 895, 896,
+ 1151, 9, 32, 40, 41, 58, 65, 67,
+ 68, 69, 72, 73, 75, 76, 77, 78,
+ 80, 82, 83, 84, 92, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 1802, 1851, 2058, 2107, 2314,
+ 2363, 2570, 2619, -128, 8, 11, 47, 48,
+ 57, 60, 127, 9, 32, 40, 41, 68,
+ 72, 77, 83, 87, 100, 104, 109, 115,
+ 119, 778, 827, 1034, 1083, 48, 57, 9,
+ 32, 40, 41, 65, 67, 68, 69, 72,
+ 73, 75, 76, 77, 78, 80, 82, 83,
+ 84, 97, 99, 100, 101, 104, 105, 107,
+ 108, 109, 110, 112, 114, 115, 116, 778,
+ 827, 1034, 1083, 69, 78, 101, 110, 82,
+ 114, 84, 116, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 777, 778, 800,
+ 808, 809, 827, 1033, 1034, 1056, 1064, 1065,
+ 1083, 896, 1151, 65, 97, 77, 109, 69,
+ 101, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 72, 78, 83, 104, 110,
+ 115, 67, 99, 73, 105, 68, 100, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 65, 83, 97, 115, 77, 109, 69,
+ 101, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 75, 107, 69, 101, 89,
+ 121, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 85, 117, 73,
+ 105, 52, 54, 56, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 52, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 73, 105, 78, 110, 70, 102, 79,
+ 111, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 78, 80, 110, 112, 9,
+ 32, 40, 41, 1034, 1083, 9, 32, 40,
+ 41, 65, 67, 68, 69, 72, 73, 75,
+ 76, 77, 78, 80, 82, 83, 84, 97,
+ 99, 100, 101, 104, 105, 107, 108, 109,
+ 110, 112, 114, 115, 116, 1034, 1083, 80,
+ 112, 83, 115, 69, 101, 67, 99, 75,
+ 107, 69, 101, 89, 121, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 69,
+ 88, 101, 120, 89, 121, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 51, 54, 79, 80, 111, 112, 50,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 52, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 67, 99, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 73, 88, 105, 120, 78,
+ 110, 70, 102, 79, 111, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 65, 73, 83, 97, 105, 115, 80,
+ 112, 84, 116, 82, 114, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 68,
+ 100, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 9, 32, 40, 41, 69,
+ 101, 2058, 2107, 2314, 2363, 2570, 2619, 67,
+ 99, 9, 32, 40, 41, 51, 2058, 2107,
+ 2314, 2363, 2570, 2619, 9, 32, 40, 41,
+ 80, 112, 2058, 2107, 2314, 2363, 2570, 2619,
+ 65, 97, 82, 114, 65, 97, 77, 109,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 84, 116, 82, 114, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 80, 82, 84, 112, 114, 116, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 83, 115, 73, 105, 71, 103, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 79, 80, 82, 83, 111, 112,
+ 114, 115, 65, 97, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 70, 102,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 86, 118, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 72, 104,
+ 70, 102, 80, 112, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 76, 88,
+ 89, 108, 120, 121, 83, 115, 65, 97,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 84, 116, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 80, 112,
+ 69, 101, 48, 57, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 1034, 896, 1151, 9, 32, 40, 41, 65,
+ 67, 68, 69, 72, 73, 75, 76, 77,
+ 78, 80, 82, 83, 84, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 778, 827, 1034, 1083, 48,
+ 57, 78, 80, 110, 112, 9, 32, 40,
+ 41, 1034, 1083, 9, 32, 40, 41, 65,
+ 67, 68, 69, 72, 73, 75, 76, 77,
+ 78, 80, 82, 83, 84, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 1034, 1083, 48, 57, 9,
+ 32, 40, 41, 68, 72, 77, 83, 87,
+ 100, 104, 109, 115, 119, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 68, 72, 77, 83, 87, 100, 104,
+ 109, 115, 119, 48, 57, 9, 32, 40,
+ 41, 1034, 1083, 48, 57, 1034, 896, 1151,
+ 10, 73, 79, 84, 105, 111, 116, 78,
+ 110, 67, 99, 76, 108, 85, 117, 68,
+ 100, 69, 101, 32, 59, 9, 10, 40,
+ 41, 9, 32, 40, 41, 1034, 1083, 9,
+ 32, 40, 41, 65, 67, 68, 69, 72,
+ 73, 75, 76, 77, 78, 80, 82, 83,
+ 84, 97, 99, 100, 101, 104, 105, 107,
+ 108, 109, 110, 112, 114, 115, 116, 1034,
+ 1083, 48, 57, 1034, 896, 1151, 9, 32,
+ 40, 41, 68, 72, 77, 83, 87, 100,
+ 104, 109, 115, 119, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 65, 67, 68, 69,
+ 72, 73, 75, 76, 77, 78, 80, 82,
+ 83, 84, 97, 99, 100, 101, 104, 105,
+ 107, 108, 109, 110, 112, 114, 115, 116,
+ 1034, 1083, 48, 57, 1034, 896, 1151, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 68,
+ 72, 77, 83, 87, 100, 104, 109, 115,
+ 119, 48, 57, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 1034, 896, 1151, 9, 32,
+ 40, 41, 65, 70, 80, 97, 102, 112,
+ 2058, 2107, 2314, 2363, 2570, 2619, 9, 32,
+ 40, 41, 58, 65, 67, 68, 69, 72,
+ 73, 75, 76, 77, 78, 80, 82, 83,
+ 84, 92, 97, 99, 100, 101, 104, 105,
+ 107, 108, 109, 110, 112, 114, 115, 116,
+ 2058, 2107, 2314, 2363, 2570, 2619, -128, 8,
+ 11, 47, 48, 57, 60, 127, 9, 32,
+ 40, 41, 65, 70, 80, 97, 102, 112,
+ 1802, 1851, 2058, 2107, 2314, 2363, 2570, 2619,
+ 9, 32, 40, 41, 92, 1802, 1851, 2058,
+ 2107, 2314, 2363, 2570, 2619, -128, 8, 11,
+ 58, 60, 127, 9, 32, 40, 41, 65,
+ 67, 68, 69, 72, 73, 75, 76, 77,
+ 78, 80, 82, 83, 84, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 778, 827, 1034, 1083, 48,
+ 57, 778, 1034, 640, 895, 896, 1151, 9,
+ 32, 40, 41, 778, 827, 1034, 1083, -128,
+ 8, 11, 58, 60, 127, 9, 32, 40,
+ 41, 778, 827, 1034, 1083, -128, 8, 11,
+ 58, 60, 127, 9, 32, 40, 41, 58,
+ 65, 67, 68, 69, 72, 73, 75, 76,
+ 77, 78, 80, 82, 83, 84, 92, 97,
+ 99, 100, 101, 104, 105, 107, 108, 109,
+ 110, 112, 114, 115, 116, 1802, 1851, 2058,
+ 2107, 2314, 2363, 2570, 2619, -128, 8, 11,
+ 47, 48, 57, 60, 127, 9, 32, 40,
+ 41, 69, 78, 101, 110, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 72, 78, 83,
+ 104, 110, 115, 778, 827, 1034, 1083, 9,
+ 32, 40, 41, 85, 117, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 73, 105, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 78,
+ 80, 110, 112, 778, 827, 1034, 1083, 9,
+ 32, 40, 41, 69, 88, 101, 120, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 51,
+ 54, 79, 80, 111, 112, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 73, 88, 105,
+ 120, 778, 827, 1034, 1083, 9, 32, 40,
+ 41, 65, 73, 83, 97, 105, 115, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 84,
+ 116, 778, 827, 1034, 1083, 9, 32, 40,
+ 41, 80, 82, 84, 112, 114, 116, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 79,
+ 80, 82, 83, 111, 112, 114, 115, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 76,
+ 88, 89, 108, 120, 121, 778, 827, 1034,
+ 1083, 778, 1034, 640, 895, 896, 1151, 9,
+ 32, 40, 41, 73, 79, 84, 105, 111,
+ 116, 778, 827, 1034, 1083, 82, 114, 73,
+ 105, 71, 103, 73, 105, 78, 110, 32,
+ 59, 9, 10, 40, 41, 84, 116, 76,
+ 108, 32, 59, 9, 10, 40, 41, 9,
+ 32, 40, 41, 778, 827, 1034, 1083, 9,
+ 32, 40, 41, 68, 72, 77, 83, 87,
+ 100, 104, 109, 115, 119, 778, 827, 1034,
+ 1083, 48, 57, 9, 32, 40, 41, 65,
+ 67, 68, 69, 72, 73, 75, 76, 77,
+ 78, 80, 82, 83, 84, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 778, 827, 1034, 1083, 48,
+ 57, 778, 1034, 640, 895, 896, 1151, 9,
+ 32, 40, 41, 65, 70, 80, 97, 102,
+ 112, 1802, 1851, 2058, 2107, 2314, 2363, 2570,
+ 2619, 9, 32, 40, 41, 58, 65, 67,
+ 68, 69, 72, 73, 75, 76, 77, 78,
+ 80, 82, 83, 84, 92, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 1802, 1851, 2058, 2107, 2314,
+ 2363, 2570, 2619, -128, 8, 11, 47, 48,
+ 57, 60, 127, 9, 32, 40, 41, 69,
+ 78, 101, 110, 778, 827, 1034, 1083, 9,
+ 32, 40, 41, 72, 78, 83, 104, 110,
+ 115, 778, 827, 1034, 1083, 9, 32, 40,
+ 41, 85, 117, 778, 827, 1034, 1083, 9,
+ 32, 40, 41, 73, 105, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 78, 80, 110,
+ 112, 778, 827, 1034, 1083, 9, 32, 40,
+ 41, 69, 88, 101, 120, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 51, 54, 79,
+ 80, 111, 112, 778, 827, 1034, 1083, 9,
+ 32, 40, 41, 73, 88, 105, 120, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 65,
+ 73, 83, 97, 105, 115, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 84, 116, 778,
+ 827, 1034, 1083, 9, 32, 40, 41, 80,
+ 82, 84, 112, 114, 116, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 79, 80, 82,
+ 83, 111, 112, 114, 115, 778, 827, 1034,
+ 1083, 9, 32, 40, 41, 76, 88, 89,
+ 108, 120, 121, 778, 827, 1034, 1083, 9,
+ 32, 35, 40, 41, 778, 827, 1034, 1083,
+ -128, 8, 11, 58, 60, 127, 9, 32,
+ 40, 41, 65, 67, 68, 69, 72, 73,
+ 75, 76, 77, 78, 80, 82, 83, 84,
+ 97, 99, 100, 101, 104, 105, 107, 108,
+ 109, 110, 112, 114, 115, 116, 778, 827,
+ 1034, 1083, 48, 57, 777, 778, 800, 808,
+ 809, 827, 1033, 1034, 1056, 1064, 1065, 1083,
+ 896, 1151, 777, 778, 800, 808, 809, 827,
+ 1033, 1034, 1056, 1064, 1065, 1083, 896, 1151,
+ 777, 778, 800, 808, 809, 1033, 1034, 1056,
+ 1064, 1065, 640, 895, 896, 1151, 65, 97,
+ 65, 97, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 83, 115, 68, 100,
+ 66, 98, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 76, 108, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 778, 1034, 640, 895, 896, 1151, 9, 32,
+ 40, 41, 778, 827, 1034, 1083, -128, 8,
+ 11, 58, 60, 127, 9, 32, 40, 41,
+ 778, 827, 1034, 1083, -128, 8, 11, 58,
+ 60, 127, 777, 778, 800, 808, 809, 827,
+ 1033, 1034, 1056, 1064, 1065, 1083, 640, 895,
+ 896, 1151, 777, 778, 800, 808, 809, 1033,
+ 1034, 1056, 1064, 1065, 640, 895, 896, 1151,
+ 1034, 896, 1151, 777, 778, 800, 808, 809,
+ 827, 1033, 1034, 1056, 1064, 1065, 1083, 896,
+ 1151, 9, 32, 40, 41, 69, 78, 101,
+ 110, 1034, 1083, 9, 32, 40, 41, 72,
+ 78, 83, 104, 110, 115, 1034, 1083, 9,
+ 32, 40, 41, 85, 117, 1034, 1083, 9,
+ 32, 40, 41, 73, 105, 1034, 1083, 9,
+ 32, 40, 41, 78, 80, 110, 112, 1034,
+ 1083, 9, 32, 40, 41, 69, 88, 101,
+ 120, 1034, 1083, 9, 32, 40, 41, 51,
+ 54, 79, 80, 111, 112, 1034, 1083, 9,
+ 32, 40, 41, 73, 88, 105, 120, 1034,
+ 1083, 9, 32, 40, 41, 65, 73, 83,
+ 97, 105, 115, 1034, 1083, 9, 32, 40,
+ 41, 84, 116, 1034, 1083, 9, 32, 40,
+ 41, 80, 82, 84, 112, 114, 116, 1034,
+ 1083, 9, 32, 40, 41, 79, 80, 82,
+ 83, 111, 112, 114, 115, 1034, 1083, 9,
+ 32, 40, 41, 76, 88, 89, 108, 120,
+ 121, 1034, 1083, 778, 1034, 640, 895, 896,
+ 1151, 778, 1034, 640, 895, 896, 1151, 9,
+ 32, 40, 41, 78, 80, 110, 112, 1034,
+ 1083, 778, 1034, 640, 895, 896, 1151, 10,
+ 10, 42, 46, 64, 92, 95, 45, 57,
+ 65, 90, 97, 122, 32, 46, 59, 9,
+ 10, 40, 41, 32, 42, 45, 59, 92,
+ 95, 9, 10, 40, 41, 47, 57, 65,
+ 90, 97, 122, 32, 46, 59, 92, 95,
+ 9, 10, 40, 41, 45, 57, 65, 90,
+ 97, 122, 48, 57, 48, 57, 48, 57,
+ 32, 46, 59, 92, 95, 9, 10, 40,
+ 41, 45, 57, 65, 90, 97, 122, 32,
+ 59, 9, 10, 40, 41, 32, 59, 9,
+ 10, 40, 41, 34, 92, 33, 58, 60,
+ 126, 32, 33, 59, 92, 9, 10, 35,
+ 39, 40, 41, 42, 126, 48, 57, 48,
+ 57, 48, 57, 32, 33, 59, 92, 9,
+ 10, 35, 39, 40, 41, 42, 126, 9,
+ 34, 92, 522, 32, 126, 32, 59, 9,
+ 10, 40, 41, 48, 57, 48, 57, 48,
+ 57, 9, 34, 92, 522, 32, 126, 9,
+ 32, 40, 41, 1034, 1083, 9, 32, 40,
+ 41, 1034, 1083, 48, 57, 9, 32, 40,
+ 41, 68, 72, 77, 83, 87, 100, 104,
+ 109, 115, 119, 778, 827, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 778, 827, 1034,
+ 1083, 10, 9, 32, 40, 41, 778, 827,
+ 1034, 1083, 48, 57, 68, 72, 77, 83,
+ 87, 100, 104, 109, 115, 119, 48, 57,
+ 9, 32, 40, 41, 778, 827, 1034, 1083,
+ 48, 57, 1034, 896, 1151, 9, 32, 40,
+ 41, 1034, 1083, 9, 32, 40, 41, 42,
+ 46, 92, 95, 1034, 1083, 45, 57, 65,
+ 90, 97, 122, 46, 9, 32, 40, 41,
+ 42, 45, 92, 95, 778, 827, 1034, 1083,
+ 47, 57, 65, 90, 97, 122, 9, 32,
+ 40, 41, 778, 827, 1034, 1083, 10, 46,
+ 92, 95, 45, 57, 65, 90, 97, 122,
+ 48, 57, 48, 57, 48, 57, 46, 92,
+ 95, 45, 57, 65, 90, 97, 122, 9,
+ 32, 40, 41, 778, 827, 1034, 1083, 1034,
+ 896, 1151, 9, 32, 40, 41, 1034, 1083,
+ 9, 32, 40, 41, 1034, 1083, -128, 8,
+ 11, 58, 60, 127, 9, 32, 40, 41,
+ 778, 827, 1034, 1083, 9, 32, 40, 41,
+ 42, 46, 92, 95, 778, 827, 1034, 1083,
+ 45, 57, 65, 90, 97, 122, 46, 9,
+ 32, 40, 41, 42, 45, 92, 95, 778,
+ 827, 1034, 1083, 47, 57, 65, 90, 97,
+ 122, 9, 32, 40, 41, 778, 827, 1034,
+ 1083, 10, 46, 92, 95, 45, 57, 65,
+ 90, 97, 122, 48, 57, 48, 57, 48,
+ 57, 46, 92, 95, 45, 57, 65, 90,
+ 97, 122, 9, 32, 40, 41, 778, 827,
+ 1034, 1083, 778, 1034, 640, 895, 896, 1151,
+ 9, 32, 40, 41, 42, 46, 92, 95,
+ 1034, 1083, 45, 57, 65, 90, 97, 122,
+ 1034, 896, 1151, 1034, 896, 1151, 43, 47,
+ 57, 65, 90, 97, 122, 43, 47, 57,
+ 65, 90, 97, 122, 43, 61, 47, 57,
+ 65, 90, 97, 122, 43, 61, 47, 57,
+ 65, 90, 97, 122, 9, 32, 40, 41,
+ 43, 2058, 2107, 2314, 2363, 2570, 2619, 47,
+ 57, 65, 90, 97, 122, 1034, 896, 1151,
+ 61, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 9, 32, 40, 41, 65,
+ 67, 68, 69, 72, 73, 75, 76, 77,
+ 78, 80, 82, 83, 84, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 2058, 2107, 2314, 2363, 2570,
+ 2619, 9, 32, 40, 41, 65, 70, 80,
+ 97, 102, 112, 2058, 2107, 2314, 2363, 2570,
+ 2619, 65, 97, 65, 97, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 1034,
+ 896, 1151, 69, 78, 101, 110, 82, 114,
+ 84, 116, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 65, 97, 77, 109,
+ 69, 101, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 72, 78, 83, 104,
+ 110, 115, 67, 99, 73, 105, 68, 100,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 65, 83, 97, 115, 77, 109,
+ 69, 101, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 75, 107, 69, 101,
+ 89, 121, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 85, 117,
+ 73, 105, 52, 54, 56, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 52,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 73, 105, 78, 110, 70, 102,
+ 79, 111, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 80, 112, 83, 115,
+ 69, 101, 67, 99, 75, 107, 69, 101,
+ 89, 121, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 69, 88, 101, 120,
+ 89, 121, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 51, 54,
+ 79, 80, 111, 112, 50, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 52,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 67, 99, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 73, 88, 105, 120, 78, 110, 70, 102,
+ 79, 111, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 65, 73,
+ 83, 97, 105, 115, 80, 112, 84, 116,
+ 82, 114, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 68, 100, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 9, 32, 40, 41, 69, 101, 2058, 2107,
+ 2314, 2363, 2570, 2619, 67, 99, 9, 32,
+ 40, 41, 51, 2058, 2107, 2314, 2363, 2570,
+ 2619, 9, 32, 40, 41, 80, 112, 2058,
+ 2107, 2314, 2363, 2570, 2619, 65, 97, 82,
+ 114, 65, 97, 77, 109, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 84,
+ 116, 82, 114, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 80, 82, 84,
+ 112, 114, 116, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 83, 115, 73,
+ 105, 71, 103, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 79,
+ 80, 82, 83, 111, 112, 114, 115, 65,
+ 97, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 70, 102, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 86,
+ 118, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 72, 104, 70, 102, 80,
+ 112, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 76, 88, 89, 108, 120,
+ 121, 83, 115, 65, 97, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 84,
+ 116, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 80, 112, 69, 101, 48,
+ 57, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 48, 57, 83, 115, 68,
+ 100, 66, 98, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 76, 108, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 9, 32, 40, 41, 1034, 1083, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 65,
+ 70, 97, 102, 48, 57, 65, 70, 97,
+ 102, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 48, 57, 65, 70, 97,
+ 102, 1034, 896, 1151, 1034, 896, 1151, 1034,
+ 896, 1151, 9, 32, 40, 41, 1034, 1083,
+ 9, 32, 40, 41, 48, 1034, 1083, 49,
+ 57, 9, 32, 40, 41, 778, 827, 1034,
+ 1083, 48, 57, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 65, 70, 97, 102, 48,
+ 57, 65, 70, 97, 102, 9, 32, 40,
+ 41, 2058, 2107, 2314, 2363, 2570, 2619, 48,
+ 57, 65, 70, 97, 102, 1034, 896, 1151,
+ 1034, 896, 1151, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 1034, 896, 1151, 68, 69,
+ 73, 80, 82, 100, 101, 105, 112, 114,
+ 48, 57, 32, 59, 9, 10, 40, 41,
+ 48, 57, 72, 83, 104, 115, 32, 59,
+ 9, 10, 40, 41, 65, 97, 32, 45,
+ 59, 9, 10, 40, 41, 78, 110, 83,
+ 115, 69, 101, 67, 99, 51, 45, 83,
+ 115, 72, 104, 65, 97, 49, 32, 59,
+ 9, 10, 40, 41, 67, 99, 67, 68,
+ 99, 100, 45, 71, 103, 79, 111, 83,
+ 115, 84, 116, 32, 59, 9, 10, 40,
+ 41, 83, 115, 65, 97, 80, 112, 50,
+ 51, 53, 54, 83, 115, 72, 104, 65,
+ 97, 50, 53, 54, 32, 59, 9, 10,
+ 40, 41, 56, 52, 83, 115, 72, 104,
+ 65, 97, 51, 56, 52, 32, 59, 9,
+ 10, 40, 41, 78, 110, 68, 100, 73,
+ 105, 82, 114, 69, 101, 67, 99, 84,
+ 116, 32, 59, 9, 10, 40, 41, 82,
+ 114, 73, 105, 86, 118, 65, 97, 84,
+ 116, 69, 101, 68, 79, 100, 111, 78,
+ 110, 83, 115, 32, 59, 9, 10, 40,
+ 41, 73, 105, 68, 100, 32, 59, 9,
+ 10, 40, 41, 83, 115, 65, 97, 77,
+ 83, 109, 115, 68, 100, 53, 32, 59,
+ 9, 10, 40, 41, 72, 104, 65, 97,
+ 49, 50, 53, 32, 45, 59, 9, 10,
+ 40, 41, 78, 110, 83, 115, 69, 101,
+ 67, 99, 51, 45, 83, 115, 72, 104,
+ 65, 97, 49, 32, 59, 9, 10, 40,
+ 41, 53, 54, 32, 59, 9, 10, 40,
+ 41, 49, 50, 32, 59, 9, 10, 40,
+ 41, 65, 73, 79, 80, 83, 85, 97,
+ 105, 111, 112, 115, 117, 48, 57, 32,
+ 59, 9, 10, 40, 41, 48, 57, 67,
+ 99, 80, 112, 75, 107, 73, 105, 88,
+ 120, 32, 59, 9, 10, 40, 41, 65,
+ 80, 83, 97, 112, 115, 67, 99, 80,
+ 112, 75, 107, 73, 105, 88, 120, 32,
+ 59, 9, 10, 40, 41, 71, 75, 103,
+ 107, 80, 112, 32, 59, 9, 10, 40,
+ 41, 73, 105, 88, 120, 32, 59, 9,
+ 10, 40, 41, 80, 112, 75, 107, 73,
+ 105, 32, 59, 9, 10, 40, 41, 73,
+ 105, 68, 100, 32, 59, 9, 10, 40,
+ 41, 71, 75, 103, 107, 80, 112, 32,
+ 59, 9, 10, 40, 41, 73, 105, 88,
+ 120, 32, 59, 9, 10, 40, 41, 80,
+ 112, 75, 107, 73, 105, 32, 59, 9,
+ 10, 40, 41, 82, 114, 73, 105, 32,
+ 59, 9, 10, 40, 41, 46, 48, 57,
+ 32, 46, 59, 9, 10, 40, 41, 48,
+ 57, 42, 92, 95, 45, 57, 64, 90,
+ 97, 122, 32, 59, 9, 10, 40, 41,
+ 42, 92, 95, 45, 57, 64, 90, 97,
+ 122, 9, 32, 40, 41, 1034, 1083, 9,
+ 32, 40, 41, 42, 92, 95, 1034, 1083,
+ 45, 57, 64, 90, 97, 122, 9, 32,
+ 40, 41, 1034, 1083, 9, 32, 40, 41,
+ 1034, 1083, 48, 57, 9, 32, 40, 41,
+ 1034, 1083, 48, 57, 9, 32, 40, 41,
+ 1034, 1083, 48, 57, 9, 32, 40, 41,
+ 68, 72, 77, 83, 87, 100, 104, 109,
+ 115, 119, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 68, 72, 77, 83, 87, 100,
+ 104, 109, 115, 119, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 68, 72, 77, 83,
+ 87, 100, 104, 109, 115, 119, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 32, 59, 68, 72, 77, 83,
+ 87, 100, 104, 109, 115, 119, 9, 10,
+ 40, 41, 48, 57, 32, 59, 9, 10,
+ 40, 41, 48, 57, 68, 72, 77, 83,
+ 87, 100, 104, 109, 115, 119, 48, 57,
+ 32, 59, 9, 10, 40, 41, 48, 57,
+ 1034, 896, 1151, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 68, 72, 77, 83, 87,
+ 100, 104, 109, 115, 119, 48, 57, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 1034,
+ 896, 1151, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 68, 72, 77, 83, 87, 100,
+ 104, 109, 115, 119, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 1034, 896,
+ 1151, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 68, 72, 77, 83, 87, 100, 104,
+ 109, 115, 119, 48, 57, 9, 32, 40,
+ 41, 1034, 1083, 48, 57, 1034, 896, 1151,
+ 1034, 896, 1151, 1034, 896, 1151, 32, 59,
+ 9, 10, 40, 41, 9, 32, 40, 41,
+ 1034, 1083, 9, 32, 40, 41, 1034, 1083,
+ -128, 8, 11, 58, 60, 127, 32, 59,
+ 9, 10, 40, 41, 1034, 896, 1151, 42,
+ 92, 95, 45, 57, 64, 90, 97, 122,
+ 9, 32, 40, 41, 1034, 1083, 9, 32,
+ 40, 41, 42, 92, 95, 1034, 1083, 45,
+ 57, 64, 90, 97, 122, 32, 59, 9,
+ 10, 40, 41, 1034, 896, 1151, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 42, 92, 95, 1034,
+ 1083, 45, 57, 64, 90, 97, 122, 32,
+ 59, 9, 10, 40, 41, 1034, 896, 1151,
+ 32, 59, 9, 10, 40, 41, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, -128, 8, 11, 58, 60, 127,
+ 1034, 896, 1151, 46, 48, 58, 65, 70,
+ 97, 102, 32, 46, 59, 9, 10, 40,
+ 41, 48, 58, 65, 70, 97, 102, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 78, 83, 1034,
+ 1083, 48, 57, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 9, 32, 40, 41, 78,
+ 83, 1034, 1083, 48, 57, 9, 32, 40,
+ 41, 46, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 78, 83, 1034, 1083, 9, 32,
+ 40, 41, 1034, 1083, 9, 32, 40, 41,
+ 1034, 1083, 48, 57, 9, 32, 40, 41,
+ 1034, 1083, 48, 57, 9, 32, 40, 41,
+ 69, 87, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 69, 87, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 46, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 69, 87, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 9,
+ 32, 40, 41, 45, 1034, 1083, 48, 57,
+ 48, 57, 9, 32, 40, 41, 46, 109,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 48, 57, 9, 32, 40, 41,
+ 46, 109, 2058, 2107, 2314, 2363, 2570, 2619,
+ 48, 57, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 48, 57, 9, 32,
+ 40, 41, 46, 109, 2058, 2107, 2314, 2363,
+ 2570, 2619, 48, 57, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 9, 32, 40, 41, 46, 109, 2058, 2107,
+ 2314, 2363, 2570, 2619, 48, 57, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 1034, 896, 1151, 9, 32, 40, 41, 109,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 9, 32, 40, 41, 109, 2058, 2107, 2314,
+ 2363, 2570, 2619, 48, 57, 1034, 896, 1151,
+ 9, 32, 40, 41, 109, 2058, 2107, 2314,
+ 2363, 2570, 2619, 48, 57, 9, 32, 40,
+ 41, 109, 2058, 2107, 2314, 2363, 2570, 2619,
+ 48, 57, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 1034, 896, 1151, 9,
+ 32, 40, 41, 109, 2058, 2107, 2314, 2363,
+ 2570, 2619, 48, 57, 9, 32, 40, 41,
+ 109, 2058, 2107, 2314, 2363, 2570, 2619, 48,
+ 57, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 1034, 896, 1151, 9, 32,
+ 40, 41, 109, 2058, 2107, 2314, 2363, 2570,
+ 2619, 48, 57, 9, 32, 40, 41, 109,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 1034, 896, 1151, 9, 32, 40,
+ 41, 1034, 1083, 1034, 896, 1151, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 1034, 896,
+ 1151, 1034, 896, 1151, 1034, 896, 1151, 9,
+ 32, 40, 41, 1034, 1083, 1034, 896, 1151,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 1034, 896, 1151, 1034, 896, 1151, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 42, 92, 95, 1034,
+ 1083, 45, 57, 64, 90, 97, 122, 32,
+ 59, 9, 10, 40, 41, 1034, 896, 1151,
+ 1034, 896, 1151, 1034, 896, 1151, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, -128, 8,
+ 11, 58, 60, 127, 9, 32, 40, 41,
+ 1034, 1083, 9, 32, 40, 41, 1034, 1083,
+ -128, 8, 11, 58, 60, 127, 9, 32,
+ 40, 41, 1034, 1083, 9, 32, 40, 41,
+ 1034, 1083, -128, 8, 11, 58, 60, 127,
+ 9, 32, 40, 41, 1034, 1083, 9, 32,
+ 40, 41, 42, 92, 95, 1034, 1083, 45,
+ 57, 64, 90, 97, 122, 32, 59, 9,
+ 10, 40, 41, 1034, 896, 1151, 1034, 896,
+ 1151, 1034, 896, 1151, 1034, 896, 1151, 1034,
+ 896, 1151, 48, 57, 65, 90, 97, 122,
+ 9, 32, 40, 41, 1034, 1083, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 65, 90,
+ 97, 122, 9, 32, 40, 41, 1034, 1083,
+ 9, 32, 40, 41, 43, 1034, 1083, 47,
+ 57, 65, 90, 97, 122, 1546, 1595, 1034,
+ 896, 1151, 1034, 896, 1151, 1034, 896, 1151,
+ 9, 32, 33, 40, 41, 49, 50, 2058,
+ 2107, 2314, 2363, 2570, 2619, 49, 50, 58,
+ 46, 48, 57, 47, 46, 57, 48, 57,
+ 9, 32, 40, 41, 2058, 2107, 2314, 2363,
+ 2570, 2619, 48, 57, 1034, 896, 1151, 58,
+ 46, 48, 58, 65, 70, 97, 102, 47,
+ 46, 58, 65, 70, 97, 102, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 9, 32, 40, 41, 1034, 1083, 48, 57,
+ 65, 90, 97, 122, 9, 32, 40, 41,
+ 1034, 1083, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 65, 70, 97, 102, 48, 57,
+ 65, 70, 97, 102, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 65, 70, 97, 102, 1034, 896, 1151, 1034,
+ 896, 1151, 1034, 896, 1151, 1034, 896, 1151,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 65, 70, 97, 102, 48, 57,
+ 65, 70, 97, 102, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 65, 70, 97, 102, 1034, 896, 1151, 1034,
+ 896, 1151, 1034, 896, 1151, 48, 57, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 9,
+ 32, 40, 41, 48, 49, 50, 51, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 9,
+ 32, 40, 41, 46, 1034, 1083, 6153, 6176,
+ 6184, 6185, 6409, 6432, 6440, 6441, 6665, 6688,
+ 6696, 6697, 9482, 9531, 9738, 9787, 10250, 10299,
+ 10506, 10555, 10762, 10811, 11274, 11323, 11530, 11579,
+ 11786, 11835, 12298, 12347, 12554, 12603, 12810, 12859,
+ 3081, 3104, 3112, 3113, 3115, 4106, 4155, 3119,
+ 3129, 3137, 3162, 3169, 3194, 1546, 1595, 4106,
+ 3968, 4223, 4617, 4640, 4648, 4649, 13578, 13627,
+ 13834, 13883, 14346, 14395, 14602, 14651, 14858, 14907,
+ 5642, 5504, 5759, 3115, 6153, 6176, 6184, 6185,
+ 6409, 6432, 6440, 6441, 6665, 6688, 6696, 6697,
+ 9482, 9531, 9738, 9787, 10250, 10299, 10506, 10555,
+ 10762, 10811, 11274, 11323, 11530, 11579, 11786, 11835,
+ 12298, 12347, 12554, 12603, 12810, 12859, 3119, 3129,
+ 3137, 3162, 3169, 3194, 7690, 8202, 8714, 7552,
+ 7807, 8064, 8319, 8576, 8831, 1034, 896, 1151,
+ 1034, 896, 1151, 9, 32, 40, 41, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 46, 1034, 1083,
+ 48, 57, 46, 6153, 6176, 6184, 6185, 6409,
+ 6432, 6440, 6441, 6665, 6688, 6696, 6697, 9482,
+ 9531, 9738, 9787, 10250, 10299, 10506, 10555, 10762,
+ 10811, 11274, 11323, 11530, 11579, 11786, 11835, 12298,
+ 12347, 12554, 12603, 12810, 12859, 48, 57, 1034,
+ 896, 1151, 1034, 896, 1151, 9, 32, 40,
+ 41, 1034, 1083, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 9, 32, 40, 41, 46,
+ 1034, 1083, 48, 58, 65, 70, 97, 102,
+ 46, 6153, 6176, 6184, 6185, 6409, 6432, 6440,
+ 6441, 6665, 6688, 6696, 6697, 9482, 9531, 9738,
+ 9787, 10250, 10299, 10506, 10555, 10762, 10811, 11274,
+ 11323, 11530, 11579, 11786, 11835, 12298, 12347, 12554,
+ 12603, 12810, 12859, 48, 58, 65, 70, 97,
+ 102, 1034, 896, 1151, 1034, 896, 1151, 9,
+ 32, 40, 41, 1034, 1083, 9, 32, 40,
+ 41, 1034, 1083, 48, 57, 9, 32, 40,
+ 41, 1034, 1083, 48, 57, 9, 32, 40,
+ 41, 42, 92, 95, 1034, 1083, 45, 57,
+ 64, 90, 97, 122, 6153, 6176, 6184, 6185,
+ 6409, 6432, 6440, 6441, 6665, 6688, 6696, 6697,
+ 9482, 9531, 9738, 9787, 10250, 10299, 10506, 10555,
+ 10762, 10811, 11274, 11323, 11530, 11579, 11786, 11835,
+ 12298, 12347, 12554, 12603, 12810, 12859, 1034, 896,
+ 1151, 1034, 896, 1151, 1034, 896, 1151, 65,
+ 67, 68, 69, 72, 73, 75, 76, 77,
+ 78, 80, 82, 83, 84, 97, 99, 100,
+ 101, 104, 105, 107, 108, 109, 110, 112,
+ 114, 115, 116, 9, 32, 40, 41, 65,
+ 70, 80, 97, 102, 112, 1034, 1083, 9,
+ 32, 40, 41, 1034, 1083, 48, 57, 65,
+ 90, 97, 122, 9, 32, 40, 41, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 42, 92, 95,
+ 1034, 1083, 45, 57, 64, 90, 97, 122,
+ 9, 32, 40, 41, 1034, 1083, 9, 32,
+ 40, 41, 43, 1034, 1083, 47, 57, 65,
+ 90, 97, 122, 1546, 1595, 1034, 896, 1151,
+ 1034, 896, 1151, 1034, 896, 1151, 1034, 896,
+ 1151, 1034, 896, 1151, 1034, 896, 1151, 1034,
+ 896, 1151, 1034, 896, 1151, 65, 97, 65,
+ 97, 9, 32, 40, 41, 1034, 1083, 83,
+ 115, 68, 100, 66, 98, 9, 32, 40,
+ 41, 1034, 1083, 76, 108, 9, 32, 40,
+ 41, 1034, 1083, 69, 78, 101, 110, 82,
+ 114, 84, 116, 9, 32, 40, 41, 1034,
+ 1083, 65, 97, 77, 109, 69, 101, 9,
+ 32, 40, 41, 1034, 1083, 72, 78, 83,
+ 104, 110, 115, 67, 99, 73, 105, 68,
+ 100, 9, 32, 40, 41, 1034, 1083, 65,
+ 83, 97, 115, 77, 109, 69, 101, 9,
+ 32, 40, 41, 1034, 1083, 75, 107, 69,
+ 101, 89, 121, 9, 32, 40, 41, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 85,
+ 117, 73, 105, 52, 54, 56, 9, 32,
+ 40, 41, 1034, 1083, 52, 9, 32, 40,
+ 41, 1034, 1083, 73, 105, 78, 110, 70,
+ 102, 79, 111, 9, 32, 40, 41, 1034,
+ 1083, 80, 112, 83, 115, 69, 101, 67,
+ 99, 75, 107, 69, 101, 89, 121, 9,
+ 32, 40, 41, 1034, 1083, 69, 88, 101,
+ 120, 89, 121, 9, 32, 40, 41, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 51,
+ 54, 79, 80, 111, 112, 50, 9, 32,
+ 40, 41, 1034, 1083, 52, 9, 32, 40,
+ 41, 1034, 1083, 67, 99, 9, 32, 40,
+ 41, 1034, 1083, 9, 32, 40, 41, 1034,
+ 1083, 73, 88, 105, 120, 78, 110, 70,
+ 102, 79, 111, 9, 32, 40, 41, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 65,
+ 73, 83, 97, 105, 115, 80, 112, 84,
+ 116, 82, 114, 9, 32, 40, 41, 1034,
+ 1083, 68, 100, 9, 32, 40, 41, 1034,
+ 1083, 9, 32, 40, 41, 69, 101, 1034,
+ 1083, 67, 99, 9, 32, 40, 41, 51,
+ 1034, 1083, 9, 32, 40, 41, 80, 112,
+ 1034, 1083, 65, 97, 82, 114, 65, 97,
+ 77, 109, 9, 32, 40, 41, 1034, 1083,
+ 84, 116, 82, 114, 9, 32, 40, 41,
+ 1034, 1083, 80, 82, 84, 112, 114, 116,
+ 9, 32, 40, 41, 1034, 1083, 83, 115,
+ 73, 105, 71, 103, 9, 32, 40, 41,
+ 1034, 1083, 9, 32, 40, 41, 1034, 1083,
+ 79, 80, 82, 83, 111, 112, 114, 115,
+ 65, 97, 9, 32, 40, 41, 1034, 1083,
+ 70, 102, 9, 32, 40, 41, 1034, 1083,
+ 86, 118, 9, 32, 40, 41, 1034, 1083,
+ 72, 104, 70, 102, 80, 112, 9, 32,
+ 40, 41, 1034, 1083, 76, 88, 89, 108,
+ 120, 121, 83, 115, 65, 97, 9, 32,
+ 40, 41, 1034, 1083, 84, 116, 9, 32,
+ 40, 41, 1034, 1083, 80, 112, 69, 101,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 42, 92, 95, 45, 57, 64,
+ 90, 97, 122, 32, 59, 9, 10, 40,
+ 41, 32, 59, 9, 10, 40, 41, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 65, 90, 97, 122, 9, 32, 40,
+ 41, 1034, 1083, 9, 32, 40, 41, 43,
+ 1034, 1083, 47, 57, 65, 90, 97, 122,
+ 1546, 1595, 1034, 896, 1151, 1034, 896, 1151,
+ 1034, 896, 1151, 43, 47, 57, 65, 90,
+ 97, 122, 1546, 1595, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 1034, 1083, 48, 57, 9, 32,
+ 40, 41, 45, 1034, 1083, 48, 57, 65,
+ 70, 97, 102, 9, 32, 40, 41, 1034,
+ 1083, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 65, 86, 97, 118, 48, 57, 65,
+ 86, 97, 118, 61, 48, 57, 65, 86,
+ 97, 118, 48, 57, 65, 86, 97, 118,
+ 61, 48, 57, 65, 86, 97, 118, 61,
+ 48, 57, 65, 86, 97, 118, 48, 57,
+ 65, 86, 97, 118, 61, 48, 57, 65,
+ 86, 97, 118, 32, 59, 9, 10, 40,
+ 41, 48, 57, 65, 86, 97, 118, 32,
+ 59, 9, 10, 40, 41, 61, 61, 61,
+ 61, 61, 1034, 896, 1151, 48, 57, 65,
+ 70, 97, 102, 9, 32, 40, 41, 1034,
+ 1083, 48, 57, 65, 70, 97, 102, 1034,
+ 896, 1151, 1034, 896, 1151, 1034, 896, 1151,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 45, 1034,
+ 1083, 48, 57, 65, 70, 97, 102, 32,
+ 59, 9, 10, 40, 41, 48, 57, 65,
+ 70, 97, 102, 32, 59, 9, 10, 40,
+ 41, 48, 57, 65, 70, 97, 102, 1034,
+ 896, 1151, 1034, 896, 1151, 1034, 896, 1151,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 65, 70, 97, 102, 48, 57,
+ 65, 70, 97, 102, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 65, 70, 97, 102, 1034, 896, 1151, 1034,
+ 896, 1151, 1034, 896, 1151, 1034, 896, 1151,
+ 48, 57, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 9, 32, 40, 41, 46, 1034,
+ 1083, 48, 57, 32, 46, 59, 9, 10,
+ 40, 41, 48, 57, 1034, 896, 1151, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 9, 32, 40, 41, 1034, 1083, 48,
+ 57, 65, 70, 97, 102, 48, 57, 65,
+ 70, 97, 102, 48, 57, 65, 70, 97,
+ 102, 48, 57, 65, 70, 97, 102, 58,
+ 48, 57, 65, 70, 97, 102, 48, 57,
+ 65, 70, 97, 102, 48, 57, 65, 70,
+ 97, 102, 48, 57, 65, 70, 97, 102,
+ 32, 58, 59, 9, 10, 40, 41, 1034,
+ 896, 1151, 48, 57, 65, 70, 97, 102,
+ 48, 57, 65, 70, 97, 102, 45, 48,
+ 57, 65, 70, 97, 102, 48, 57, 65,
+ 70, 97, 102, 32, 45, 59, 9, 10,
+ 40, 41, 48, 57, 65, 70, 97, 102,
+ 48, 57, 65, 70, 97, 102, 45, 48,
+ 57, 65, 70, 97, 102, 48, 57, 65,
+ 70, 97, 102, 32, 45, 59, 9, 10,
+ 40, 41, 9, 32, 36, 40, 41, 42,
+ 92, 95, 778, 827, 1034, 1083, 45, 57,
+ 64, 90, 97, 122, 9, 32, 36, 40,
+ 41, 42, 58, 92, 95, 1802, 1851, 2058,
+ 2107, 2314, 2363, 2570, 2619, -128, 8, 11,
+ 44, 45, 57, 60, 63, 64, 90, 91,
+ 96, 97, 122, 123, 127, 9, 32, 36,
+ 40, 41, 42, 65, 67, 68, 69, 72,
+ 73, 75, 76, 77, 78, 80, 82, 83,
+ 84, 92, 95, 97, 99, 100, 101, 104,
+ 105, 107, 108, 109, 110, 112, 114, 115,
+ 116, 778, 827, 1034, 1083, 45, 57, 64,
+ 90, 98, 122, 9, 32, 36, 40, 41,
+ 42, 65, 67, 68, 69, 72, 73, 75,
+ 76, 77, 78, 80, 82, 83, 84, 92,
+ 95, 97, 99, 100, 101, 104, 105, 107,
+ 108, 109, 110, 112, 114, 115, 116, 778,
+ 827, 1034, 1083, 45, 47, 48, 57, 64,
+ 90, 98, 122, 9, 32, 36, 40, 41,
+ 42, 92, 95, 778, 827, 1034, 1083, 45,
+ 57, 64, 90, 97, 122, 9, 32, 36,
+ 40, 41, 42, 65, 67, 68, 69, 72,
+ 73, 75, 76, 77, 78, 80, 82, 83,
+ 84, 92, 95, 97, 99, 100, 101, 104,
+ 105, 107, 108, 109, 110, 112, 114, 115,
+ 116, 778, 827, 1034, 1083, 45, 47, 48,
+ 57, 64, 90, 98, 122, 9, 32, 36,
+ 40, 41, 42, 92, 95, 778, 827, 1034,
+ 1083, 45, 57, 64, 90, 97, 122, 9,
+ 32, 36, 40, 41, 42, 58, 92, 95,
+ 1802, 1851, 2058, 2107, 2314, 2363, 2570, 2619,
+ -128, 8, 11, 44, 45, 57, 60, 63,
+ 64, 90, 91, 96, 97, 122, 123, 127,
+ 9, 32, 36, 40, 41, 42, 58, 65,
+ 67, 68, 69, 72, 73, 75, 76, 77,
+ 78, 80, 82, 83, 84, 92, 95, 97,
+ 99, 100, 101, 104, 105, 107, 108, 109,
+ 110, 112, 114, 115, 116, 1802, 1851, 2058,
+ 2107, 2314, 2363, 2570, 2619, -128, 8, 11,
+ 44, 45, 47, 48, 57, 60, 63, 64,
+ 90, 91, 96, 98, 122, 123, 127, 9,
+ 32, 36, 40, 41, 42, 58, 65, 67,
+ 68, 69, 72, 73, 75, 76, 77, 78,
+ 80, 82, 83, 84, 92, 95, 97, 99,
+ 100, 101, 104, 105, 107, 108, 109, 110,
+ 112, 114, 115, 116, 1802, 1851, 2058, 2107,
+ 2314, 2363, 2570, 2619, -128, 8, 11, 44,
+ 45, 47, 48, 57, 60, 63, 64, 90,
+ 91, 96, 98, 122, 123, 127, 32, 33,
+ 59, 92, 9, 10, 35, 39, 40, 41,
+ 42, 126, 9, 32, 40, 41, 42, 46,
+ 92, 95, 1034, 1083, 45, 57, 65, 90,
+ 97, 122, 9, 32, 40, 41, 43, 2058,
+ 2107, 2314, 2363, 2570, 2619, 47, 57, 65,
+ 90, 97, 122, 1034, 896, 1151, 9, 32,
+ 40, 41, 65, 67, 68, 69, 72, 73,
+ 75, 76, 77, 78, 80, 82, 83, 84,
+ 97, 99, 100, 101, 104, 105, 107, 108,
+ 109, 110, 112, 114, 115, 116, 2058, 2107,
+ 2314, 2363, 2570, 2619, 1034, 896, 1151, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 48, 57, 65, 70, 97, 102, 1034,
+ 896, 1151, 9, 32, 40, 41, 1034, 1083,
+ 48, 57, 65, 70, 97, 102, 9, 32,
+ 40, 41, 2058, 2107, 2314, 2363, 2570, 2619,
+ 48, 57, 65, 70, 97, 102, 1034, 896,
+ 1151, 1034, 896, 1151, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, -128, 8,
+ 11, 58, 60, 127, 1034, 896, 1151, 9,
+ 32, 40, 41, 2058, 2107, 2314, 2363, 2570,
+ 2619, 1034, 896, 1151, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 1034, 896, 1151, 9, 32, 40, 41, 2058,
+ 2107, 2314, 2363, 2570, 2619, 48, 57, 1034,
+ 896, 1151, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 48, 57, 1034, 896,
+ 1151, 9, 32, 33, 40, 41, 49, 50,
+ 2058, 2107, 2314, 2363, 2570, 2619, 1034, 896,
+ 1151, 9, 32, 40, 41, 2058, 2107, 2314,
+ 2363, 2570, 2619, 48, 57, 65, 70, 97,
+ 102, 1034, 896, 1151, 9, 32, 40, 41,
+ 2058, 2107, 2314, 2363, 2570, 2619, 48, 57,
+ 65, 70, 97, 102, 1034, 896, 1151, 4617,
+ 4640, 4648, 4649, 13578, 13627, 13834, 13883, 14346,
+ 14395, 14602, 14651, 14858, 14907, 5642, 5504, 5759,
+ 3081, 3104, 3112, 3113, 3115, 4106, 4155, 3119,
+ 3129, 3137, 3162, 3169, 3194, 4106, 3968, 4223,
+ 3115, 6153, 6176, 6184, 6185, 6409, 6432, 6440,
+ 6441, 6665, 6688, 6696, 6697, 9482, 9531, 9738,
+ 9787, 10250, 10299, 10506, 10555, 10762, 10811, 11274,
+ 11323, 11530, 11579, 11786, 11835, 12298, 12347, 12554,
+ 12603, 12810, 12859, 3119, 3129, 3137, 3162, 3169,
+ 3194, 7690, 8202, 8714, 7552, 7807, 8064, 8319,
+ 8576, 8831, 9, 32, 40, 41, 2058, 2107,
+ 2314, 2363, 2570, 2619, 48, 57, 65, 70,
+ 97, 102, 1034, 896, 1151, 0
+};
+
+static const char _zone_scanner_single_lengths[] = {
+ 0, 36, 16, 34, 16, 11, 8, 8,
+ 1, 1, 8, 1, 13, 2, 42, 18,
+ 36, 4, 2, 2, 10, 12, 2, 2,
+ 2, 10, 6, 2, 2, 2, 10, 4,
+ 2, 2, 10, 2, 2, 2, 10, 10,
+ 2, 2, 2, 1, 10, 1, 10, 2,
+ 2, 2, 2, 10, 4, 6, 34, 2,
+ 2, 2, 2, 2, 2, 2, 10, 4,
+ 2, 10, 10, 6, 1, 10, 1, 10,
+ 2, 10, 10, 4, 2, 2, 2, 10,
+ 10, 6, 2, 2, 2, 10, 2, 10,
+ 12, 2, 11, 12, 2, 2, 2, 2,
+ 10, 2, 2, 10, 6, 10, 2, 2,
+ 2, 10, 10, 8, 2, 10, 2, 10,
+ 2, 10, 2, 2, 2, 10, 6, 2,
+ 2, 10, 2, 10, 2, 2, 0, 10,
+ 1, 36, 4, 6, 34, 16, 6, 10,
+ 6, 1, 1, 6, 2, 2, 2, 2,
+ 2, 2, 2, 6, 34, 1, 16, 34,
+ 1, 6, 10, 6, 1, 16, 40, 18,
+ 13, 36, 2, 8, 8, 42, 12, 14,
+ 10, 10, 12, 12, 14, 12, 14, 10,
+ 14, 16, 14, 2, 14, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 8, 18,
+ 36, 2, 18, 42, 12, 14, 10, 10,
+ 12, 12, 14, 12, 14, 10, 14, 16,
+ 14, 9, 36, 12, 12, 10, 2, 2,
+ 10, 2, 2, 2, 10, 2, 10, 2,
+ 8, 8, 12, 10, 1, 12, 10, 12,
+ 8, 8, 10, 10, 12, 10, 12, 8,
+ 12, 14, 12, 2, 2, 10, 2, 1,
+ 1, 5, 3, 6, 5, 0, 0, 0,
+ 5, 2, 2, 2, 4, 0, 0, 0,
+ 4, 4, 2, 0, 0, 0, 4, 6,
+ 6, 18, 8, 1, 8, 10, 8, 1,
+ 6, 10, 1, 12, 8, 1, 3, 0,
+ 0, 0, 3, 8, 1, 6, 6, 8,
+ 12, 1, 12, 8, 1, 3, 0, 0,
+ 0, 3, 8, 2, 10, 1, 1, 1,
+ 1, 2, 2, 11, 1, 1, 10, 38,
+ 16, 2, 2, 10, 1, 4, 2, 2,
+ 10, 2, 2, 2, 10, 6, 2, 2,
+ 2, 10, 4, 2, 2, 10, 2, 2,
+ 2, 10, 10, 2, 2, 2, 1, 10,
+ 1, 10, 2, 2, 2, 2, 10, 2,
+ 2, 2, 2, 2, 2, 2, 10, 4,
+ 2, 10, 10, 6, 1, 10, 1, 10,
+ 2, 10, 10, 4, 2, 2, 2, 10,
+ 10, 6, 2, 2, 2, 10, 2, 10,
+ 12, 2, 11, 12, 2, 2, 2, 2,
+ 10, 2, 2, 10, 6, 10, 2, 2,
+ 2, 10, 10, 8, 2, 10, 2, 10,
+ 2, 10, 2, 2, 2, 10, 6, 2,
+ 2, 10, 2, 10, 2, 2, 0, 10,
+ 2, 2, 2, 10, 2, 10, 6, 6,
+ 6, 6, 0, 10, 1, 1, 1, 6,
+ 7, 8, 6, 0, 10, 1, 1, 6,
+ 1, 10, 2, 4, 2, 2, 3, 2,
+ 2, 2, 2, 1, 1, 2, 2, 2,
+ 1, 2, 2, 4, 1, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 1,
+ 2, 2, 2, 1, 1, 1, 2, 1,
+ 1, 2, 2, 2, 1, 1, 1, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 4, 2,
+ 2, 2, 2, 2, 2, 2, 2, 4,
+ 2, 1, 2, 2, 2, 3, 3, 2,
+ 2, 2, 2, 1, 1, 2, 2, 2,
+ 1, 2, 1, 1, 2, 1, 1, 2,
+ 12, 2, 2, 2, 2, 2, 2, 2,
+ 6, 2, 2, 2, 2, 2, 2, 4,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 4, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 1, 3, 3, 2, 3, 6, 9,
+ 6, 6, 6, 6, 16, 6, 16, 6,
+ 16, 6, 12, 2, 10, 2, 1, 6,
+ 10, 6, 1, 6, 10, 6, 1, 6,
+ 10, 6, 1, 1, 1, 2, 6, 6,
+ 2, 1, 3, 6, 9, 2, 1, 0,
+ 6, 9, 2, 1, 2, 10, 10, 1,
+ 1, 3, 0, 6, 8, 6, 8, 7,
+ 8, 6, 6, 6, 8, 6, 8, 7,
+ 8, 6, 7, 0, 12, 10, 12, 10,
+ 12, 10, 12, 10, 1, 11, 11, 1,
+ 11, 11, 10, 1, 11, 11, 10, 1,
+ 11, 11, 10, 1, 6, 1, 6, 6,
+ 1, 1, 1, 6, 1, 6, 6, 1,
+ 1, 0, 6, 6, 6, 6, 6, 9,
+ 2, 1, 1, 1, 0, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 9, 2,
+ 1, 1, 1, 1, 1, 0, 6, 6,
+ 6, 6, 6, 7, 2, 1, 1, 1,
+ 13, 2, 1, 1, 1, 0, 10, 1,
+ 1, 1, 1, 0, 6, 6, 6, 6,
+ 6, 6, 0, 10, 1, 1, 1, 1,
+ 0, 6, 6, 6, 6, 0, 10, 1,
+ 1, 1, 0, 6, 10, 6, 6, 6,
+ 7, 34, 7, 2, 1, 14, 1, 35,
+ 3, 1, 1, 6, 6, 6, 7, 35,
+ 1, 1, 6, 6, 6, 7, 35, 1,
+ 1, 6, 6, 6, 9, 34, 1, 1,
+ 1, 28, 12, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 9,
+ 6, 7, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 2, 2, 6, 2, 2,
+ 2, 6, 2, 6, 4, 2, 2, 6,
+ 2, 2, 2, 6, 6, 2, 2, 2,
+ 6, 4, 2, 2, 6, 2, 2, 2,
+ 6, 6, 2, 2, 2, 1, 6, 1,
+ 6, 2, 2, 2, 2, 6, 2, 2,
+ 2, 2, 2, 2, 2, 6, 4, 2,
+ 6, 6, 6, 1, 6, 1, 6, 2,
+ 6, 6, 4, 2, 2, 2, 6, 6,
+ 6, 2, 2, 2, 6, 2, 6, 8,
+ 2, 7, 8, 2, 2, 2, 2, 6,
+ 2, 2, 6, 6, 6, 2, 2, 2,
+ 6, 6, 8, 2, 6, 2, 6, 2,
+ 6, 2, 2, 2, 6, 6, 2, 2,
+ 6, 2, 6, 2, 2, 0, 6, 3,
+ 2, 2, 0, 6, 6, 6, 6, 6,
+ 7, 2, 1, 1, 1, 1, 2, 0,
+ 6, 6, 6, 6, 6, 7, 6, 6,
+ 0, 1, 0, 1, 1, 0, 1, 2,
+ 2, 1, 1, 1, 1, 1, 1, 0,
+ 6, 1, 1, 1, 0, 6, 6, 6,
+ 6, 6, 7, 2, 0, 2, 1, 1,
+ 1, 0, 6, 6, 6, 6, 6, 6,
+ 0, 10, 1, 1, 1, 1, 0, 6,
+ 7, 3, 1, 0, 6, 6, 0, 0,
+ 0, 1, 0, 0, 0, 0, 3, 1,
+ 0, 0, 1, 0, 0, 3, 0, 0,
+ 1, 0, 0, 3, 12, 17, 40, 40,
+ 12, 40, 12, 17, 45, 45, 0, 0,
+ 0, 4, 0, 0, 0, 10, 0, 11,
+ 1, 0, 38, 1, 0, 10, 1, 6,
+ 0, 10, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 10, 1, 0,
+ 0, 10, 1, 10, 1, 10, 1, 10,
+ 1, 0, 0, 0, 0, 13, 1, 0,
+ 10, 1, 0, 10, 1, 0, 14, 1,
+ 7, 1, 35, 3, 0, 0, 0, 0,
+ 0, 0, 0, 10, 1, 0, 0, 0,
+ 0
+};
+
+static const char _zone_scanner_range_lengths[] = {
+ 0, 1, 1, 0, 0, 3, 0, 0,
+ 0, 0, 0, 1, 3, 2, 4, 1,
+ 0, 0, 0, 0, 0, 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, 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, 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, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1,
+ 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 4, 0,
+ 3, 1, 2, 3, 3, 4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 2, 0, 1,
+ 1, 2, 0, 4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 1, 1, 1, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 3, 3, 2, 2, 1, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 2, 0, 2, 0,
+ 0, 3, 2, 5, 5, 1, 1, 1,
+ 5, 2, 2, 2, 4, 1, 1, 1,
+ 4, 1, 2, 1, 1, 1, 1, 0,
+ 1, 1, 0, 0, 1, 1, 1, 1,
+ 0, 3, 0, 3, 0, 0, 3, 1,
+ 1, 1, 3, 0, 1, 0, 3, 0,
+ 3, 0, 3, 0, 0, 3, 1, 1,
+ 1, 3, 0, 2, 3, 1, 1, 3,
+ 3, 3, 3, 3, 1, 0, 0, 0,
+ 0, 0, 0, 0, 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, 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, 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, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 1,
+ 1, 3, 3, 3, 1, 1, 1, 0,
+ 1, 1, 3, 3, 3, 1, 1, 1,
+ 1, 1, 3, 0, 2, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 2, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 2, 0, 0, 2,
+ 1, 3, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 2, 0, 0, 2, 0, 0, 0,
+ 2, 0, 0, 2, 0, 0, 2, 0,
+ 0, 2, 0, 0, 0, 2, 0, 0,
+ 2, 1, 3, 3, 2, 3, 0, 3,
+ 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 3, 3, 1, 3, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 0, 3,
+ 2, 1, 3, 0, 3, 2, 1, 1,
+ 1, 3, 2, 1, 2, 0, 3, 1,
+ 3, 5, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 0, 1, 1, 1, 0, 1,
+ 1, 1, 0, 1, 0, 1, 1, 1,
+ 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3,
+ 2, 1, 1, 1, 1, 1, 1, 1,
+ 3, 0, 3, 0, 3, 0, 3, 2,
+ 1, 1, 1, 1, 1, 3, 0, 1,
+ 1, 3, 0, 3, 0, 1, 1, 1,
+ 0, 0, 0, 1, 1, 1, 1, 1,
+ 0, 3, 3, 1, 1, 3, 0, 1,
+ 1, 3, 3, 3, 1, 1, 1, 1,
+ 1, 1, 1, 1, 3, 3, 3, 1,
+ 1, 1, 1, 1, 0, 0, 1, 1,
+ 0, 0, 3, 0, 1, 0, 1, 3,
+ 3, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 0, 1, 1, 3, 3, 1,
+ 1, 0, 1, 1, 3, 0, 1, 1,
+ 1, 0, 0, 3, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3,
+ 0, 3, 0, 1, 1, 1, 1, 1,
+ 1, 1, 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, 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, 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, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 3,
+ 2, 2, 1, 1, 1, 1, 3, 0,
+ 3, 0, 1, 1, 1, 3, 0, 1,
+ 1, 1, 1, 1, 1, 3, 0, 3,
+ 3, 3, 3, 3, 3, 3, 3, 5,
+ 2, 0, 0, 0, 0, 0, 1, 3,
+ 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 3, 2, 3, 5, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 3,
+ 3, 3, 1, 1, 1, 1, 1, 1,
+ 1, 3, 1, 1, 1, 3, 3, 3,
+ 3, 0, 3, 3, 3, 3, 2, 1,
+ 3, 3, 0, 3, 3, 2, 3, 3,
+ 0, 3, 3, 2, 3, 8, 3, 4,
+ 3, 4, 3, 8, 9, 9, 0, 0,
+ 0, 4, 0, 0, 0, 3, 0, 3,
+ 1, 0, 0, 1, 0, 3, 1, 3,
+ 0, 3, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 1, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 1, 0,
+ 3, 1, 0, 3, 1, 0, 0, 1,
+ 3, 1, 3, 3, 0, 0, 0, 0,
+ 0, 0, 0, 3, 1, 0, 0, 0,
+ 0
+};
+
+static const short _zone_scanner_index_offsets[] = {
+ 0, 0, 38, 56, 91, 108, 123, 132,
+ 141, 143, 145, 154, 157, 174, 179, 226,
+ 246, 283, 288, 291, 294, 305, 319, 322,
+ 325, 328, 339, 346, 349, 352, 355, 366,
+ 371, 374, 377, 388, 391, 394, 397, 408,
+ 419, 422, 425, 428, 430, 441, 443, 454,
+ 457, 460, 463, 466, 477, 482, 489, 524,
+ 527, 530, 533, 536, 539, 542, 545, 556,
+ 561, 564, 575, 586, 593, 595, 606, 608,
+ 619, 622, 633, 644, 649, 652, 655, 658,
+ 669, 680, 687, 690, 693, 696, 707, 710,
+ 721, 734, 737, 749, 762, 765, 768, 771,
+ 774, 785, 788, 791, 802, 809, 820, 823,
+ 826, 829, 840, 851, 860, 863, 874, 877,
+ 888, 891, 902, 905, 908, 911, 922, 929,
+ 932, 935, 946, 949, 960, 963, 966, 968,
+ 980, 983, 1021, 1026, 1033, 1069, 1087, 1095,
+ 1107, 1115, 1118, 1120, 1127, 1130, 1133, 1136,
+ 1139, 1142, 1145, 1150, 1157, 1193, 1196, 1214,
+ 1250, 1253, 1261, 1273, 1281, 1284, 1301, 1346,
+ 1365, 1382, 1420, 1425, 1437, 1449, 1496, 1509,
+ 1524, 1535, 1546, 1559, 1572, 1587, 1600, 1615,
+ 1626, 1641, 1658, 1673, 1678, 1693, 1696, 1699,
+ 1702, 1705, 1708, 1713, 1716, 1719, 1724, 1733,
+ 1753, 1791, 1796, 1815, 1862, 1875, 1890, 1901,
+ 1912, 1925, 1938, 1953, 1966, 1981, 1992, 2007,
+ 2024, 2039, 2052, 2090, 2104, 2118, 2131, 2134,
+ 2137, 2148, 2151, 2154, 2157, 2168, 2171, 2182,
+ 2187, 2199, 2211, 2226, 2239, 2242, 2256, 2267,
+ 2280, 2289, 2298, 2309, 2320, 2333, 2344, 2357,
+ 2366, 2379, 2394, 2407, 2412, 2417, 2428, 2433,
+ 2435, 2437, 2446, 2452, 2464, 2475, 2477, 2479,
+ 2481, 2492, 2497, 2502, 2507, 2516, 2518, 2520,
+ 2522, 2531, 2537, 2542, 2544, 2546, 2548, 2554,
+ 2561, 2569, 2589, 2598, 2600, 2610, 2622, 2632,
+ 2635, 2642, 2656, 2658, 2674, 2683, 2685, 2692,
+ 2694, 2696, 2698, 2705, 2714, 2717, 2724, 2734,
+ 2743, 2759, 2761, 2777, 2786, 2788, 2795, 2797,
+ 2799, 2801, 2808, 2817, 2822, 2836, 2839, 2842,
+ 2847, 2852, 2858, 2864, 2879, 2882, 2884, 2895,
+ 2934, 2951, 2954, 2957, 2968, 2971, 2976, 2979,
+ 2982, 2993, 2996, 2999, 3002, 3013, 3020, 3023,
+ 3026, 3029, 3040, 3045, 3048, 3051, 3062, 3065,
+ 3068, 3071, 3082, 3093, 3096, 3099, 3102, 3104,
+ 3115, 3117, 3128, 3131, 3134, 3137, 3140, 3151,
+ 3154, 3157, 3160, 3163, 3166, 3169, 3172, 3183,
+ 3188, 3191, 3202, 3213, 3220, 3222, 3233, 3235,
+ 3246, 3249, 3260, 3271, 3276, 3279, 3282, 3285,
+ 3296, 3307, 3314, 3317, 3320, 3323, 3334, 3337,
+ 3348, 3361, 3364, 3376, 3389, 3392, 3395, 3398,
+ 3401, 3412, 3415, 3418, 3429, 3436, 3447, 3450,
+ 3453, 3456, 3467, 3478, 3487, 3490, 3501, 3504,
+ 3515, 3518, 3529, 3532, 3535, 3538, 3549, 3556,
+ 3559, 3562, 3573, 3576, 3587, 3590, 3593, 3595,
+ 3607, 3610, 3613, 3616, 3627, 3630, 3641, 3648,
+ 3656, 3664, 3674, 3678, 3692, 3695, 3698, 3701,
+ 3708, 3717, 3727, 3737, 3741, 3755, 3758, 3761,
+ 3769, 3772, 3784, 3790, 3795, 3800, 3803, 3809,
+ 3812, 3815, 3818, 3821, 3823, 3825, 3828, 3831,
+ 3834, 3836, 3841, 3844, 3849, 3851, 3854, 3857,
+ 3860, 3863, 3868, 3871, 3874, 3877, 3880, 3882,
+ 3884, 3887, 3890, 3893, 3895, 3897, 3899, 3904,
+ 3906, 3908, 3911, 3914, 3917, 3919, 3921, 3923,
+ 3928, 3931, 3934, 3937, 3940, 3943, 3946, 3949,
+ 3954, 3957, 3960, 3963, 3966, 3969, 3972, 3977,
+ 3980, 3983, 3988, 3991, 3994, 3999, 4002, 4005,
+ 4010, 4013, 4015, 4020, 4023, 4026, 4030, 4036,
+ 4039, 4042, 4045, 4048, 4050, 4052, 4055, 4058,
+ 4061, 4063, 4068, 4070, 4072, 4077, 4079, 4081,
+ 4086, 4100, 4106, 4109, 4112, 4115, 4118, 4121,
+ 4126, 4133, 4136, 4139, 4142, 4145, 4148, 4153,
+ 4158, 4161, 4166, 4169, 4172, 4177, 4180, 4183,
+ 4186, 4191, 4194, 4197, 4202, 4207, 4210, 4215,
+ 4218, 4221, 4226, 4229, 4232, 4235, 4240, 4243,
+ 4246, 4251, 4254, 4261, 4268, 4273, 4280, 4287,
+ 4300, 4307, 4315, 4323, 4331, 4349, 4357, 4375,
+ 4383, 4401, 4409, 4425, 4431, 4443, 4449, 4452,
+ 4460, 4472, 4480, 4483, 4491, 4503, 4511, 4514,
+ 4522, 4534, 4542, 4545, 4548, 4551, 4556, 4563,
+ 4573, 4578, 4581, 4588, 4595, 4608, 4613, 4616,
+ 4618, 4626, 4639, 4644, 4647, 4652, 4663, 4677,
+ 4680, 4685, 4694, 4696, 4704, 4714, 4722, 4732,
+ 4741, 4750, 4757, 4765, 4773, 4783, 4791, 4801,
+ 4810, 4819, 4826, 4835, 4837, 4851, 4863, 4877,
+ 4889, 4903, 4915, 4929, 4940, 4943, 4956, 4969,
+ 4972, 4985, 4998, 5009, 5012, 5025, 5038, 5049,
+ 5052, 5065, 5078, 5089, 5092, 5099, 5102, 5110,
+ 5118, 5121, 5124, 5127, 5134, 5137, 5145, 5153,
+ 5156, 5159, 5161, 5169, 5177, 5185, 5193, 5201,
+ 5214, 5219, 5222, 5225, 5228, 5230, 5238, 5246,
+ 5254, 5264, 5271, 5281, 5288, 5298, 5305, 5318,
+ 5323, 5326, 5329, 5332, 5335, 5338, 5342, 5349,
+ 5357, 5365, 5375, 5382, 5393, 5396, 5399, 5402,
+ 5405, 5419, 5422, 5424, 5427, 5430, 5432, 5444,
+ 5447, 5449, 5454, 5459, 5461, 5469, 5479, 5486,
+ 5494, 5502, 5512, 5516, 5530, 5533, 5536, 5539,
+ 5542, 5544, 5552, 5560, 5568, 5578, 5582, 5596,
+ 5599, 5602, 5605, 5607, 5615, 5626, 5633, 5641,
+ 5649, 5657, 5692, 5703, 5706, 5709, 5724, 5727,
+ 5766, 5773, 5776, 5779, 5786, 5794, 5802, 5811,
+ 5848, 5851, 5854, 5861, 5869, 5877, 5888, 5927,
+ 5930, 5933, 5940, 5948, 5956, 5969, 6004, 6007,
+ 6010, 6013, 6042, 6055, 6065, 6072, 6080, 6088,
+ 6096, 6104, 6112, 6120, 6128, 6136, 6144, 6152,
+ 6165, 6172, 6183, 6186, 6189, 6192, 6195, 6198,
+ 6201, 6204, 6207, 6210, 6213, 6216, 6223, 6226,
+ 6229, 6232, 6239, 6242, 6249, 6254, 6257, 6260,
+ 6267, 6270, 6273, 6276, 6283, 6290, 6293, 6296,
+ 6299, 6306, 6311, 6314, 6317, 6324, 6327, 6330,
+ 6333, 6340, 6347, 6350, 6353, 6356, 6358, 6365,
+ 6367, 6374, 6377, 6380, 6383, 6386, 6393, 6396,
+ 6399, 6402, 6405, 6408, 6411, 6414, 6421, 6426,
+ 6429, 6436, 6443, 6450, 6452, 6459, 6461, 6468,
+ 6471, 6478, 6485, 6490, 6493, 6496, 6499, 6506,
+ 6513, 6520, 6523, 6526, 6529, 6536, 6539, 6546,
+ 6555, 6558, 6566, 6575, 6578, 6581, 6584, 6587,
+ 6594, 6597, 6600, 6607, 6614, 6621, 6624, 6627,
+ 6630, 6637, 6644, 6653, 6656, 6663, 6666, 6673,
+ 6676, 6683, 6686, 6689, 6692, 6699, 6706, 6709,
+ 6712, 6719, 6722, 6729, 6732, 6735, 6737, 6745,
+ 6752, 6757, 6762, 6764, 6772, 6780, 6788, 6798,
+ 6805, 6816, 6819, 6822, 6825, 6828, 6833, 6836,
+ 6838, 6846, 6854, 6862, 6870, 6878, 6889, 6896,
+ 6906, 6910, 6915, 6919, 6924, 6929, 6933, 6938,
+ 6946, 6951, 6953, 6955, 6957, 6959, 6961, 6964,
+ 6968, 6978, 6981, 6984, 6987, 6989, 6997, 7005,
+ 7013, 7021, 7029, 7040, 7045, 7049, 7057, 7060,
+ 7063, 7066, 7068, 7076, 7084, 7092, 7100, 7108,
+ 7118, 7122, 7136, 7139, 7142, 7145, 7148, 7150,
+ 7158, 7167, 7174, 7177, 7179, 7187, 7197, 7201,
+ 7205, 7209, 7211, 7215, 7219, 7223, 7227, 7233,
+ 7236, 7240, 7244, 7246, 7250, 7254, 7260, 7264,
+ 7268, 7270, 7274, 7278, 7284, 7300, 7326, 7370,
+ 7415, 7431, 7476, 7492, 7518, 7573, 7628, 7629,
+ 7630, 7631, 7640, 7641, 7642, 7643, 7657, 7658,
+ 7673, 7676, 7677, 7716, 7719, 7720, 7734, 7737,
+ 7747, 7748, 7762, 7765, 7768, 7769, 7770, 7771,
+ 7772, 7773, 7774, 7775, 7776, 7777, 7791, 7794,
+ 7795, 7796, 7807, 7810, 7822, 7825, 7837, 7840,
+ 7852, 7855, 7856, 7857, 7858, 7859, 7873, 7876,
+ 7877, 7891, 7894, 7895, 7909, 7912, 7913, 7928,
+ 7931, 7942, 7945, 7984, 7991, 7992, 7993, 7994,
+ 7995, 7996, 7997, 7998, 8012, 8015, 8016, 8017,
+ 8018
+};
+
+static const short _zone_scanner_indicies[] = {
+ 1, 1, 2, 3, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 4, 0, 24, 24,
+ 25, 26, 28, 29, 30, 31, 32, 28,
+ 29, 30, 31, 32, 33, 34, 27, 23,
+ 36, 36, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50,
+ 51, 52, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52,
+ 53, 54, 35, 56, 56, 57, 58, 59,
+ 60, 61, 59, 60, 61, 62, 63, 64,
+ 64, 65, 66, 55, 68, 68, 70, 71,
+ 72, 73, 74, 75, 75, 76, 77, 67,
+ 67, 67, 69, 79, 79, 80, 81, 82,
+ 83, 82, 83, 78, 85, 85, 86, 87,
+ 88, 89, 88, 89, 84, 88, 89, 91,
+ 90, 85, 85, 86, 87, 88, 89, 88,
+ 89, 78, 73, 74, 69, 92, 92, 93,
+ 94, 72, 88, 89, 88, 95, 96, 97,
+ 88, 98, 67, 67, 67, 78, 88, 99,
+ 89, 95, 78, 100, 100, 102, 103, 67,
+ 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 115, 116, 117, 118, 72, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 19, 20, 119,
+ 120, 121, 122, 123, 124, 67, 67, 104,
+ 67, 101, 126, 126, 127, 128, 28, 29,
+ 30, 31, 32, 28, 29, 30, 31, 32,
+ 82, 83, 129, 130, 27, 125, 132, 132,
+ 133, 134, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52,
+ 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, 51, 52, 88, 89,
+ 135, 136, 131, 137, 138, 137, 138, 35,
+ 139, 139, 35, 140, 140, 35, 141, 141,
+ 142, 143, 144, 145, 146, 146, 147, 148,
+ 55, 85, 88, 85, 86, 87, 89, 149,
+ 88, 149, 150, 151, 95, 74, 78, 152,
+ 152, 35, 153, 153, 35, 154, 154, 35,
+ 155, 155, 156, 157, 158, 159, 160, 160,
+ 161, 162, 55, 163, 164, 165, 163, 164,
+ 165, 35, 166, 166, 35, 167, 167, 35,
+ 168, 168, 35, 169, 169, 170, 171, 172,
+ 173, 174, 174, 175, 176, 55, 177, 178,
+ 177, 178, 35, 179, 179, 35, 180, 180,
+ 35, 181, 181, 182, 183, 184, 185, 186,
+ 186, 187, 188, 55, 189, 189, 35, 190,
+ 190, 35, 191, 191, 35, 192, 192, 193,
+ 194, 195, 196, 197, 197, 198, 199, 55,
+ 200, 200, 201, 202, 203, 204, 205, 205,
+ 206, 207, 55, 208, 208, 35, 209, 209,
+ 35, 210, 211, 35, 212, 35, 213, 213,
+ 214, 215, 216, 217, 218, 218, 219, 220,
+ 55, 221, 35, 222, 222, 223, 224, 225,
+ 226, 227, 227, 228, 229, 55, 230, 230,
+ 35, 231, 231, 35, 232, 232, 35, 233,
+ 233, 35, 234, 234, 235, 236, 237, 238,
+ 239, 239, 240, 241, 55, 242, 243, 242,
+ 243, 35, 244, 244, 245, 246, 247, 248,
+ 35, 249, 249, 250, 251, 252, 253, 254,
+ 255, 256, 257, 258, 259, 260, 261, 262,
+ 263, 264, 265, 252, 253, 254, 255, 256,
+ 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 35, 243, 243, 35, 268,
+ 268, 35, 269, 269, 35, 270, 270, 35,
+ 271, 271, 35, 272, 272, 35, 273, 273,
+ 35, 274, 274, 275, 276, 277, 278, 279,
+ 279, 280, 281, 55, 282, 283, 282, 283,
+ 35, 284, 284, 35, 285, 285, 286, 287,
+ 288, 289, 290, 290, 291, 292, 55, 293,
+ 293, 294, 295, 296, 297, 298, 298, 299,
+ 300, 55, 301, 302, 303, 304, 303, 304,
+ 35, 305, 35, 306, 306, 307, 308, 309,
+ 310, 311, 311, 312, 313, 55, 314, 35,
+ 315, 315, 316, 317, 318, 319, 320, 320,
+ 321, 322, 55, 323, 323, 35, 324, 324,
+ 325, 326, 327, 328, 329, 329, 330, 331,
+ 55, 332, 332, 333, 334, 335, 336, 337,
+ 337, 338, 339, 55, 340, 341, 340, 341,
+ 35, 342, 342, 35, 343, 343, 35, 344,
+ 344, 35, 345, 345, 346, 347, 348, 349,
+ 350, 350, 351, 352, 55, 353, 353, 354,
+ 355, 356, 357, 358, 358, 359, 360, 55,
+ 361, 362, 363, 361, 362, 363, 35, 364,
+ 364, 35, 365, 365, 35, 366, 366, 35,
+ 367, 367, 368, 369, 370, 371, 372, 372,
+ 373, 374, 55, 375, 375, 35, 376, 376,
+ 377, 378, 379, 380, 381, 381, 382, 383,
+ 55, 384, 384, 385, 386, 387, 387, 388,
+ 389, 390, 390, 391, 392, 55, 393, 393,
+ 35, 394, 394, 395, 396, 397, 398, 399,
+ 400, 400, 401, 402, 55, 403, 403, 404,
+ 405, 406, 406, 407, 408, 409, 409, 410,
+ 411, 55, 412, 412, 35, 413, 413, 35,
+ 414, 414, 35, 415, 415, 35, 416, 416,
+ 417, 418, 419, 420, 421, 421, 422, 423,
+ 55, 424, 424, 35, 425, 425, 35, 426,
+ 426, 427, 428, 429, 430, 431, 431, 432,
+ 433, 55, 434, 435, 436, 434, 435, 436,
+ 35, 437, 437, 438, 439, 440, 441, 442,
+ 442, 443, 444, 55, 445, 445, 35, 446,
+ 446, 35, 447, 447, 35, 448, 448, 449,
+ 450, 451, 452, 453, 453, 454, 455, 55,
+ 456, 456, 457, 458, 459, 460, 461, 461,
+ 462, 463, 55, 464, 465, 466, 467, 464,
+ 465, 466, 467, 35, 468, 468, 35, 469,
+ 469, 470, 471, 472, 473, 474, 474, 475,
+ 476, 55, 477, 477, 35, 478, 478, 479,
+ 480, 481, 482, 483, 483, 484, 485, 55,
+ 486, 486, 35, 487, 487, 488, 489, 490,
+ 491, 492, 492, 493, 494, 55, 495, 495,
+ 35, 496, 496, 35, 497, 497, 35, 498,
+ 498, 499, 500, 501, 502, 503, 503, 504,
+ 505, 55, 506, 507, 508, 506, 507, 508,
+ 35, 509, 509, 35, 510, 510, 35, 511,
+ 511, 512, 513, 514, 515, 516, 516, 517,
+ 518, 55, 519, 519, 35, 520, 520, 521,
+ 522, 523, 524, 525, 525, 526, 527, 55,
+ 528, 528, 35, 529, 529, 35, 531, 530,
+ 533, 533, 534, 535, 537, 538, 539, 539,
+ 540, 541, 536, 532, 266, 267, 35, 542,
+ 542, 543, 544, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 545, 546, 4, 0, 547, 243, 547,
+ 243, 35, 548, 548, 549, 550, 551, 552,
+ 35, 553, 553, 554, 555, 557, 558, 559,
+ 560, 561, 562, 563, 564, 565, 566, 567,
+ 568, 569, 570, 557, 558, 559, 560, 561,
+ 562, 563, 564, 565, 566, 567, 568, 569,
+ 570, 571, 572, 556, 530, 573, 573, 574,
+ 575, 577, 578, 579, 580, 581, 577, 578,
+ 579, 580, 581, 582, 583, 576, 23, 573,
+ 573, 574, 575, 582, 583, 584, 23, 586,
+ 587, 588, 589, 590, 586, 587, 588, 589,
+ 590, 585, 23, 591, 591, 592, 593, 595,
+ 596, 594, 23, 571, 572, 35, 19, 20,
+ 598, 599, 600, 598, 599, 600, 597, 601,
+ 601, 597, 602, 602, 597, 603, 603, 597,
+ 604, 604, 597, 605, 605, 597, 606, 606,
+ 597, 607, 607, 607, 607, 597, 609, 609,
+ 610, 611, 612, 613, 608, 614, 614, 615,
+ 616, 5, 6, 7, 8, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 617, 618, 4,
+ 530, 617, 618, 619, 621, 621, 622, 623,
+ 28, 29, 30, 31, 32, 28, 29, 30,
+ 31, 32, 624, 625, 27, 620, 626, 626,
+ 627, 628, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 629, 630,
+ 4, 530, 629, 630, 35, 24, 24, 25,
+ 26, 33, 34, 631, 23, 633, 634, 635,
+ 636, 637, 633, 634, 635, 636, 637, 632,
+ 23, 638, 638, 639, 640, 642, 643, 641,
+ 23, 53, 54, 35, 645, 645, 646, 647,
+ 59, 60, 61, 59, 60, 61, 648, 649,
+ 64, 64, 650, 651, 644, 652, 652, 653,
+ 654, 67, 105, 106, 107, 108, 109, 110,
+ 111, 112, 113, 114, 115, 116, 117, 118,
+ 72, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 655,
+ 656, 75, 75, 657, 658, 67, 67, 104,
+ 67, 532, 660, 660, 661, 662, 59, 60,
+ 61, 59, 60, 61, 82, 83, 663, 664,
+ 665, 666, 667, 668, 659, 669, 669, 670,
+ 671, 72, 88, 89, 99, 95, 96, 97,
+ 672, 98, 67, 67, 67, 78, 673, 673,
+ 674, 675, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 88, 89,
+ 676, 677, 4, 0, 88, 676, 89, 677,
+ 84, 678, 678, 679, 680, 88, 89, 88,
+ 89, 89, 89, 89, 78, 678, 678, 679,
+ 680, 88, 89, 88, 89, 89, 89, 89,
+ 84, 681, 681, 682, 683, 67, 105, 106,
+ 107, 108, 109, 110, 111, 112, 113, 114,
+ 115, 116, 117, 118, 72, 105, 106, 107,
+ 108, 109, 110, 111, 112, 113, 114, 115,
+ 116, 117, 118, 88, 89, 676, 684, 96,
+ 97, 676, 685, 67, 67, 104, 67, 101,
+ 79, 79, 80, 81, 137, 138, 137, 138,
+ 82, 83, 82, 83, 659, 79, 79, 80,
+ 81, 163, 164, 165, 163, 164, 165, 82,
+ 83, 82, 83, 659, 79, 79, 80, 81,
+ 208, 208, 82, 83, 82, 83, 659, 79,
+ 79, 80, 81, 230, 230, 82, 83, 82,
+ 83, 659, 79, 79, 80, 81, 547, 243,
+ 547, 243, 82, 83, 82, 83, 659, 79,
+ 79, 80, 81, 282, 283, 282, 283, 82,
+ 83, 82, 83, 659, 79, 79, 80, 81,
+ 301, 302, 303, 304, 303, 304, 82, 83,
+ 82, 83, 659, 79, 79, 80, 81, 340,
+ 341, 340, 341, 82, 83, 82, 83, 659,
+ 79, 79, 80, 81, 361, 362, 363, 361,
+ 362, 363, 82, 83, 82, 83, 659, 79,
+ 79, 80, 81, 424, 424, 82, 83, 82,
+ 83, 659, 79, 79, 80, 81, 434, 435,
+ 436, 434, 435, 436, 82, 83, 82, 83,
+ 659, 79, 79, 80, 81, 464, 465, 466,
+ 467, 464, 465, 466, 467, 82, 83, 82,
+ 83, 659, 79, 79, 80, 81, 506, 507,
+ 508, 506, 507, 508, 82, 83, 82, 83,
+ 659, 88, 686, 89, 684, 78, 79, 79,
+ 80, 81, 598, 599, 600, 598, 599, 600,
+ 82, 83, 82, 83, 687, 688, 688, 597,
+ 689, 689, 597, 690, 690, 597, 691, 691,
+ 597, 692, 692, 597, 693, 693, 693, 693,
+ 597, 694, 694, 597, 695, 695, 597, 696,
+ 696, 696, 696, 597, 698, 698, 699, 700,
+ 82, 83, 701, 702, 697, 704, 704, 705,
+ 706, 28, 29, 30, 31, 32, 28, 29,
+ 30, 31, 32, 82, 83, 707, 708, 27,
+ 703, 709, 709, 710, 711, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 88, 89, 712, 713, 4, 0, 88,
+ 712, 89, 713, 131, 715, 715, 716, 717,
+ 59, 60, 61, 59, 60, 61, 82, 83,
+ 718, 719, 665, 666, 720, 721, 714, 722,
+ 722, 723, 724, 67, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 115, 116,
+ 117, 118, 72, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 88, 89, 686, 684, 96, 97, 725,
+ 685, 67, 67, 104, 67, 101, 698, 698,
+ 699, 700, 137, 138, 137, 138, 82, 83,
+ 701, 702, 714, 698, 698, 699, 700, 163,
+ 164, 165, 163, 164, 165, 82, 83, 701,
+ 702, 714, 698, 698, 699, 700, 208, 208,
+ 82, 83, 701, 702, 714, 698, 698, 699,
+ 700, 230, 230, 82, 83, 701, 702, 714,
+ 698, 698, 699, 700, 547, 243, 547, 243,
+ 82, 83, 701, 702, 714, 698, 698, 699,
+ 700, 282, 283, 282, 283, 82, 83, 701,
+ 702, 714, 698, 698, 699, 700, 301, 302,
+ 303, 304, 303, 304, 82, 83, 701, 702,
+ 714, 698, 698, 699, 700, 340, 341, 340,
+ 341, 82, 83, 701, 702, 714, 698, 698,
+ 699, 700, 361, 362, 363, 361, 362, 363,
+ 82, 83, 701, 702, 714, 698, 698, 699,
+ 700, 424, 424, 82, 83, 701, 702, 714,
+ 698, 698, 699, 700, 434, 435, 436, 434,
+ 435, 436, 82, 83, 701, 702, 714, 698,
+ 698, 699, 700, 464, 465, 466, 467, 464,
+ 465, 466, 467, 82, 83, 701, 702, 714,
+ 698, 698, 699, 700, 506, 507, 508, 506,
+ 507, 508, 82, 83, 701, 702, 714, 726,
+ 726, 91, 728, 729, 90, 90, 730, 731,
+ 90, 90, 90, 727, 732, 732, 733, 734,
+ 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 82, 83, 735, 736,
+ 4, 101, 79, 82, 79, 80, 81, 83,
+ 737, 735, 737, 738, 739, 736, 618, 78,
+ 85, 88, 85, 86, 87, 89, 740, 676,
+ 740, 741, 742, 677, 618, 84, 678, 88,
+ 678, 679, 680, 743, 676, 743, 744, 745,
+ 89, 684, 78, 746, 746, 35, 747, 747,
+ 35, 748, 748, 749, 750, 751, 752, 753,
+ 753, 754, 755, 55, 756, 756, 35, 757,
+ 757, 35, 758, 758, 35, 759, 759, 760,
+ 761, 762, 763, 764, 764, 765, 766, 55,
+ 767, 767, 35, 768, 768, 769, 770, 771,
+ 772, 773, 773, 774, 775, 55, 19, 119,
+ 20, 120, 78, 776, 776, 777, 778, 88,
+ 89, 88, 89, 20, 20, 20, 78, 776,
+ 776, 777, 778, 88, 89, 88, 89, 20,
+ 20, 20, 84, 776, 88, 776, 777, 778,
+ 89, 779, 676, 779, 780, 781, 684, 20,
+ 120, 78, 678, 88, 678, 679, 680, 782,
+ 88, 782, 783, 784, 89, 95, 78, 655,
+ 656, 69, 85, 88, 85, 86, 87, 89,
+ 785, 676, 785, 786, 787, 684, 656, 78,
+ 609, 609, 610, 611, 137, 138, 137, 138,
+ 612, 613, 788, 609, 609, 610, 611, 163,
+ 164, 165, 163, 164, 165, 612, 613, 788,
+ 609, 609, 610, 611, 208, 208, 612, 613,
+ 788, 609, 609, 610, 611, 230, 230, 612,
+ 613, 788, 609, 609, 610, 611, 547, 243,
+ 547, 243, 612, 613, 788, 609, 609, 610,
+ 611, 282, 283, 282, 283, 612, 613, 788,
+ 609, 609, 610, 611, 301, 302, 303, 304,
+ 303, 304, 612, 613, 788, 609, 609, 610,
+ 611, 340, 341, 340, 341, 612, 613, 788,
+ 609, 609, 610, 611, 361, 362, 363, 361,
+ 362, 363, 612, 613, 788, 609, 609, 610,
+ 611, 424, 424, 612, 613, 788, 609, 609,
+ 610, 611, 434, 435, 436, 434, 435, 436,
+ 612, 613, 788, 609, 609, 610, 611, 464,
+ 465, 466, 467, 464, 465, 466, 467, 612,
+ 613, 788, 609, 609, 610, 611, 506, 507,
+ 508, 506, 507, 508, 612, 613, 788, 19,
+ 21, 20, 22, 84, 19, 545, 20, 546,
+ 131, 609, 609, 610, 611, 242, 243, 242,
+ 243, 612, 613, 788, 88, 135, 89, 136,
+ 131, 790, 789, 792, 791, 794, 796, 797,
+ 798, 795, 795, 795, 795, 793, 799, 800,
+ 799, 799, 799, 793, 801, 802, 803, 801,
+ 804, 803, 801, 801, 803, 803, 803, 793,
+ 799, 800, 799, 806, 805, 799, 799, 805,
+ 805, 805, 793, 807, 805, 809, 808, 810,
+ 808, 811, 813, 811, 814, 812, 811, 811,
+ 812, 812, 812, 808, 801, 801, 801, 801,
+ 793, 815, 815, 815, 815, 793, 818, 819,
+ 817, 817, 816, 820, 817, 820, 819, 820,
+ 817, 821, 817, 816, 822, 817, 824, 823,
+ 825, 823, 826, 827, 826, 829, 826, 827,
+ 828, 827, 823, 830, 831, 832, 830, 830,
+ 816, 820, 820, 820, 820, 833, 834, 830,
+ 835, 823, 836, 823, 837, 838, 839, 837,
+ 837, 823, 841, 841, 842, 843, 844, 845,
+ 840, 841, 841, 842, 843, 844, 845, 847,
+ 846, 849, 849, 850, 851, 853, 854, 855,
+ 856, 857, 853, 854, 855, 856, 857, 858,
+ 859, 858, 859, 852, 848, 849, 849, 850,
+ 851, 858, 859, 858, 859, 860, 858, 859,
+ 849, 849, 850, 851, 858, 859, 858, 859,
+ 861, 848, 864, 865, 866, 867, 868, 864,
+ 865, 866, 867, 868, 863, 862, 869, 869,
+ 870, 871, 873, 874, 873, 874, 872, 848,
+ 844, 845, 840, 876, 876, 877, 878, 879,
+ 880, 875, 876, 876, 877, 878, 881, 883,
+ 884, 882, 879, 880, 882, 882, 882, 875,
+ 885, 875, 887, 887, 888, 889, 890, 891,
+ 892, 891, 893, 894, 893, 894, 891, 891,
+ 891, 886, 895, 895, 896, 897, 898, 899,
+ 898, 899, 886, 898, 899, 885, 901, 900,
+ 900, 900, 900, 875, 902, 900, 904, 903,
+ 905, 903, 907, 908, 906, 906, 906, 906,
+ 903, 887, 887, 888, 889, 893, 894, 893,
+ 894, 886, 879, 880, 875, 909, 909, 910,
+ 911, 912, 913, 619, 909, 909, 910, 911,
+ 912, 913, 914, 914, 914, 915, 917, 917,
+ 918, 919, 920, 921, 920, 922, 916, 924,
+ 924, 925, 926, 927, 929, 930, 928, 931,
+ 932, 931, 933, 928, 928, 928, 923, 935,
+ 934, 936, 936, 937, 938, 939, 940, 941,
+ 940, 942, 943, 942, 943, 940, 940, 940,
+ 923, 944, 944, 945, 946, 931, 932, 931,
+ 932, 84, 931, 932, 935, 948, 947, 947,
+ 947, 947, 934, 949, 947, 951, 950, 952,
+ 950, 954, 955, 953, 953, 953, 953, 950,
+ 936, 936, 937, 938, 942, 943, 942, 943,
+ 923, 931, 956, 932, 933, 84, 957, 957,
+ 958, 959, 927, 929, 930, 928, 960, 961,
+ 928, 928, 928, 934, 960, 961, 619, 912,
+ 913, 619, 963, 963, 963, 963, 962, 964,
+ 964, 964, 964, 962, 965, 966, 965, 965,
+ 965, 962, 967, 968, 967, 967, 967, 962,
+ 968, 968, 969, 970, 963, 971, 972, 973,
+ 973, 974, 975, 963, 963, 963, 962, 971,
+ 972, 962, 968, 962, 977, 977, 978, 979,
+ 980, 981, 982, 982, 983, 984, 976, 985,
+ 985, 986, 987, 988, 989, 990, 991, 992,
+ 993, 994, 995, 996, 997, 998, 999, 1000,
+ 1001, 988, 989, 990, 991, 992, 993, 994,
+ 995, 996, 997, 998, 999, 1000, 1001, 1002,
+ 1003, 1004, 1004, 1005, 1006, 976, 1007, 1007,
+ 1008, 1009, 1010, 1011, 1012, 1010, 1011, 1012,
+ 1013, 1014, 1015, 1015, 1016, 1017, 976, 1018,
+ 1018, 976, 1019, 1019, 976, 1020, 1020, 1021,
+ 1022, 1023, 1024, 1025, 1025, 1026, 1027, 976,
+ 1002, 1003, 976, 1028, 1029, 1028, 1029, 976,
+ 1030, 1030, 976, 1031, 1031, 976, 1032, 1032,
+ 1033, 1034, 1035, 1036, 1037, 1037, 1038, 1039,
+ 976, 1040, 1040, 976, 1041, 1041, 976, 1042,
+ 1042, 976, 1043, 1043, 1044, 1045, 1046, 1047,
+ 1048, 1048, 1049, 1050, 976, 1051, 1052, 1053,
+ 1051, 1052, 1053, 976, 1054, 1054, 976, 1055,
+ 1055, 976, 1056, 1056, 976, 1057, 1057, 1058,
+ 1059, 1060, 1061, 1062, 1062, 1063, 1064, 976,
+ 1065, 1066, 1065, 1066, 976, 1067, 1067, 976,
+ 1068, 1068, 976, 1069, 1069, 1070, 1071, 1072,
+ 1073, 1074, 1074, 1075, 1076, 976, 1077, 1077,
+ 976, 1078, 1078, 976, 1079, 1079, 976, 1080,
+ 1080, 1081, 1082, 1083, 1084, 1085, 1085, 1086,
+ 1087, 976, 1088, 1088, 1089, 1090, 1091, 1092,
+ 1093, 1093, 1094, 1095, 976, 1096, 1096, 976,
+ 1097, 1097, 976, 1098, 1099, 976, 1100, 976,
+ 1101, 1101, 1102, 1103, 1104, 1105, 1106, 1106,
+ 1107, 1108, 976, 1109, 976, 1110, 1110, 1111,
+ 1112, 1113, 1114, 1115, 1115, 1116, 1117, 976,
+ 1118, 1118, 976, 1119, 1119, 976, 1120, 1120,
+ 976, 1121, 1121, 976, 1122, 1122, 1123, 1124,
+ 1125, 1126, 1127, 1127, 1128, 1129, 976, 1130,
+ 1130, 976, 1131, 1131, 976, 1132, 1132, 976,
+ 1133, 1133, 976, 1134, 1134, 976, 1135, 1135,
+ 976, 1136, 1136, 976, 1137, 1137, 1138, 1139,
+ 1140, 1141, 1142, 1142, 1143, 1144, 976, 1145,
+ 1146, 1145, 1146, 976, 1147, 1147, 976, 1148,
+ 1148, 1149, 1150, 1151, 1152, 1153, 1153, 1154,
+ 1155, 976, 1156, 1156, 1157, 1158, 1159, 1160,
+ 1161, 1161, 1162, 1163, 976, 1164, 1165, 1166,
+ 1167, 1166, 1167, 976, 1168, 976, 1169, 1169,
+ 1170, 1171, 1172, 1173, 1174, 1174, 1175, 1176,
+ 976, 1177, 976, 1178, 1178, 1179, 1180, 1181,
+ 1182, 1183, 1183, 1184, 1185, 976, 1186, 1186,
+ 976, 1187, 1187, 1188, 1189, 1190, 1191, 1192,
+ 1192, 1193, 1194, 976, 1195, 1195, 1196, 1197,
+ 1198, 1199, 1200, 1200, 1201, 1202, 976, 1203,
+ 1204, 1203, 1204, 976, 1205, 1205, 976, 1206,
+ 1206, 976, 1207, 1207, 976, 1208, 1208, 1209,
+ 1210, 1211, 1212, 1213, 1213, 1214, 1215, 976,
+ 1216, 1216, 1217, 1218, 1219, 1220, 1221, 1221,
+ 1222, 1223, 976, 1224, 1225, 1226, 1224, 1225,
+ 1226, 976, 1227, 1227, 976, 1228, 1228, 976,
+ 1229, 1229, 976, 1230, 1230, 1231, 1232, 1233,
+ 1234, 1235, 1235, 1236, 1237, 976, 1238, 1238,
+ 976, 1239, 1239, 1240, 1241, 1242, 1243, 1244,
+ 1244, 1245, 1246, 976, 1247, 1247, 1248, 1249,
+ 1250, 1250, 1251, 1252, 1253, 1253, 1254, 1255,
+ 976, 1256, 1256, 976, 1257, 1257, 1258, 1259,
+ 1260, 1261, 1262, 1263, 1263, 1264, 1265, 976,
+ 1266, 1266, 1267, 1268, 1269, 1269, 1270, 1271,
+ 1272, 1272, 1273, 1274, 976, 1275, 1275, 976,
+ 1276, 1276, 976, 1277, 1277, 976, 1278, 1278,
+ 976, 1279, 1279, 1280, 1281, 1282, 1283, 1284,
+ 1284, 1285, 1286, 976, 1287, 1287, 976, 1288,
+ 1288, 976, 1289, 1289, 1290, 1291, 1292, 1293,
+ 1294, 1294, 1295, 1296, 976, 1297, 1298, 1299,
+ 1297, 1298, 1299, 976, 1300, 1300, 1301, 1302,
+ 1303, 1304, 1305, 1305, 1306, 1307, 976, 1308,
+ 1308, 976, 1309, 1309, 976, 1310, 1310, 976,
+ 1311, 1311, 1312, 1313, 1314, 1315, 1316, 1316,
+ 1317, 1318, 976, 1319, 1319, 1320, 1321, 1322,
+ 1323, 1324, 1324, 1325, 1326, 976, 1327, 1328,
+ 1329, 1330, 1327, 1328, 1329, 1330, 976, 1331,
+ 1331, 976, 1332, 1332, 1333, 1334, 1335, 1336,
+ 1337, 1337, 1338, 1339, 976, 1340, 1340, 976,
+ 1341, 1341, 1342, 1343, 1344, 1345, 1346, 1346,
+ 1347, 1348, 976, 1349, 1349, 976, 1350, 1350,
+ 1351, 1352, 1353, 1354, 1355, 1355, 1356, 1357,
+ 976, 1358, 1358, 976, 1359, 1359, 976, 1360,
+ 1360, 976, 1361, 1361, 1362, 1363, 1364, 1365,
+ 1366, 1366, 1367, 1368, 976, 1369, 1370, 1371,
+ 1369, 1370, 1371, 976, 1372, 1372, 976, 1373,
+ 1373, 976, 1374, 1374, 1375, 1376, 1377, 1378,
+ 1379, 1379, 1380, 1381, 976, 1382, 1382, 976,
+ 1383, 1383, 1384, 1385, 1386, 1387, 1388, 1388,
+ 1389, 1390, 976, 1391, 1391, 976, 1392, 1392,
+ 976, 1393, 976, 1394, 1394, 1395, 1396, 1398,
+ 1399, 1400, 1400, 1401, 1402, 1397, 976, 1403,
+ 1403, 976, 1404, 1404, 976, 1405, 1405, 976,
+ 1406, 1406, 1407, 1408, 1409, 1410, 1411, 1411,
+ 1412, 1413, 976, 1414, 1414, 976, 1415, 1415,
+ 1416, 1417, 1418, 1419, 1420, 1420, 1421, 1422,
+ 976, 1424, 1424, 1425, 1426, 1427, 1428, 1423,
+ 1424, 1424, 1425, 1426, 1427, 1428, 1430, 1429,
+ 1431, 1431, 1432, 1433, 1435, 1436, 1434, 1429,
+ 1438, 1438, 1439, 1440, 1442, 1443, 1441, 1441,
+ 1441, 1437, 1444, 1444, 1444, 1437, 1445, 1445,
+ 1446, 1447, 1448, 1449, 1450, 1450, 1451, 1452,
+ 1441, 1441, 1441, 1437, 1448, 1449, 1437, 1442,
+ 1443, 1423, 1427, 1428, 1423, 1453, 1453, 1454,
+ 1455, 1456, 1457, 1423, 1453, 1453, 1454, 1455,
+ 1458, 1456, 1457, 1459, 1429, 1460, 1460, 1461,
+ 1462, 1464, 1464, 1465, 1466, 1463, 1429, 1467,
+ 1467, 1468, 1469, 1471, 1472, 1470, 1470, 1470,
+ 1437, 1473, 1473, 1473, 1437, 1474, 1474, 1475,
+ 1476, 1477, 1478, 1479, 1479, 1480, 1481, 1470,
+ 1470, 1470, 1437, 1477, 1478, 1437, 1471, 1472,
+ 1423, 1482, 1482, 1483, 1484, 1485, 1486, 1463,
+ 1429, 1456, 1457, 1423, 1489, 1490, 1491, 1492,
+ 1493, 1489, 1490, 1491, 1492, 1493, 1488, 1487,
+ 1494, 1494, 1494, 1494, 1495, 1487, 1496, 1497,
+ 1496, 1497, 1487, 1498, 1498, 1498, 1498, 1487,
+ 1499, 1499, 1487, 1500, 1501, 1500, 1500, 1500,
+ 1487, 1502, 1502, 1487, 1503, 1503, 1487, 1504,
+ 1504, 1487, 1505, 1505, 1487, 1506, 1487, 1507,
+ 1487, 1508, 1508, 1487, 1509, 1509, 1487, 1510,
+ 1510, 1487, 1511, 1487, 1512, 1512, 1512, 1512,
+ 1487, 1513, 1513, 1487, 1514, 1515, 1514, 1515,
+ 1487, 1516, 1487, 1517, 1517, 1487, 1518, 1518,
+ 1487, 1519, 1519, 1487, 1520, 1520, 1487, 1521,
+ 1521, 1521, 1521, 1487, 1522, 1522, 1487, 1523,
+ 1523, 1487, 1524, 1524, 1487, 1525, 1526, 1487,
+ 1527, 1487, 1528, 1487, 1529, 1529, 1487, 1530,
+ 1530, 1487, 1531, 1531, 1487, 1532, 1487, 1533,
+ 1487, 1534, 1487, 1535, 1535, 1535, 1535, 1487,
+ 1536, 1487, 1537, 1487, 1538, 1538, 1487, 1539,
+ 1539, 1487, 1540, 1540, 1487, 1541, 1487, 1542,
+ 1487, 1543, 1487, 1544, 1544, 1544, 1544, 1487,
+ 1545, 1545, 1487, 1546, 1546, 1487, 1547, 1547,
+ 1487, 1548, 1548, 1487, 1549, 1549, 1487, 1550,
+ 1550, 1487, 1551, 1551, 1487, 1552, 1552, 1552,
+ 1552, 1487, 1553, 1553, 1487, 1554, 1554, 1487,
+ 1555, 1555, 1487, 1556, 1556, 1487, 1557, 1557,
+ 1487, 1558, 1558, 1487, 1559, 1560, 1559, 1560,
+ 1487, 1561, 1561, 1487, 1562, 1562, 1487, 1563,
+ 1563, 1563, 1563, 1487, 1564, 1564, 1487, 1565,
+ 1565, 1487, 1566, 1566, 1566, 1566, 1487, 1567,
+ 1567, 1487, 1568, 1568, 1487, 1569, 1570, 1569,
+ 1570, 1487, 1571, 1571, 1487, 1572, 1487, 1573,
+ 1573, 1573, 1573, 1487, 1574, 1574, 1487, 1575,
+ 1575, 1487, 1576, 1577, 1578, 1487, 1579, 1580,
+ 1579, 1579, 1579, 1487, 1581, 1581, 1487, 1582,
+ 1582, 1487, 1583, 1583, 1487, 1584, 1584, 1487,
+ 1585, 1487, 1586, 1487, 1587, 1587, 1487, 1588,
+ 1588, 1487, 1589, 1589, 1487, 1590, 1487, 1591,
+ 1591, 1591, 1591, 1487, 1592, 1487, 1593, 1487,
+ 1594, 1594, 1594, 1594, 1487, 1595, 1487, 1596,
+ 1487, 1597, 1597, 1597, 1597, 1487, 1600, 1601,
+ 1602, 1603, 1604, 1605, 1600, 1601, 1602, 1603,
+ 1604, 1605, 1599, 1598, 1606, 1606, 1606, 1606,
+ 1607, 1598, 1608, 1608, 1598, 1609, 1609, 1598,
+ 1610, 1610, 1598, 1611, 1611, 1598, 1612, 1612,
+ 1598, 1613, 1613, 1613, 1613, 1598, 1614, 1615,
+ 1616, 1614, 1615, 1616, 1598, 1617, 1617, 1598,
+ 1618, 1618, 1598, 1619, 1619, 1598, 1620, 1620,
+ 1598, 1621, 1621, 1598, 1622, 1622, 1622, 1622,
+ 1598, 1623, 1624, 1623, 1624, 1598, 1625, 1625,
+ 1598, 1626, 1626, 1626, 1626, 1598, 1627, 1627,
+ 1598, 1628, 1628, 1598, 1629, 1629, 1629, 1629,
+ 1598, 1630, 1630, 1598, 1631, 1631, 1598, 1632,
+ 1632, 1598, 1633, 1633, 1633, 1633, 1598, 1634,
+ 1634, 1598, 1635, 1635, 1598, 1636, 1636, 1636,
+ 1636, 1598, 1637, 1638, 1637, 1638, 1598, 1639,
+ 1639, 1598, 1640, 1640, 1640, 1640, 1598, 1641,
+ 1641, 1598, 1642, 1642, 1598, 1643, 1643, 1643,
+ 1643, 1598, 1644, 1644, 1598, 1645, 1645, 1598,
+ 1646, 1646, 1598, 1647, 1647, 1647, 1647, 1598,
+ 1648, 1648, 1598, 1649, 1649, 1598, 1650, 1650,
+ 1650, 1650, 1598, 1652, 1652, 1651, 1653, 1654,
+ 1653, 1653, 1653, 1654, 1651, 1655, 1655, 1655,
+ 1655, 1655, 1655, 69, 1656, 1656, 1656, 1656,
+ 69, 1657, 1657, 1657, 1657, 1657, 1657, 69,
+ 1658, 1658, 1659, 1660, 1661, 1662, 69, 1663,
+ 1663, 1664, 1665, 1666, 1666, 1666, 1667, 1668,
+ 1666, 1666, 1666, 69, 1669, 1669, 1670, 1671,
+ 1672, 1673, 69, 1675, 1675, 1676, 1677, 1679,
+ 1680, 1678, 1674, 1681, 1681, 1682, 1683, 1685,
+ 1686, 1684, 1674, 1687, 1687, 1688, 1689, 1691,
+ 1692, 1690, 1674, 1694, 1694, 1695, 1696, 1698,
+ 1699, 1700, 1701, 1702, 1698, 1699, 1700, 1701,
+ 1702, 1703, 1704, 1697, 1693, 1705, 1705, 1706,
+ 1707, 1709, 1710, 1708, 1674, 1711, 1711, 1712,
+ 1713, 1715, 1716, 1717, 1718, 1719, 1715, 1716,
+ 1717, 1718, 1719, 1720, 1721, 1714, 1693, 1722,
+ 1722, 1723, 1724, 1726, 1727, 1725, 1674, 1728,
+ 1728, 1729, 1730, 1732, 1733, 1734, 1735, 1736,
+ 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1731,
+ 1693, 1739, 1739, 1740, 1741, 1743, 1744, 1742,
+ 1674, 1745, 1745, 1747, 1748, 1749, 1750, 1751,
+ 1747, 1748, 1749, 1750, 1751, 1745, 1745, 1746,
+ 1693, 1745, 1745, 1745, 1745, 1752, 1693, 1754,
+ 1755, 1756, 1757, 1758, 1754, 1755, 1756, 1757,
+ 1758, 1753, 1693, 1759, 1759, 1759, 1759, 1760,
+ 1693, 1743, 1744, 69, 1728, 1728, 1729, 1730,
+ 1737, 1738, 1761, 1693, 1763, 1764, 1765, 1766,
+ 1767, 1763, 1764, 1765, 1766, 1767, 1762, 1693,
+ 1768, 1768, 1769, 1770, 1772, 1773, 1771, 1693,
+ 1726, 1727, 69, 1711, 1711, 1712, 1713, 1720,
+ 1721, 1774, 1693, 1776, 1777, 1778, 1779, 1780,
+ 1776, 1777, 1778, 1779, 1780, 1775, 1693, 1781,
+ 1781, 1782, 1783, 1785, 1786, 1784, 1693, 1709,
+ 1710, 69, 1694, 1694, 1695, 1696, 1703, 1704,
+ 1787, 1693, 1789, 1790, 1791, 1792, 1793, 1789,
+ 1790, 1791, 1792, 1793, 1788, 1693, 1794, 1794,
+ 1795, 1796, 1798, 1799, 1797, 1693, 1691, 1692,
+ 69, 1679, 1680, 69, 1667, 1668, 69, 69,
+ 69, 69, 69, 1800, 1801, 1801, 1802, 1803,
+ 1804, 1805, 69, 1807, 1807, 1808, 1809, 1810,
+ 1811, 1806, 1806, 1806, 69, 1812, 1812, 1812,
+ 1812, 69, 1810, 1811, 69, 1813, 1813, 1813,
+ 1813, 1813, 1813, 69, 1814, 1814, 1815, 1816,
+ 1817, 1818, 69, 1819, 1819, 1820, 1821, 1822,
+ 1822, 1822, 1823, 1824, 1822, 1822, 1822, 69,
+ 1825, 1825, 1825, 1825, 69, 1823, 1824, 69,
+ 1826, 1674, 1827, 1827, 1828, 1829, 1831, 1832,
+ 1830, 1674, 1833, 1833, 1834, 1835, 1836, 1836,
+ 1836, 1837, 1838, 1836, 1836, 1836, 69, 1839,
+ 1839, 1839, 1839, 69, 1837, 1838, 69, 69,
+ 69, 69, 69, 1840, 1841, 1841, 1842, 1843,
+ 1844, 1845, 1846, 1846, 1847, 1848, 69, 1849,
+ 1849, 1850, 1851, 1852, 1853, 1854, 1854, 1855,
+ 1856, 1840, 1840, 1840, 69, 1852, 1853, 69,
+ 1857, 1857, 1857, 1857, 1651, 1858, 1859, 1858,
+ 1858, 1858, 1859, 1859, 1859, 1651, 1861, 1860,
+ 1862, 1862, 1863, 1864, 1866, 1867, 1865, 1860,
+ 1868, 1868, 1869, 1870, 1872, 1873, 1874, 1875,
+ 1871, 1860, 1876, 1876, 1877, 1878, 1880, 1881,
+ 1879, 1860, 1882, 1882, 1883, 1884, 1872, 1873,
+ 1886, 1887, 1885, 1860, 1888, 1888, 1889, 1890,
+ 1891, 1893, 1894, 1892, 1860, 1895, 1895, 1896,
+ 1897, 1872, 1873, 1898, 1899, 1860, 1900, 1900,
+ 1901, 1902, 1903, 1904, 1860, 1900, 1900, 1901,
+ 1902, 1903, 1904, 1905, 1860, 1906, 1906, 1907,
+ 1908, 1910, 1911, 1909, 1860, 1912, 1912, 1913,
+ 1914, 1916, 1917, 1918, 1919, 1915, 1860, 1920,
+ 1920, 1921, 1922, 1924, 1925, 1923, 1860, 1926,
+ 1926, 1927, 1928, 1916, 1917, 1930, 1931, 1929,
+ 1860, 1932, 1932, 1933, 1934, 1935, 1937, 1938,
+ 1936, 1860, 1939, 1939, 1940, 1941, 1916, 1917,
+ 1942, 1943, 1860, 1944, 1944, 1945, 1946, 1947,
+ 1948, 1860, 1944, 1944, 1945, 1946, 1949, 1947,
+ 1948, 1950, 1860, 1951, 1860, 1952, 1952, 1953,
+ 1954, 1955, 1957, 1958, 1959, 1960, 1960, 1961,
+ 1962, 1956, 1860, 1963, 1963, 1964, 1965, 1967,
+ 1968, 1969, 1969, 1970, 1971, 1966, 1860, 1972,
+ 1972, 1973, 1974, 1975, 1977, 1978, 1979, 1980,
+ 1980, 1981, 1982, 1976, 1860, 1983, 1983, 1984,
+ 1985, 1987, 1988, 1969, 1969, 1989, 1990, 1986,
+ 1860, 1991, 1991, 1992, 1993, 1994, 1996, 1997,
+ 1998, 1999, 1999, 2000, 2001, 1995, 1860, 2002,
+ 2002, 2003, 2004, 2006, 2007, 1969, 1969, 2008,
+ 2009, 2005, 1860, 2010, 2010, 2011, 2012, 2013,
+ 2010, 2015, 2016, 2017, 2017, 2018, 2019, 2014,
+ 1860, 2020, 2020, 2021, 2022, 2023, 2024, 1969,
+ 1969, 2025, 2026, 1860, 2023, 2024, 1860, 2027,
+ 2027, 2028, 2029, 2027, 2031, 2032, 2033, 2033,
+ 2034, 2035, 2030, 1860, 2010, 2010, 2011, 2012,
+ 2010, 2015, 2016, 2017, 2017, 2018, 2019, 2036,
+ 1860, 2006, 2007, 1860, 2037, 2037, 2038, 2039,
+ 2041, 2042, 2043, 2044, 2044, 2045, 2046, 2040,
+ 1860, 1991, 1991, 1992, 1993, 1996, 1997, 1998,
+ 1999, 1999, 2000, 2001, 2047, 1860, 2002, 2002,
+ 2003, 2004, 2006, 2007, 1969, 1969, 2008, 2009,
+ 1860, 1987, 1988, 1860, 2048, 2048, 2049, 2050,
+ 2052, 2053, 2054, 2055, 2055, 2056, 2057, 2051,
+ 1860, 1972, 1972, 1973, 1974, 1977, 1978, 1979,
+ 1980, 1980, 1981, 1982, 2058, 1860, 1983, 1983,
+ 1984, 1985, 1987, 1988, 1969, 1969, 1989, 1990,
+ 1860, 1967, 1968, 1860, 2059, 2059, 2060, 2061,
+ 2063, 2064, 2065, 2066, 2066, 2067, 2068, 2062,
+ 1860, 1952, 1952, 1953, 1954, 1957, 1958, 1959,
+ 1960, 1960, 1961, 1962, 2069, 1860, 1963, 1963,
+ 1964, 1965, 1967, 1968, 1969, 1969, 1970, 1971,
+ 1860, 1947, 1948, 1860, 2070, 2070, 2071, 2072,
+ 2073, 2074, 1860, 1942, 1943, 1860, 2075, 2075,
+ 2076, 2077, 2079, 2080, 2078, 1860, 1932, 1932,
+ 1933, 1934, 1937, 1938, 2081, 1860, 1930, 1931,
+ 1860, 1918, 1919, 1860, 1903, 1904, 1860, 2082,
+ 2082, 2083, 2084, 2085, 2086, 1860, 1898, 1899,
+ 1860, 2087, 2087, 2088, 2089, 2091, 2092, 2090,
+ 1860, 1888, 1888, 1889, 1890, 1893, 1894, 2093,
+ 1860, 1886, 1887, 1860, 1874, 1875, 1860, 2094,
+ 1674, 2095, 2095, 2096, 2097, 2099, 2100, 2098,
+ 1674, 2101, 2101, 2102, 2103, 2105, 2106, 2104,
+ 1674, 2107, 2107, 2108, 2109, 2111, 2112, 2110,
+ 1674, 2113, 2113, 2114, 2115, 2117, 2118, 2116,
+ 1674, 2119, 2119, 2120, 2121, 2123, 2124, 2122,
+ 1674, 2125, 2125, 2126, 2127, 2128, 2128, 2128,
+ 2129, 2130, 2128, 2128, 2128, 69, 2131, 2131,
+ 2131, 2131, 69, 2129, 2130, 69, 2117, 2118,
+ 69, 2105, 2106, 69, 2132, 1674, 2133, 2133,
+ 2134, 2135, 2137, 2138, 2136, 1674, 2139, 2139,
+ 2140, 2141, 2143, 2144, 2142, 1674, 2145, 2145,
+ 2146, 2147, 2149, 2150, 2148, 1674, 2152, 2152,
+ 2153, 2154, 2155, 2156, 2151, 2151, 2151, 69,
+ 2157, 2157, 2158, 2159, 2160, 2161, 69, 2163,
+ 2163, 2164, 2165, 2166, 2167, 2162, 2162, 2162,
+ 69, 2168, 2168, 2169, 2170, 2171, 2172, 69,
+ 2174, 2174, 2175, 2176, 2177, 2178, 2173, 2173,
+ 2173, 69, 2179, 2179, 2180, 2181, 2182, 2183,
+ 69, 2184, 2184, 2185, 2186, 2187, 2187, 2187,
+ 2188, 2189, 2187, 2187, 2187, 69, 2190, 2190,
+ 2190, 2190, 69, 2188, 2189, 69, 2177, 2178,
+ 69, 2166, 2167, 69, 2155, 2156, 69, 2143,
+ 2144, 69, 2191, 2191, 2191, 69, 2192, 2192,
+ 2193, 2194, 2195, 2196, 69, 2192, 2192, 2193,
+ 2194, 2195, 2196, 2197, 1674, 2198, 2198, 2199,
+ 2200, 2202, 2203, 2201, 1674, 2204, 2204, 2205,
+ 2206, 2208, 2209, 2207, 2207, 2207, 69, 2210,
+ 2210, 2211, 2212, 2213, 2214, 69, 2210, 2210,
+ 2211, 2212, 2215, 2213, 2214, 2215, 2215, 2215,
+ 69, 2216, 2216, 69, 2213, 2214, 69, 2208,
+ 2209, 69, 2195, 2196, 69, 2218, 2218, 2219,
+ 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2226,
+ 2227, 2228, 2217, 2229, 2230, 2217, 2231, 2217,
+ 2233, 2233, 2232, 2235, 2234, 2232, 2236, 2217,
+ 2237, 2237, 2238, 2239, 2241, 2242, 2243, 2243,
+ 2244, 2245, 2240, 2217, 2224, 2225, 69, 2246,
+ 2217, 2247, 2247, 2247, 2247, 2232, 2249, 2248,
+ 2248, 2248, 2232, 2250, 1674, 2251, 2251, 2252,
+ 2253, 2255, 2256, 2254, 1674, 2257, 2257, 2258,
+ 2259, 2261, 2262, 2260, 2260, 2260, 69, 2263,
+ 2263, 2264, 2265, 2266, 2267, 69, 2263, 2263,
+ 2264, 2265, 2266, 2267, 2268, 1674, 2269, 2269,
+ 2270, 2271, 2273, 2274, 2272, 1674, 2276, 2276,
+ 2277, 2278, 2280, 2281, 2279, 2279, 2279, 2275,
+ 2282, 2282, 2282, 2275, 2283, 2283, 2284, 2285,
+ 2286, 2287, 2288, 2288, 2289, 2290, 2279, 2279,
+ 2279, 2275, 2286, 2287, 2275, 2280, 2281, 69,
+ 2266, 2267, 69, 2261, 2262, 69, 2291, 1674,
+ 2292, 2292, 2293, 2294, 2296, 2297, 2295, 1674,
+ 2298, 2298, 2299, 2300, 2302, 2303, 2301, 1674,
+ 2304, 2304, 2305, 2306, 2308, 2309, 2307, 1674,
+ 2310, 2310, 2311, 2312, 2314, 2315, 2313, 2313,
+ 2313, 2275, 2316, 2316, 2316, 2275, 2317, 2317,
+ 2318, 2319, 2320, 2321, 2322, 2322, 2323, 2324,
+ 2313, 2313, 2313, 2275, 2320, 2321, 2275, 2314,
+ 2315, 69, 2302, 2303, 69, 2325, 1674, 2326,
+ 2326, 2327, 2328, 2330, 2331, 2329, 1674, 2333,
+ 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340,
+ 2341, 2332, 2342, 2342, 2343, 2344, 2345, 2346,
+ 2332, 2342, 2342, 2343, 2344, 2345, 2346, 2348,
+ 2347, 2349, 2349, 2350, 2351, 2353, 2354, 2352,
+ 2347, 2355, 2355, 2356, 2357, 2358, 2359, 2360,
+ 2332, 2362, 2362, 2363, 2364, 2365, 2365, 2366,
+ 2367, 2368, 2368, 2369, 2370, 2371, 2371, 2371,
+ 2371, 2372, 2373, 2371, 2371, 2374, 2375, 2376,
+ 2377, 2371, 2371, 2378, 2379, 2380, 2381, 2371,
+ 2371, 2382, 2383, 2361, 2362, 2362, 2363, 2364,
+ 2385, 2372, 2373, 2385, 2385, 2385, 2384, 2371,
+ 2371, 2384, 2372, 2373, 2384, 2365, 2365, 2366,
+ 2367, 2371, 2371, 2371, 2371, 2376, 2377, 2371,
+ 2371, 2378, 2379, 2384, 2376, 2377, 2384, 2385,
+ 2362, 2362, 2363, 2364, 2365, 2365, 2366, 2367,
+ 2368, 2368, 2369, 2370, 2371, 2371, 2371, 2371,
+ 2372, 2373, 2371, 2371, 2374, 2375, 2376, 2377,
+ 2371, 2371, 2378, 2379, 2380, 2381, 2371, 2371,
+ 2382, 2383, 2385, 2385, 2385, 2384, 2372, 2376,
+ 2380, 2373, 2377, 2381, 2384, 2359, 2360, 2332,
+ 2345, 2346, 2332, 2386, 2386, 2387, 2388, 2389,
+ 2390, 2332, 2386, 2386, 2387, 2388, 2389, 2390,
+ 2391, 2347, 2392, 2392, 2393, 2394, 2396, 2397,
+ 2395, 2347, 2399, 2399, 2400, 2401, 2402, 2403,
+ 2404, 2402, 2398, 2406, 2407, 2407, 2408, 2409,
+ 2410, 2410, 2411, 2412, 2413, 2413, 2414, 2415,
+ 2416, 2416, 2416, 2416, 2417, 2418, 2416, 2416,
+ 2419, 2420, 2421, 2422, 2416, 2416, 2423, 2424,
+ 2425, 2426, 2416, 2416, 2427, 2428, 2406, 2405,
+ 2403, 2404, 2332, 2389, 2390, 2332, 2429, 2429,
+ 2430, 2431, 2432, 2433, 2332, 2429, 2429, 2430,
+ 2431, 2432, 2433, 2434, 2347, 2435, 2435, 2436,
+ 2437, 2439, 2440, 2438, 2347, 2441, 2441, 2442,
+ 2443, 2444, 2445, 2446, 2444, 2444, 2444, 2398,
+ 2447, 2448, 2448, 2449, 2450, 2451, 2451, 2452,
+ 2453, 2454, 2454, 2455, 2456, 2457, 2457, 2457,
+ 2457, 2458, 2459, 2457, 2457, 2460, 2461, 2462,
+ 2463, 2457, 2457, 2464, 2465, 2466, 2467, 2457,
+ 2457, 2468, 2469, 2447, 2447, 2447, 2405, 2445,
+ 2446, 2332, 2432, 2433, 2332, 2470, 2470, 2471,
+ 2472, 2473, 2474, 2332, 2470, 2470, 2471, 2472,
+ 2473, 2474, 2475, 2347, 2476, 2476, 2477, 2478,
+ 2480, 2481, 2479, 2347, 2482, 2482, 2483, 2484,
+ 2485, 2485, 2485, 2486, 2487, 2485, 2485, 2485,
+ 2332, 2488, 2488, 2489, 2490, 2491, 2491, 2492,
+ 2493, 2494, 2494, 2495, 2496, 2497, 2497, 2497,
+ 2497, 2498, 2499, 2497, 2497, 2500, 2501, 2502,
+ 2503, 2497, 2497, 2504, 2505, 2506, 2507, 2497,
+ 2497, 2508, 2509, 2361, 2486, 2487, 2332, 2473,
+ 2474, 2332, 2340, 2341, 69, 2511, 2512, 2513,
+ 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521,
+ 2522, 2523, 2524, 2511, 2512, 2513, 2514, 2515,
+ 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523,
+ 2524, 2510, 2525, 2525, 2526, 2527, 2528, 2529,
+ 2530, 2528, 2529, 2530, 2531, 2532, 2510, 2533,
+ 2533, 2534, 2535, 2537, 2538, 2536, 2536, 2536,
+ 69, 2539, 2539, 2540, 2541, 2542, 2543, 69,
+ 2539, 2539, 2540, 2541, 2542, 2543, 2544, 1674,
+ 2545, 2545, 2546, 2547, 2549, 2550, 2548, 1674,
+ 2551, 2551, 2552, 2553, 2555, 2556, 2554, 1674,
+ 2557, 2557, 2558, 2559, 2561, 2562, 2560, 1674,
+ 2564, 2564, 2565, 2566, 2568, 2569, 2567, 2563,
+ 2570, 2570, 2571, 2572, 2574, 2575, 2573, 2563,
+ 2576, 2576, 2577, 2578, 2580, 2581, 2579, 2563,
+ 2582, 2582, 2583, 2584, 2586, 2587, 2585, 2563,
+ 2588, 2588, 2589, 2590, 2592, 2593, 2591, 1674,
+ 2594, 2594, 2595, 2596, 2598, 2599, 2597, 1674,
+ 2600, 2600, 2601, 2602, 2603, 2603, 2603, 2604,
+ 2605, 2603, 2603, 2603, 69, 2606, 2606, 2607,
+ 2608, 2609, 2610, 69, 2611, 2611, 2612, 2613,
+ 2614, 2615, 2616, 2614, 2614, 2614, 69, 2617,
+ 2617, 69, 2615, 2616, 69, 2604, 2605, 69,
+ 2592, 2593, 69, 2580, 2581, 69, 2568, 2569,
+ 69, 2555, 2556, 69, 2542, 2543, 69, 2537,
+ 2538, 69, 2618, 2618, 2510, 2619, 2619, 2510,
+ 2620, 2620, 2621, 2622, 2623, 2624, 2510, 2625,
+ 2625, 2510, 2626, 2626, 2510, 2627, 2627, 2510,
+ 2628, 2628, 2629, 2630, 2631, 2632, 2510, 2633,
+ 2633, 2510, 2634, 2634, 2635, 2636, 2637, 2638,
+ 2510, 2639, 2640, 2639, 2640, 2510, 2641, 2641,
+ 2510, 2642, 2642, 2510, 2643, 2643, 2644, 2645,
+ 2646, 2647, 2510, 2648, 2648, 2510, 2649, 2649,
+ 2510, 2650, 2650, 2510, 2651, 2651, 2652, 2653,
+ 2654, 2655, 2510, 2656, 2657, 2658, 2656, 2657,
+ 2658, 2510, 2659, 2659, 2510, 2660, 2660, 2510,
+ 2661, 2661, 2510, 2662, 2662, 2663, 2664, 2665,
+ 2666, 2510, 2667, 2668, 2667, 2668, 2510, 2669,
+ 2669, 2510, 2670, 2670, 2510, 2671, 2671, 2672,
+ 2673, 2674, 2675, 2510, 2676, 2676, 2510, 2677,
+ 2677, 2510, 2678, 2678, 2510, 2679, 2679, 2680,
+ 2681, 2682, 2683, 2510, 2684, 2684, 2685, 2686,
+ 2687, 2688, 2510, 2689, 2689, 2510, 2690, 2690,
+ 2510, 2691, 2692, 2510, 2693, 2510, 2694, 2694,
+ 2695, 2696, 2697, 2698, 2510, 2699, 2510, 2700,
+ 2700, 2701, 2702, 2703, 2704, 2510, 2705, 2705,
+ 2510, 2706, 2706, 2510, 2707, 2707, 2510, 2708,
+ 2708, 2510, 2709, 2709, 2710, 2711, 2712, 2713,
+ 2510, 2714, 2714, 2510, 2715, 2715, 2510, 2716,
+ 2716, 2510, 2717, 2717, 2510, 2718, 2718, 2510,
+ 2719, 2719, 2510, 2720, 2720, 2510, 2721, 2721,
+ 2722, 2723, 2724, 2725, 2510, 2726, 2727, 2726,
+ 2727, 2510, 2728, 2728, 2510, 2729, 2729, 2730,
+ 2731, 2732, 2733, 2510, 2734, 2734, 2735, 2736,
+ 2737, 2738, 2510, 2739, 2740, 2741, 2742, 2741,
+ 2742, 2510, 2743, 2510, 2744, 2744, 2745, 2746,
+ 2747, 2748, 2510, 2749, 2510, 2750, 2750, 2751,
+ 2752, 2753, 2754, 2510, 2755, 2755, 2510, 2756,
+ 2756, 2757, 2758, 2759, 2760, 2510, 2761, 2761,
+ 2762, 2763, 2764, 2765, 2510, 2766, 2767, 2766,
+ 2767, 2510, 2768, 2768, 2510, 2769, 2769, 2510,
+ 2770, 2770, 2510, 2771, 2771, 2772, 2773, 2774,
+ 2775, 2510, 2776, 2776, 2777, 2778, 2779, 2780,
+ 2510, 2781, 2782, 2783, 2781, 2782, 2783, 2510,
+ 2784, 2784, 2510, 2785, 2785, 2510, 2786, 2786,
+ 2510, 2787, 2787, 2788, 2789, 2790, 2791, 2510,
+ 2792, 2792, 2510, 2793, 2793, 2794, 2795, 2796,
+ 2797, 2510, 2798, 2798, 2799, 2800, 2801, 2801,
+ 2802, 2803, 2510, 2804, 2804, 2510, 2805, 2805,
+ 2806, 2807, 2808, 2809, 2810, 2510, 2811, 2811,
+ 2812, 2813, 2814, 2814, 2815, 2816, 2510, 2817,
+ 2817, 2510, 2818, 2818, 2510, 2819, 2819, 2510,
+ 2820, 2820, 2510, 2821, 2821, 2822, 2823, 2824,
+ 2825, 2510, 2826, 2826, 2510, 2827, 2827, 2510,
+ 2828, 2828, 2829, 2830, 2831, 2832, 2510, 2833,
+ 2834, 2835, 2833, 2834, 2835, 2510, 2836, 2836,
+ 2837, 2838, 2839, 2840, 2510, 2841, 2841, 2510,
+ 2842, 2842, 2510, 2843, 2843, 2510, 2844, 2844,
+ 2845, 2846, 2847, 2848, 2510, 2849, 2849, 2850,
+ 2851, 2852, 2853, 2510, 2854, 2855, 2856, 2857,
+ 2854, 2855, 2856, 2857, 2510, 2858, 2858, 2510,
+ 2859, 2859, 2860, 2861, 2862, 2863, 2510, 2864,
+ 2864, 2510, 2865, 2865, 2866, 2867, 2868, 2869,
+ 2510, 2870, 2870, 2510, 2871, 2871, 2872, 2873,
+ 2874, 2875, 2510, 2876, 2876, 2510, 2877, 2877,
+ 2510, 2878, 2878, 2510, 2879, 2879, 2880, 2881,
+ 2882, 2883, 2510, 2884, 2885, 2886, 2884, 2885,
+ 2886, 2510, 2887, 2887, 2510, 2888, 2888, 2510,
+ 2889, 2889, 2890, 2891, 2892, 2893, 2510, 2894,
+ 2894, 2510, 2895, 2895, 2896, 2897, 2898, 2899,
+ 2510, 2900, 2900, 2510, 2901, 2901, 2510, 2903,
+ 2902, 2904, 2904, 2905, 2906, 2908, 2909, 2907,
+ 2902, 2910, 2910, 2910, 2910, 2910, 2910, 69,
+ 2911, 2911, 2911, 2911, 69, 2912, 2912, 2912,
+ 2912, 69, 2913, 1674, 2914, 2914, 2915, 2916,
+ 2918, 2919, 2917, 1674, 2920, 2920, 2921, 2922,
+ 2924, 2925, 2923, 1674, 2926, 2926, 2927, 2928,
+ 2930, 2931, 2929, 1674, 2932, 2932, 2933, 2934,
+ 2936, 2937, 2935, 2935, 2935, 69, 2938, 2938,
+ 2939, 2940, 2941, 2942, 69, 2938, 2938, 2939,
+ 2940, 2943, 2941, 2942, 2943, 2943, 2943, 69,
+ 2944, 2944, 69, 2941, 2942, 69, 2936, 2937,
+ 69, 2924, 2925, 69, 2945, 2945, 2945, 2945,
+ 69, 2946, 2946, 69, 2947, 1674, 2948, 2948,
+ 2949, 2950, 2952, 2953, 2951, 1674, 2954, 2954,
+ 2955, 2956, 2958, 2959, 2957, 1674, 2960, 2960,
+ 2961, 2962, 2964, 2965, 2963, 1674, 2966, 2966,
+ 2967, 2968, 2970, 2971, 2969, 1674, 2972, 2972,
+ 2973, 2974, 2976, 2977, 2975, 1674, 2978, 2978,
+ 2979, 2980, 2981, 2983, 2984, 2982, 2982, 2982,
+ 2275, 2985, 2985, 2986, 2987, 2988, 2989, 2275,
+ 2991, 2991, 2992, 2993, 2995, 2996, 2994, 2994,
+ 2994, 2990, 2997, 2997, 2997, 2990, 2999, 2998,
+ 2998, 2998, 2990, 3000, 3000, 3000, 2990, 3002,
+ 3001, 3001, 3001, 2990, 3004, 3003, 3003, 3003,
+ 2990, 3005, 3005, 3005, 2990, 3007, 3006, 3006,
+ 3006, 2990, 3008, 3008, 3008, 3008, 3009, 3009,
+ 3009, 2990, 3010, 3010, 3010, 3010, 69, 3011,
+ 2990, 3007, 2990, 3004, 2990, 3012, 2990, 3002,
+ 2990, 2995, 2996, 69, 3013, 3013, 3013, 2275,
+ 2985, 2985, 2986, 2987, 2988, 2989, 3014, 3014,
+ 3014, 2275, 2983, 2984, 69, 2970, 2971, 69,
+ 2958, 2959, 69, 3015, 1674, 3016, 3016, 3017,
+ 3018, 3020, 3021, 3019, 1674, 3022, 3022, 3023,
+ 3024, 3026, 3027, 3025, 1674, 3028, 3028, 3029,
+ 3030, 3032, 3033, 3031, 1674, 3034, 3034, 3035,
+ 3036, 3038, 3039, 3037, 1674, 3040, 3040, 3041,
+ 3042, 3044, 3045, 3043, 1674, 3046, 3046, 3047,
+ 3048, 3049, 3051, 3052, 3050, 3050, 3050, 2275,
+ 3053, 3053, 3053, 3053, 2275, 3054, 3054, 3054,
+ 2275, 3053, 3053, 3053, 3053, 3055, 3055, 3055,
+ 2275, 3051, 3052, 69, 3038, 3039, 69, 3026,
+ 3027, 69, 3056, 1674, 3057, 3057, 3058, 3059,
+ 3061, 3062, 3060, 1674, 3063, 3063, 3064, 3065,
+ 3067, 3068, 3066, 1674, 3069, 3069, 3070, 3071,
+ 3073, 3074, 3072, 1674, 3075, 3075, 3076, 3077,
+ 3079, 3080, 3078, 1674, 3081, 3081, 3082, 3083,
+ 3085, 3086, 3084, 1674, 3087, 3087, 3088, 3089,
+ 3091, 3092, 3090, 3090, 3090, 2275, 3093, 3093,
+ 3093, 2275, 3094, 3094, 3095, 3096, 3097, 3098,
+ 3099, 3099, 3100, 3101, 3090, 3090, 3090, 2275,
+ 3097, 3098, 2275, 3091, 3092, 69, 3079, 3080,
+ 69, 3067, 3068, 69, 3102, 1674, 3103, 3103,
+ 3104, 3105, 3107, 3108, 3106, 1674, 3109, 3109,
+ 3110, 3111, 3112, 3113, 3114, 3112, 1651, 3115,
+ 3116, 3115, 3115, 3115, 3116, 1651, 3113, 3114,
+ 69, 3117, 1674, 3118, 3118, 3119, 3120, 3122,
+ 3123, 3121, 1674, 3124, 3124, 3125, 3126, 3128,
+ 3129, 3127, 3127, 3127, 2275, 3130, 3130, 3130,
+ 2275, 3131, 3131, 3131, 2275, 3132, 3132, 3132,
+ 2275, 3134, 3133, 3135, 3135, 3135, 2275, 3136,
+ 3136, 3136, 2275, 3137, 3137, 3137, 2275, 3138,
+ 3138, 3138, 2275, 3140, 3134, 3140, 3140, 3140,
+ 3139, 3128, 3129, 69, 3141, 3141, 3141, 2275,
+ 3142, 3142, 3142, 2275, 3144, 3143, 3145, 3145,
+ 3145, 2275, 3146, 3146, 3146, 2275, 3147, 3144,
+ 3147, 3147, 3147, 3143, 3148, 3148, 3148, 2275,
+ 3149, 3149, 3149, 2275, 3150, 3143, 3151, 3151,
+ 3151, 2275, 3152, 3152, 3152, 2275, 3153, 3150,
+ 3153, 3153, 3153, 3143, 3155, 3155, 3156, 3157,
+ 3158, 3159, 3159, 3159, 19, 20, 3160, 3161,
+ 3159, 3159, 3159, 3154, 3162, 3162, 3163, 3164,
+ 3165, 3166, 67, 3167, 3166, 19, 20, 3168,
+ 3169, 121, 122, 3170, 3171, 67, 67, 3166,
+ 67, 3166, 67, 3166, 67, 697, 3173, 3173,
+ 3156, 3174, 3175, 3159, 3176, 3177, 3178, 3179,
+ 3180, 3181, 3182, 3183, 3184, 3185, 3186, 3187,
+ 3188, 3189, 3159, 3159, 3176, 3177, 3178, 3179,
+ 3180, 3181, 3182, 3183, 3184, 3185, 3186, 3187,
+ 3188, 3189, 19, 20, 3190, 3191, 3159, 3159,
+ 3159, 3172, 3173, 3173, 3156, 3174, 3175, 3159,
+ 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201,
+ 3202, 3203, 3204, 3205, 3206, 3207, 3159, 3159,
+ 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201,
+ 3202, 3203, 3204, 3205, 3206, 3207, 19, 20,
+ 3190, 3191, 3159, 3193, 3159, 3159, 3192, 3209,
+ 3209, 3210, 3211, 3212, 3213, 3213, 3213, 3214,
+ 3215, 3216, 3217, 3213, 3213, 3213, 3208, 3155,
+ 3155, 3156, 3218, 3219, 3159, 3194, 3195, 3196,
+ 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204,
+ 3205, 3206, 3207, 3159, 3159, 3194, 3195, 3196,
+ 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204,
+ 3205, 3206, 3207, 19, 20, 3220, 3161, 3159,
+ 3193, 3159, 3159, 3192, 3221, 3221, 3156, 3222,
+ 3223, 3159, 3159, 3159, 88, 89, 3224, 3225,
+ 3159, 3159, 3159, 697, 3226, 3226, 3163, 3227,
+ 3228, 3166, 67, 3167, 3166, 88, 89, 3224,
+ 3229, 96, 97, 3224, 3230, 67, 67, 3166,
+ 67, 3166, 67, 3166, 67, 697, 3162, 3162,
+ 3163, 3164, 3165, 3166, 67, 3233, 3234, 3235,
+ 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243,
+ 3244, 3245, 3246, 3167, 3166, 3233, 3234, 3235,
+ 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243,
+ 3244, 3245, 3246, 19, 20, 3168, 3169, 121,
+ 122, 3170, 3171, 67, 67, 3166, 3232, 67,
+ 3166, 67, 3166, 67, 3231, 3226, 3226, 3163,
+ 3227, 3228, 3166, 67, 3233, 3234, 3235, 3236,
+ 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244,
+ 3245, 3246, 3167, 3166, 3233, 3234, 3235, 3236,
+ 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244,
+ 3245, 3246, 88, 89, 3247, 3229, 96, 97,
+ 3247, 3230, 67, 67, 3166, 3232, 67, 3166,
+ 67, 3166, 67, 3231, 619, 619, 619, 820,
+ 817, 820, 819, 820, 817, 821, 817, 816,
+ 619, 619, 619, 957, 957, 958, 959, 927,
+ 929, 930, 928, 960, 961, 928, 928, 928,
+ 934, 619, 968, 968, 969, 970, 963, 971,
+ 972, 973, 973, 974, 975, 963, 963, 963,
+ 962, 971, 972, 962, 619, 985, 985, 986,
+ 987, 988, 989, 990, 991, 992, 993, 994,
+ 995, 996, 997, 998, 999, 1000, 1001, 988,
+ 989, 990, 991, 992, 993, 994, 995, 996,
+ 997, 998, 999, 1000, 1001, 1002, 1003, 1004,
+ 1004, 1005, 1006, 976, 1002, 1003, 976, 619,
+ 1445, 1445, 1446, 1447, 1448, 1449, 1450, 1450,
+ 1451, 1452, 1441, 1441, 1441, 1437, 1448, 1449,
+ 1437, 1467, 1467, 1468, 1469, 1471, 1472, 1470,
+ 1470, 1470, 1437, 1423, 1474, 1474, 1475, 1476,
+ 1477, 1478, 1479, 1479, 1480, 1481, 1470, 1470,
+ 1470, 1437, 1477, 1478, 1437, 1471, 1472, 1423,
+ 619, 619, 619, 619, 619, 619, 619, 619,
+ 619, 1849, 1849, 1850, 1851, 1852, 1853, 1854,
+ 1854, 1855, 1856, 1840, 1840, 1840, 69, 1852,
+ 1853, 69, 619, 619, 2020, 2020, 2021, 2022,
+ 2023, 2024, 1969, 1969, 2025, 2026, 1860, 2023,
+ 2024, 1860, 2002, 2002, 2003, 2004, 2006, 2007,
+ 1969, 1969, 2008, 2009, 2005, 1860, 2006, 2007,
+ 1860, 1983, 1983, 1984, 1985, 1987, 1988, 1969,
+ 1969, 1989, 1990, 1986, 1860, 1987, 1988, 1860,
+ 1963, 1963, 1964, 1965, 1967, 1968, 1969, 1969,
+ 1970, 1971, 1966, 1860, 1967, 1968, 1860, 619,
+ 619, 619, 619, 2218, 2218, 2219, 2220, 2221,
+ 2222, 2223, 2224, 2225, 2226, 2226, 2227, 2228,
+ 2217, 2224, 2225, 69, 619, 2283, 2283, 2284,
+ 2285, 2286, 2287, 2288, 2288, 2289, 2290, 2279,
+ 2279, 2279, 2275, 2286, 2287, 2275, 619, 2317,
+ 2317, 2318, 2319, 2320, 2321, 2322, 2322, 2323,
+ 2324, 2313, 2313, 2313, 2275, 2320, 2321, 2275,
+ 619, 2365, 2365, 2366, 2367, 2371, 2371, 2371,
+ 2371, 2376, 2377, 2371, 2371, 2378, 2379, 2384,
+ 2376, 2377, 2384, 2362, 2362, 2363, 2364, 2385,
+ 2372, 2373, 2385, 2385, 2385, 2384, 2372, 2373,
+ 2384, 2385, 2362, 2362, 2363, 2364, 2365, 2365,
+ 2366, 2367, 2368, 2368, 2369, 2370, 2371, 2371,
+ 2371, 2371, 2372, 2373, 2371, 2371, 2374, 2375,
+ 2376, 2377, 2371, 2371, 2378, 2379, 2380, 2381,
+ 2371, 2371, 2382, 2383, 2385, 2385, 2385, 2384,
+ 2372, 2376, 2380, 2373, 2377, 2381, 2384, 619,
+ 619, 619, 619, 619, 619, 619, 3094, 3094,
+ 3095, 3096, 3097, 3098, 3099, 3099, 3100, 3101,
+ 3090, 3090, 3090, 2275, 3097, 3098, 2275, 619,
+ 619, 619, 619, 0
+};
+
+static const short _zone_scanner_trans_targs[] = {
+ 0, 1, 1, 1, 2, 4, 17, 26,
+ 40, 47, 130, 63, 67, 75, 81, 97,
+ 100, 107, 118, 1060, 138, 1065, 243, 0,
+ 3, 3, 3, 2, 153, 153, 153, 153,
+ 153, 3, 156, 0, 3, 3, 3, 4,
+ 17, 26, 40, 47, 52, 63, 67, 75,
+ 81, 97, 100, 107, 118, 3, 156, 0,
+ 5, 5, 5, 214, 217, 221, 5, 11,
+ 10, 12, 21, 6, 5, 0, 5, 5,
+ 9, 5, 11, 10, 12, 21, 0, 7,
+ 7, 7, 1060, 8, 0, 7, 7, 7,
+ 1060, 8, 6, 10, 12, 12, 12, 13,
+ 1066, 163, 227, 1061, 14, 0, 14, 14,
+ 15, 159, 166, 167, 168, 169, 170, 171,
+ 172, 173, 174, 175, 176, 177, 178, 1068,
+ 223, 1066, 224, 1069, 226, 0, 16, 16,
+ 16, 1062, 246, 0, 16, 16, 16, 1062,
+ 246, 18, 22, 19, 20, 5, 5, 5,
+ 5, 11, 10, 12, 21, 21, 21, 21,
+ 23, 24, 25, 5, 5, 5, 5, 11,
+ 10, 12, 21, 27, 31, 39, 28, 29,
+ 30, 5, 5, 5, 5, 11, 10, 12,
+ 21, 32, 35, 33, 34, 5, 5, 5,
+ 5, 11, 10, 12, 21, 36, 37, 38,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 41, 42, 43, 45, 44, 5, 5, 5,
+ 5, 11, 10, 12, 21, 46, 5, 5,
+ 5, 5, 11, 10, 12, 21, 48, 49,
+ 50, 51, 5, 5, 5, 5, 11, 10,
+ 12, 21, 53, 56, 54, 54, 54, 54,
+ 128, 54, 54, 54, 4, 17, 26, 40,
+ 47, 55, 63, 67, 75, 81, 97, 100,
+ 107, 118, 54, 128, 57, 58, 59, 60,
+ 61, 62, 5, 5, 5, 5, 11, 10,
+ 12, 21, 64, 66, 65, 5, 5, 5,
+ 5, 11, 10, 12, 21, 5, 5, 5,
+ 5, 11, 10, 12, 21, 68, 70, 72,
+ 74, 69, 5, 5, 5, 5, 11, 10,
+ 12, 21, 71, 5, 5, 5, 5, 11,
+ 10, 12, 21, 73, 5, 5, 5, 5,
+ 11, 10, 12, 21, 5, 5, 5, 5,
+ 11, 10, 12, 21, 76, 80, 77, 78,
+ 79, 5, 5, 5, 5, 11, 10, 12,
+ 21, 5, 5, 5, 5, 11, 10, 12,
+ 21, 82, 86, 88, 83, 84, 85, 5,
+ 5, 5, 5, 11, 10, 12, 21, 87,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 5, 5, 5, 89, 5, 11, 10, 12,
+ 21, 90, 5, 5, 5, 91, 5, 11,
+ 10, 12, 21, 5, 5, 5, 92, 5,
+ 11, 10, 12, 21, 93, 94, 95, 96,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 98, 99, 5, 5, 5, 5, 11, 10,
+ 12, 21, 101, 102, 106, 5, 5, 5,
+ 5, 11, 10, 12, 21, 103, 104, 105,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 108, 110, 112, 114, 109, 5, 5, 5,
+ 5, 11, 10, 12, 21, 111, 5, 5,
+ 5, 5, 11, 10, 12, 21, 113, 5,
+ 5, 5, 5, 11, 10, 12, 21, 115,
+ 116, 117, 5, 5, 5, 5, 11, 10,
+ 12, 21, 119, 122, 124, 120, 121, 5,
+ 5, 5, 5, 11, 10, 12, 21, 123,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 125, 126, 0, 127, 0, 5, 5, 5,
+ 127, 5, 11, 10, 12, 21, 129, 129,
+ 129, 1063, 244, 131, 132, 132, 132, 132,
+ 137, 132, 132, 132, 133, 4, 17, 26,
+ 40, 47, 55, 63, 67, 75, 81, 97,
+ 100, 107, 118, 132, 137, 54, 54, 54,
+ 133, 134, 134, 134, 134, 134, 54, 128,
+ 135, 135, 136, 136, 136, 136, 136, 54,
+ 54, 54, 135, 54, 128, 0, 140, 181,
+ 187, 141, 142, 143, 144, 145, 146, 1064,
+ 0, 148, 148, 148, 148, 149, 148, 148,
+ 148, 148, 149, 0, 0, 151, 151, 151,
+ 151, 152, 151, 151, 151, 151, 152, 154,
+ 154, 155, 155, 155, 155, 155, 3, 3,
+ 3, 154, 3, 156, 0, 158, 158, 158,
+ 158, 228, 165, 229, 158, 158, 158, 158,
+ 228, 165, 229, 0, 160, 160, 160, 1061,
+ 13, 1066, 163, 1067, 227, 160, 160, 160,
+ 1067, 161, 161, 161, 1065, 162, 164, 164,
+ 164, 165, 165, 165, 179, 213, 1068, 0,
+ 182, 183, 184, 185, 186, 1064, 188, 189,
+ 1064, 0, 161, 161, 161, 1065, 162, 0,
+ 192, 192, 192, 1063, 193, 192, 192, 192,
+ 1063, 193, 0, 195, 195, 195, 1068, 179,
+ 1069, 213, 195, 195, 195, 1069, 210, 0,
+ 210, 210, 210, 211, 161, 161, 161, 1065,
+ 162, 212, 212, 212, 212, 212, 212, 213,
+ 213, 213, 215, 216, 5, 5, 5, 5,
+ 11, 10, 12, 21, 218, 219, 220, 5,
+ 5, 5, 5, 11, 10, 12, 21, 222,
+ 5, 5, 5, 5, 11, 10, 12, 21,
+ 225, 225, 225, 226, 226, 226, 227, 227,
+ 227, 229, 229, 229, 0, 248, 1070, 248,
+ 1070, 0, 250, 252, 257, 258, 253, 1071,
+ 251, 1071, 250, 252, 253, 252, 253, 254,
+ 0, 255, 256, 1071, 252, 251, 253, 1071,
+ 0, 260, 265, 261, 1072, 1073, 262, 0,
+ 263, 264, 1072, 260, 1073, 261, 265, 266,
+ 267, 0, 268, 269, 270, 265, 266, 267,
+ 0, 272, 272, 272, 272, 279, 0, 273,
+ 0, 274, 274, 274, 273, 276, 276, 276,
+ 276, 276, 1074, 275, 0, 277, 0, 277,
+ 278, 278, 278, 278, 278, 274, 274, 274,
+ 277, 1074, 275, 0, 281, 281, 281, 281,
+ 292, 282, 286, 291, 287, 283, 0, 284,
+ 284, 284, 282, 286, 287, 1075, 285, 284,
+ 284, 284, 1075, 285, 286, 287, 288, 0,
+ 289, 290, 286, 283, 287, 294, 294, 294,
+ 294, 310, 295, 0, 0, 296, 296, 296,
+ 1076, 300, 307, 0, 296, 296, 296, 297,
+ 301, 306, 302, 1076, 300, 307, 0, 298,
+ 299, 299, 299, 297, 301, 302, 1076, 300,
+ 299, 299, 299, 301, 302, 303, 0, 304,
+ 305, 301, 298, 302, 1077, 308, 308, 308,
+ 308, 309, 0, 312, 313, 314, 317, 315,
+ 315, 315, 315, 315, 316, 1078, 1079, 1080,
+ 0, 319, 319, 319, 319, 324, 1081, 1082,
+ 1083, 319, 319, 319, 320, 325, 333, 347,
+ 354, 359, 367, 371, 379, 385, 401, 404,
+ 411, 422, 319, 324, 1081, 1082, 1083, 319,
+ 319, 319, 321, 432, 436, 319, 324, 1081,
+ 1082, 1083, 322, 323, 319, 319, 319, 319,
+ 324, 1081, 1082, 1083, 326, 329, 327, 328,
+ 319, 319, 319, 319, 324, 1081, 1082, 1083,
+ 330, 331, 332, 319, 319, 319, 319, 324,
+ 1081, 1082, 1083, 334, 338, 346, 335, 336,
+ 337, 319, 319, 319, 319, 324, 1081, 1082,
+ 1083, 339, 342, 340, 341, 319, 319, 319,
+ 319, 324, 1081, 1082, 1083, 343, 344, 345,
+ 319, 319, 319, 319, 324, 1081, 1082, 1083,
+ 319, 319, 319, 319, 324, 1081, 1082, 1083,
+ 348, 349, 350, 352, 351, 319, 319, 319,
+ 319, 324, 1081, 1082, 1083, 353, 319, 319,
+ 319, 319, 324, 1081, 1082, 1083, 355, 356,
+ 357, 358, 319, 319, 319, 319, 324, 1081,
+ 1082, 1083, 360, 361, 362, 363, 364, 365,
+ 366, 319, 319, 319, 319, 324, 1081, 1082,
+ 1083, 368, 370, 369, 319, 319, 319, 319,
+ 324, 1081, 1082, 1083, 319, 319, 319, 319,
+ 324, 1081, 1082, 1083, 372, 374, 376, 378,
+ 373, 319, 319, 319, 319, 324, 1081, 1082,
+ 1083, 375, 319, 319, 319, 319, 324, 1081,
+ 1082, 1083, 377, 319, 319, 319, 319, 324,
+ 1081, 1082, 1083, 319, 319, 319, 319, 324,
+ 1081, 1082, 1083, 380, 384, 381, 382, 383,
+ 319, 319, 319, 319, 324, 1081, 1082, 1083,
+ 319, 319, 319, 319, 324, 1081, 1082, 1083,
+ 386, 390, 392, 387, 388, 389, 319, 319,
+ 319, 319, 324, 1081, 1082, 1083, 391, 319,
+ 319, 319, 319, 324, 1081, 1082, 1083, 319,
+ 319, 319, 393, 319, 324, 1081, 1082, 1083,
+ 394, 319, 319, 319, 395, 319, 324, 1081,
+ 1082, 1083, 319, 319, 319, 396, 319, 324,
+ 1081, 1082, 1083, 397, 398, 399, 400, 319,
+ 319, 319, 319, 324, 1081, 1082, 1083, 402,
+ 403, 319, 319, 319, 319, 324, 1081, 1082,
+ 1083, 405, 406, 410, 319, 319, 319, 319,
+ 324, 1081, 1082, 1083, 407, 408, 409, 319,
+ 319, 319, 319, 324, 1081, 1082, 1083, 319,
+ 319, 319, 319, 324, 1081, 1082, 1083, 412,
+ 414, 416, 418, 413, 319, 319, 319, 319,
+ 324, 1081, 1082, 1083, 415, 319, 319, 319,
+ 319, 324, 1081, 1082, 1083, 417, 319, 319,
+ 319, 319, 324, 1081, 1082, 1083, 419, 420,
+ 421, 319, 319, 319, 319, 324, 1081, 1082,
+ 1083, 423, 426, 428, 424, 425, 319, 319,
+ 319, 319, 324, 1081, 1082, 1083, 427, 319,
+ 319, 319, 319, 324, 1081, 1082, 1083, 429,
+ 430, 431, 319, 319, 319, 431, 319, 324,
+ 1081, 1082, 1083, 433, 434, 435, 319, 319,
+ 319, 319, 324, 1081, 1082, 1083, 437, 319,
+ 319, 319, 319, 324, 1081, 1082, 1083, 0,
+ 439, 439, 439, 439, 446, 0, 440, 441,
+ 441, 441, 440, 441, 445, 0, 441, 441,
+ 441, 442, 441, 445, 443, 443, 443, 443,
+ 443, 444, 1084, 1085, 1086, 448, 448, 448,
+ 448, 456, 449, 455, 1087, 1087, 1087, 455,
+ 1088, 1087, 1091, 450, 450, 450, 451, 450,
+ 454, 452, 452, 452, 452, 452, 453, 1088,
+ 1089, 1090, 450, 450, 450, 450, 454, 0,
+ 458, 459, 474, 504, 512, 525, 1092, 458,
+ 460, 461, 1092, 462, 1092, 463, 464, 465,
+ 466, 467, 468, 469, 470, 471, 472, 473,
+ 1092, 475, 476, 482, 477, 478, 479, 480,
+ 481, 1092, 483, 484, 485, 486, 495, 487,
+ 488, 489, 490, 491, 492, 493, 494, 1092,
+ 496, 497, 498, 499, 500, 501, 502, 503,
+ 1092, 505, 506, 507, 508, 509, 510, 511,
+ 1092, 513, 514, 515, 516, 517, 518, 519,
+ 522, 520, 521, 1092, 523, 524, 1092, 526,
+ 527, 528, 531, 529, 530, 1092, 532, 533,
+ 534, 546, 549, 1092, 535, 536, 537, 538,
+ 539, 540, 541, 542, 543, 544, 545, 1092,
+ 547, 548, 1092, 550, 551, 1092, 0, 553,
+ 554, 560, 577, 580, 586, 590, 1093, 553,
+ 555, 556, 557, 558, 559, 1093, 561, 567,
+ 573, 562, 563, 564, 565, 566, 1093, 568,
+ 570, 569, 1093, 571, 572, 1093, 574, 575,
+ 576, 1093, 578, 579, 1093, 581, 583, 582,
+ 1093, 584, 585, 1093, 587, 588, 589, 1093,
+ 591, 592, 1093, 0, 594, 1094, 594, 596,
+ 1095, 598, 599, 599, 599, 599, 628, 599,
+ 599, 599, 600, 599, 628, 601, 601, 601,
+ 601, 627, 0, 601, 601, 601, 602, 601,
+ 627, 603, 603, 603, 602, 603, 626, 603,
+ 603, 603, 604, 603, 626, 0, 605, 605,
+ 605, 604, 623, 623, 623, 623, 623, 605,
+ 622, 605, 605, 605, 606, 605, 622, 607,
+ 607, 607, 606, 619, 619, 619, 619, 619,
+ 607, 618, 607, 607, 607, 608, 607, 618,
+ 609, 609, 609, 608, 615, 615, 615, 615,
+ 615, 609, 614, 609, 609, 609, 610, 609,
+ 614, 1096, 610, 611, 611, 611, 611, 611,
+ 612, 612, 613, 613, 613, 613, 613, 1096,
+ 612, 616, 616, 617, 617, 617, 617, 617,
+ 609, 609, 609, 616, 609, 614, 620, 620,
+ 621, 621, 621, 621, 621, 607, 607, 607,
+ 620, 607, 618, 624, 624, 625, 625, 625,
+ 625, 625, 605, 605, 605, 624, 605, 622,
+ 630, 631, 631, 631, 631, 633, 632, 631,
+ 631, 631, 631, 633, 1097, 635, 636, 636,
+ 636, 636, 638, 636, 636, 636, 637, 636,
+ 638, 1098, 640, 641, 641, 641, 640, 641,
+ 643, 641, 641, 641, 642, 641, 643, 1099,
+ 645, 646, 646, 646, 646, 647, 1100, 1101,
+ 1102, 646, 646, 646, 646, 647, 1100, 1101,
+ 1102, 649, 1103, 649, 0, 651, 652, 652,
+ 652, 651, 652, 704, 652, 652, 652, 653,
+ 657, 699, 652, 704, 654, 654, 654, 653,
+ 654, 703, 654, 654, 654, 655, 654, 703,
+ 656, 656, 656, 701, 655, 656, 700, 656,
+ 656, 656, 656, 700, 658, 658, 658, 658,
+ 698, 659, 660, 660, 660, 659, 660, 697,
+ 660, 660, 660, 661, 665, 692, 660, 697,
+ 662, 662, 662, 661, 662, 696, 662, 662,
+ 662, 663, 662, 696, 664, 664, 664, 694,
+ 663, 664, 693, 664, 664, 664, 664, 693,
+ 666, 666, 666, 666, 691, 667, 668, 668,
+ 669, 669, 669, 688, 668, 690, 669, 687,
+ 1104, 1111, 1112, 669, 669, 669, 670, 669,
+ 687, 1104, 1111, 1112, 671, 671, 671, 684,
+ 670, 686, 671, 683, 1104, 1109, 1110, 671,
+ 671, 671, 672, 671, 683, 1109, 1110, 673,
+ 673, 673, 680, 672, 682, 673, 679, 1104,
+ 1107, 1108, 673, 673, 673, 674, 673, 679,
+ 1107, 1108, 675, 675, 675, 677, 674, 675,
+ 676, 1104, 1105, 1106, 675, 675, 675, 675,
+ 676, 1105, 1106, 675, 675, 675, 678, 675,
+ 676, 1104, 1105, 1106, 678, 673, 673, 673,
+ 681, 682, 673, 679, 1104, 1107, 1108, 681,
+ 671, 671, 671, 685, 686, 671, 683, 1104,
+ 1109, 1110, 685, 669, 669, 669, 689, 690,
+ 669, 687, 1104, 1111, 1112, 689, 666, 666,
+ 666, 666, 691, 664, 664, 664, 695, 664,
+ 693, 695, 658, 658, 658, 658, 698, 656,
+ 656, 656, 702, 656, 700, 702, 706, 707,
+ 707, 707, 706, 707, 715, 707, 707, 707,
+ 708, 707, 715, 709, 709, 709, 708, 709,
+ 714, 709, 709, 709, 710, 709, 714, 711,
+ 711, 711, 710, 711, 713, 711, 711, 711,
+ 712, 711, 713, 1113, 717, 718, 718, 718,
+ 717, 718, 732, 718, 718, 718, 719, 718,
+ 732, 720, 720, 720, 719, 720, 731, 721,
+ 720, 720, 720, 720, 731, 722, 722, 722,
+ 722, 730, 723, 722, 722, 722, 722, 730,
+ 724, 724, 724, 724, 729, 725, 724, 724,
+ 724, 724, 729, 726, 726, 726, 726, 728,
+ 726, 726, 726, 727, 726, 728, 1114, 734,
+ 735, 735, 735, 735, 743, 736, 737, 737,
+ 737, 736, 737, 742, 737, 737, 737, 738,
+ 737, 742, 739, 739, 739, 739, 741, 740,
+ 1115, 0, 744, 745, 744, 744, 746, 752,
+ 744, 751, 1116, 1117, 1118, 746, 752, 747,
+ 0, 748, 748, 749, 750, 744, 744, 744,
+ 750, 744, 751, 1116, 1117, 1118, 753, 754,
+ 754, 749, 756, 757, 757, 757, 756, 757,
+ 767, 757, 757, 757, 758, 757, 767, 759,
+ 759, 759, 759, 766, 760, 761, 761, 761,
+ 760, 761, 765, 0, 761, 761, 761, 762,
+ 761, 765, 763, 763, 763, 763, 763, 764,
+ 1119, 1120, 1121, 769, 770, 770, 770, 769,
+ 770, 777, 770, 770, 770, 771, 770, 777,
+ 772, 772, 772, 771, 772, 776, 772, 772,
+ 772, 773, 772, 776, 774, 774, 774, 774,
+ 774, 775, 1122, 1123, 1124, 779, 780, 780,
+ 780, 779, 780, 816, 0, 780, 780, 780,
+ 781, 795, 802, 809, 780, 816, 782, 782,
+ 782, 782, 794, 0, 783, 784, 784, 784,
+ 783, 784, 793, 784, 784, 784, 785, 784,
+ 793, 0, 786, 786, 786, 789, 789, 789,
+ 791, 791, 791, 1125, 786, 788, 1128, 1129,
+ 789, 790, 1126, 1127, 791, 792, 1130, 1131,
+ 0, 787, 796, 796, 796, 796, 801, 797,
+ 798, 798, 798, 797, 798, 800, 0, 798,
+ 798, 798, 799, 798, 800, 0, 799, 786,
+ 786, 786, 789, 789, 789, 791, 791, 791,
+ 1125, 786, 788, 1128, 1129, 789, 790, 1126,
+ 1127, 791, 792, 1130, 1131, 803, 803, 803,
+ 803, 808, 804, 805, 805, 805, 804, 805,
+ 807, 805, 805, 805, 806, 805, 807, 806,
+ 786, 786, 786, 789, 789, 789, 791, 791,
+ 791, 1125, 786, 788, 1128, 1129, 789, 790,
+ 1126, 1127, 791, 792, 1130, 1131, 810, 810,
+ 810, 810, 815, 811, 812, 812, 812, 811,
+ 812, 814, 812, 812, 812, 813, 812, 814,
+ 786, 786, 786, 789, 789, 789, 791, 791,
+ 791, 1125, 786, 788, 1128, 1129, 789, 790,
+ 1126, 1127, 791, 792, 1130, 1131, 0, 818,
+ 852, 860, 874, 881, 886, 894, 898, 906,
+ 912, 928, 931, 938, 949, 819, 819, 819,
+ 843, 846, 850, 819, 842, 819, 819, 819,
+ 820, 819, 842, 821, 821, 821, 821, 841,
+ 822, 823, 823, 823, 822, 823, 840, 823,
+ 823, 823, 824, 823, 840, 825, 825, 825,
+ 824, 825, 839, 0, 825, 825, 825, 826,
+ 825, 839, 827, 827, 827, 826, 827, 838,
+ 827, 827, 827, 828, 827, 838, 829, 829,
+ 829, 828, 829, 837, 829, 829, 829, 830,
+ 829, 837, 831, 831, 831, 830, 831, 836,
+ 831, 831, 831, 832, 831, 836, 833, 833,
+ 833, 833, 835, 833, 833, 833, 834, 833,
+ 835, 1132, 844, 845, 819, 819, 819, 819,
+ 842, 847, 848, 849, 819, 819, 819, 819,
+ 842, 851, 819, 819, 819, 819, 842, 853,
+ 856, 854, 855, 819, 819, 819, 819, 842,
+ 857, 858, 859, 819, 819, 819, 819, 842,
+ 861, 865, 873, 862, 863, 864, 819, 819,
+ 819, 819, 842, 866, 869, 867, 868, 819,
+ 819, 819, 819, 842, 870, 871, 872, 819,
+ 819, 819, 819, 842, 819, 819, 819, 819,
+ 842, 875, 876, 877, 879, 878, 819, 819,
+ 819, 819, 842, 880, 819, 819, 819, 819,
+ 842, 882, 883, 884, 885, 819, 819, 819,
+ 819, 842, 887, 888, 889, 890, 891, 892,
+ 893, 819, 819, 819, 819, 842, 895, 897,
+ 896, 819, 819, 819, 819, 842, 819, 819,
+ 819, 819, 842, 899, 901, 903, 905, 900,
+ 819, 819, 819, 819, 842, 902, 819, 819,
+ 819, 819, 842, 904, 819, 819, 819, 819,
+ 842, 819, 819, 819, 819, 842, 907, 911,
+ 908, 909, 910, 819, 819, 819, 819, 842,
+ 819, 819, 819, 819, 842, 913, 917, 919,
+ 914, 915, 916, 819, 819, 819, 819, 842,
+ 918, 819, 819, 819, 819, 842, 819, 819,
+ 819, 920, 819, 842, 921, 819, 819, 819,
+ 922, 819, 842, 819, 819, 819, 923, 819,
+ 842, 924, 925, 926, 927, 819, 819, 819,
+ 819, 842, 929, 930, 819, 819, 819, 819,
+ 842, 932, 933, 937, 819, 819, 819, 819,
+ 842, 934, 935, 936, 819, 819, 819, 819,
+ 842, 819, 819, 819, 819, 842, 939, 941,
+ 943, 945, 940, 819, 819, 819, 819, 842,
+ 942, 819, 819, 819, 819, 842, 944, 819,
+ 819, 819, 819, 842, 946, 947, 948, 819,
+ 819, 819, 819, 842, 950, 953, 955, 951,
+ 952, 819, 819, 819, 819, 842, 954, 819,
+ 819, 819, 819, 842, 956, 957, 0, 958,
+ 819, 819, 819, 958, 819, 842, 960, 961,
+ 1133, 963, 964, 964, 964, 963, 964, 972,
+ 964, 964, 964, 965, 964, 972, 966, 966,
+ 966, 965, 966, 971, 966, 966, 966, 967,
+ 966, 971, 968, 968, 968, 968, 970, 969,
+ 1134, 974, 1135, 976, 977, 977, 977, 976,
+ 977, 1003, 977, 977, 977, 978, 977, 1003,
+ 979, 979, 979, 978, 979, 1002, 979, 979,
+ 979, 980, 979, 1002, 981, 981, 981, 980,
+ 981, 1001, 981, 981, 981, 982, 999, 981,
+ 1001, 983, 983, 983, 983, 998, 0, 983,
+ 983, 983, 984, 983, 998, 985, 986, 996,
+ 987, 988, 995, 989, 993, 990, 991, 991,
+ 992, 984, 1136, 994, 997, 1000, 999, 1005,
+ 1006, 1006, 1006, 1005, 1006, 1016, 1006, 1006,
+ 1006, 1007, 1006, 1016, 1008, 1008, 1008, 1007,
+ 1008, 1015, 1008, 1008, 1008, 1009, 1008, 1015,
+ 1010, 1010, 1010, 1009, 1010, 1014, 1010, 1010,
+ 1010, 1011, 1012, 1010, 1014, 1137, 1013, 1012,
+ 1018, 1019, 1019, 1019, 1018, 1019, 1029, 1019,
+ 1019, 1019, 1020, 1019, 1029, 1021, 1021, 1021,
+ 1020, 1021, 1028, 1021, 1021, 1021, 1022, 1021,
+ 1028, 1023, 1023, 1023, 1022, 1023, 1027, 1023,
+ 1023, 1023, 1024, 1023, 1027, 1025, 1025, 1025,
+ 1025, 1025, 1026, 1138, 1139, 1140, 1031, 1032,
+ 1032, 1032, 1031, 1032, 1034, 1032, 1032, 1032,
+ 1033, 1032, 1034, 1141, 1033, 1036, 1037, 1037,
+ 1037, 1036, 1037, 1047, 1037, 1037, 1037, 1038,
+ 1037, 1047, 1039, 1040, 1041, 0, 1042, 1043,
+ 1044, 1045, 1046, 0, 1142, 1049, 1050, 0,
+ 1051, 1052, 1053, 1143, 1055, 1056, 1057, 1058,
+ 1059, 1144, 0, 1, 139, 1, 1, 147,
+ 1065, 243, 14, 180, 14, 14, 190, 209,
+ 1068, 223, 1069, 226, 0, 129, 129, 129,
+ 157, 230, 231, 232, 233, 245, 235, 236,
+ 237, 238, 239, 240, 241, 242, 1063, 244,
+ 0, 150, 157, 230, 231, 232, 233, 234,
+ 235, 236, 237, 238, 239, 240, 241, 242,
+ 0, 1, 139, 1, 1, 147, 1060, 138,
+ 1065, 243, 1, 1, 1065, 161, 161, 161,
+ 1065, 162, 165, 165, 165, 179, 213, 0,
+ 191, 194, 196, 197, 198, 199, 200, 201,
+ 202, 203, 204, 205, 206, 207, 208, 1065
+};
+
+static const short _zone_scanner_trans_actions[] = {
+ 1872, 0, 5, 7, 506, 659, 659, 659,
+ 659, 659, 659, 659, 659, 659, 659, 659,
+ 659, 659, 659, 3, 0, 3, 0, 2012,
+ 101, 674, 677, 41, 55, 53, 51, 0,
+ 57, 671, 101, 345, 0, 5, 7, 95,
+ 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 95, 95, 95, 3, 0, 1592,
+ 1595, 2384, 2388, 0, 0, 0, 2380, 1595,
+ 2392, 3481, 2392, 339, 0, 337, 5, 7,
+ 0, 3, 0, 339, 356, 339, 1571, 343,
+ 1580, 1583, 2372, 343, 9, 0, 5, 7,
+ 1709, 0, 1586, 341, 0, 5, 7, 0,
+ 2368, 339, 339, 359, 0, 3086, 5, 7,
+ 1860, 2096, 2096, 2096, 2096, 2096, 2096, 2096,
+ 2096, 2096, 2096, 2096, 2096, 2096, 2096, 3,
+ 0, 1574, 339, 356, 339, 3782, 680, 2100,
+ 2104, 3256, 680, 1589, 0, 5, 7, 359,
+ 0, 0, 0, 0, 0, 1649, 2676, 2680,
+ 2672, 1649, 2684, 3586, 2684, 0, 5, 7,
+ 0, 0, 0, 1601, 2420, 2424, 2416, 1601,
+ 2428, 3506, 2428, 0, 0, 0, 0, 0,
+ 0, 1676, 2820, 2824, 2816, 1676, 2828, 3631,
+ 2828, 0, 0, 0, 0, 1652, 2692, 2696,
+ 2688, 1652, 2700, 3591, 2700, 0, 0, 0,
+ 1673, 2804, 2808, 2800, 1673, 2812, 3626, 2812,
+ 1658, 2724, 2728, 2720, 1658, 2732, 3601, 2732,
+ 0, 0, 0, 0, 0, 1703, 2964, 2968,
+ 2960, 1703, 2972, 3676, 2972, 0, 1706, 2980,
+ 2984, 2976, 1706, 2988, 3681, 2988, 0, 0,
+ 0, 0, 1610, 2468, 2472, 2464, 1610, 2476,
+ 3521, 2476, 0, 0, 99, 665, 668, 662,
+ 99, 0, 5, 7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 1664, 2756, 2760, 2752, 1664, 2764,
+ 3611, 2764, 0, 0, 0, 1631, 2580, 2584,
+ 2576, 1631, 2588, 3556, 2588, 1646, 2660, 2664,
+ 2656, 1646, 2668, 3581, 2668, 0, 0, 0,
+ 0, 0, 1694, 2916, 2920, 2912, 1694, 2924,
+ 3661, 2924, 0, 1697, 2932, 2936, 2928, 1697,
+ 2940, 3666, 2940, 0, 1637, 2612, 2616, 2608,
+ 1637, 2620, 3566, 2620, 1700, 2948, 2952, 2944,
+ 1700, 2956, 3671, 2956, 0, 0, 0, 0,
+ 0, 1613, 2484, 2488, 2480, 1613, 2492, 3526,
+ 2492, 1616, 2500, 2504, 2496, 1616, 2508, 3531,
+ 2508, 0, 0, 0, 0, 0, 0, 1643,
+ 2644, 2648, 2640, 1643, 2652, 3576, 2652, 0,
+ 1691, 2900, 2904, 2896, 1691, 2908, 3656, 2908,
+ 1598, 2404, 2408, 0, 2400, 1598, 2412, 3501,
+ 2412, 0, 1670, 2788, 2792, 0, 2784, 1670,
+ 2796, 3621, 2796, 1679, 2836, 2840, 0, 2832,
+ 1679, 2844, 3636, 2844, 0, 0, 0, 0,
+ 1682, 2852, 2856, 2848, 1682, 2860, 3641, 2860,
+ 0, 0, 1607, 2452, 2456, 2448, 1607, 2460,
+ 3516, 2460, 0, 0, 0, 1622, 2532, 2536,
+ 2528, 1622, 2540, 3541, 2540, 0, 0, 0,
+ 1667, 2772, 2776, 2768, 1667, 2780, 3616, 2780,
+ 1628, 2564, 2568, 2560, 1628, 2572, 3551, 2572,
+ 0, 0, 0, 0, 0, 1604, 2436, 2440,
+ 2432, 1604, 2444, 3511, 2444, 0, 1688, 2884,
+ 2888, 2880, 1688, 2892, 3651, 2892, 0, 1640,
+ 2628, 2632, 2624, 1640, 2636, 3571, 2636, 0,
+ 0, 0, 1661, 2740, 2744, 2736, 1661, 2748,
+ 3606, 2748, 0, 0, 0, 0, 0, 1685,
+ 2868, 2872, 2864, 1685, 2876, 3646, 2876, 0,
+ 1619, 2516, 2520, 2512, 1619, 2524, 3536, 2524,
+ 0, 0, 518, 506, 1876, 578, 1992, 1996,
+ 41, 1988, 578, 2000, 3216, 2000, 0, 5,
+ 7, 3, 0, 0, 99, 665, 668, 662,
+ 99, 0, 5, 7, 506, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 3, 0, 101, 674, 677,
+ 41, 55, 53, 51, 0, 57, 671, 101,
+ 2016, 41, 55, 53, 51, 0, 57, 599,
+ 2040, 2044, 3226, 2036, 599, 93, 89, 89,
+ 89, 0, 0, 0, 0, 0, 0, 87,
+ 37, 33, 455, 458, 452, 33, 0, 5,
+ 7, 3, 0, 0, 3071, 461, 1796, 1804,
+ 1792, 461, 0, 5, 7, 3, 0, 2016,
+ 41, 55, 53, 51, 0, 57, 599, 2040,
+ 2044, 3226, 2036, 599, 1836, 1820, 3036, 3051,
+ 3021, 1820, 3698, 3056, 0, 5, 7, 3,
+ 0, 356, 339, 2376, 2396, 3486, 3491, 3800,
+ 2396, 3855, 3496, 3848, 3496, 0, 5, 7,
+ 1744, 0, 5, 7, 359, 0, 0, 5,
+ 7, 0, 5, 7, 0, 339, 359, 2360,
+ 0, 0, 0, 0, 0, 79, 0, 0,
+ 75, 1828, 464, 1800, 1808, 3011, 464, 3813,
+ 1812, 3026, 3041, 3692, 1812, 0, 5, 7,
+ 359, 0, 3076, 3061, 3704, 3710, 3806, 3061,
+ 3862, 3716, 0, 5, 7, 1744, 1816, 479,
+ 3031, 3046, 3016, 1816, 343, 365, 371, 1748,
+ 343, 343, 1580, 1583, 0, 5, 7, 0,
+ 5, 7, 0, 0, 1634, 2596, 2600, 2592,
+ 1634, 2604, 3561, 2604, 0, 0, 0, 1625,
+ 2548, 2552, 2544, 1625, 2556, 3546, 2556, 0,
+ 1655, 2708, 2712, 2704, 1655, 2716, 3596, 2716,
+ 0, 5, 7, 0, 5, 7, 0, 5,
+ 7, 0, 5, 7, 482, 380, 2996, 11,
+ 1756, 27, 1772, 1772, 25, 0, 419, 1760,
+ 17, 404, 383, 383, 13, 15, 0, 386,
+ 395, 19, 19, 3001, 389, 392, 21, 416,
+ 620, 65, 0, 0, 1, 617, 623, 2052,
+ 69, 69, 626, 629, 2048, 71, 65, 0,
+ 0, 67, 623, 69, 69, 629, 71, 71,
+ 73, 0, 5, 7, 3, 0, 509, 506,
+ 3221, 0, 5, 7, 41, 55, 53, 51,
+ 0, 57, 2056, 0, 374, 2016, 2004, 41,
+ 55, 53, 51, 0, 57, 59, 590, 593,
+ 3226, 3231, 59, 77, 0, 5, 7, 3,
+ 0, 3236, 3236, 632, 2060, 17, 377, 23,
+ 407, 410, 383, 383, 13, 3006, 23, 0,
+ 5, 7, 2064, 0, 15, 0, 386, 398,
+ 19, 19, 389, 392, 21, 0, 5, 7,
+ 3, 0, 635, 83, 644, 81, 638, 641,
+ 3241, 81, 81, 650, 0, 5, 7, 3246,
+ 3246, 647, 2068, 2072, 0, 0, 85, 17,
+ 413, 1764, 1768, 383, 383, 13, 3686, 413,
+ 0, 5, 7, 15, 0, 386, 401, 19,
+ 19, 389, 392, 21, 1724, 0, 5, 7,
+ 3, 0, 125, 117, 119, 121, 0, 123,
+ 0, 5, 7, 3, 0, 1, 350, 1,
+ 309, 307, 1496, 1499, 1493, 307, 2332, 3476,
+ 2332, 0, 5, 7, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 1502, 1732, 1502, 231,
+ 1154, 1157, 0, 0, 0, 1151, 231, 2180,
+ 3286, 2180, 0, 0, 257, 1271, 1274, 1268,
+ 257, 2232, 3351, 2232, 0, 0, 0, 0,
+ 267, 1316, 1319, 1313, 267, 2252, 3376, 2252,
+ 0, 0, 0, 235, 1172, 1175, 1169, 235,
+ 2188, 3296, 2188, 0, 0, 0, 0, 0,
+ 0, 285, 1397, 1400, 1394, 285, 2288, 3421,
+ 2288, 0, 0, 0, 0, 269, 1325, 1328,
+ 1322, 269, 2256, 3381, 2256, 0, 0, 0,
+ 283, 1388, 1391, 1385, 283, 2284, 3416, 2284,
+ 273, 1343, 1346, 1340, 273, 2264, 3391, 2264,
+ 0, 0, 0, 0, 0, 303, 1478, 1481,
+ 1475, 303, 2324, 3466, 2324, 0, 305, 1487,
+ 1490, 1484, 305, 2328, 3471, 2328, 0, 0,
+ 0, 0, 241, 1199, 1202, 1196, 241, 2200,
+ 3311, 2200, 0, 0, 0, 0, 0, 0,
+ 0, 277, 1361, 1364, 1358, 277, 2272, 3401,
+ 2272, 0, 0, 0, 255, 1262, 1265, 1259,
+ 255, 2228, 3346, 2228, 265, 1307, 1310, 1304,
+ 265, 2248, 3371, 2248, 0, 0, 0, 0,
+ 0, 297, 1451, 1454, 1448, 297, 2312, 3451,
+ 2312, 0, 299, 1460, 1463, 1457, 299, 2316,
+ 3456, 2316, 0, 259, 1280, 1283, 1277, 259,
+ 2236, 3356, 2236, 301, 1469, 1472, 1466, 301,
+ 2320, 3461, 2320, 0, 0, 0, 0, 0,
+ 243, 1208, 1211, 1205, 243, 2204, 3316, 2204,
+ 245, 1217, 1220, 1214, 245, 2208, 3321, 2208,
+ 0, 0, 0, 0, 0, 0, 263, 1298,
+ 1301, 1295, 263, 2244, 3366, 2244, 0, 295,
+ 1442, 1445, 1439, 295, 2308, 3446, 2308, 233,
+ 1163, 1166, 0, 1160, 233, 2184, 3291, 2184,
+ 0, 281, 1379, 1382, 0, 1376, 281, 2280,
+ 3411, 2280, 287, 1406, 1409, 0, 1403, 287,
+ 2292, 3426, 2292, 0, 0, 0, 0, 289,
+ 1415, 1418, 1412, 289, 2296, 3431, 2296, 0,
+ 0, 239, 1190, 1193, 1187, 239, 2196, 3306,
+ 2196, 0, 0, 0, 249, 1235, 1238, 1232,
+ 249, 2216, 3331, 2216, 0, 0, 0, 279,
+ 1370, 1373, 1367, 279, 2276, 3406, 2276, 253,
+ 1253, 1256, 1250, 253, 2224, 3341, 2224, 0,
+ 0, 0, 0, 0, 237, 1181, 1184, 1178,
+ 237, 2192, 3301, 2192, 0, 293, 1433, 1436,
+ 1430, 293, 2304, 3441, 2304, 0, 261, 1289,
+ 1292, 1286, 261, 2240, 3361, 2240, 0, 0,
+ 0, 275, 1352, 1355, 1349, 275, 2268, 3396,
+ 2268, 0, 0, 0, 0, 0, 291, 1424,
+ 1427, 1421, 291, 2300, 3436, 2300, 0, 247,
+ 1226, 1229, 1223, 247, 2212, 3326, 2212, 0,
+ 0, 506, 229, 1145, 1148, 41, 1142, 229,
+ 2176, 3281, 2176, 0, 0, 0, 251, 1244,
+ 1247, 1241, 251, 2220, 3336, 2220, 0, 271,
+ 1334, 1337, 1331, 271, 2260, 3386, 2260, 323,
+ 0, 5, 7, 3, 0, 512, 506, 49,
+ 584, 587, 41, 581, 49, 2164, 0, 5,
+ 7, 113, 3, 0, 115, 0, 5, 7,
+ 3, 0, 713, 1728, 713, 0, 5, 7,
+ 3, 0, 506, 506, 347, 1716, 1720, 41,
+ 1, 1712, 347, 0, 5, 7, 113, 3,
+ 0, 115, 0, 5, 7, 3, 0, 713,
+ 1728, 713, 49, 584, 587, 581, 49, 329,
+ 506, 0, 0, 0, 0, 0, 539, 41,
+ 0, 0, 722, 0, 725, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 731, 0, 0, 0, 0, 0, 0, 0,
+ 0, 743, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 746,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 749, 0, 0, 0, 0, 0, 0, 0,
+ 752, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 755, 0, 0, 758, 0,
+ 0, 0, 0, 0, 0, 719, 0, 0,
+ 0, 0, 0, 728, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 734,
+ 0, 0, 737, 0, 0, 740, 331, 506,
+ 0, 0, 0, 0, 0, 0, 551, 41,
+ 0, 0, 0, 0, 0, 779, 0, 0,
+ 0, 0, 0, 0, 0, 0, 782, 0,
+ 0, 0, 776, 0, 0, 770, 0, 0,
+ 0, 773, 0, 0, 788, 0, 0, 0,
+ 767, 0, 0, 761, 0, 0, 0, 764,
+ 0, 0, 785, 686, 683, 2116, 103, 485,
+ 488, 485, 500, 1848, 1852, 1844, 500, 0,
+ 5, 7, 485, 3, 0, 500, 1848, 1852,
+ 1844, 500, 515, 0, 5, 7, 506, 3,
+ 0, 47, 572, 575, 41, 569, 47, 0,
+ 5, 7, 506, 3, 0, 2008, 47, 572,
+ 575, 41, 55, 53, 51, 0, 57, 569,
+ 47, 0, 5, 7, 506, 3, 0, 47,
+ 572, 575, 41, 55, 53, 51, 0, 57,
+ 569, 47, 0, 5, 7, 506, 3, 0,
+ 47, 572, 575, 41, 55, 53, 51, 0,
+ 57, 569, 47, 0, 5, 7, 506, 3,
+ 0, 566, 41, 55, 53, 51, 0, 57,
+ 2016, 41, 55, 53, 51, 0, 57, 2020,
+ 3226, 2016, 41, 55, 53, 51, 0, 57,
+ 596, 2028, 2032, 3226, 2024, 596, 2016, 41,
+ 55, 53, 51, 0, 57, 596, 2028, 2032,
+ 3226, 2024, 596, 2016, 41, 55, 53, 51,
+ 0, 57, 596, 2028, 2032, 3226, 2024, 596,
+ 422, 31, 437, 440, 434, 31, 422, 0,
+ 5, 7, 3, 0, 431, 485, 500, 1848,
+ 1852, 1844, 500, 0, 5, 7, 485, 3,
+ 0, 488, 506, 563, 1980, 1984, 41, 1976,
+ 563, 0, 5, 7, 485, 3, 0, 488,
+ 422, 31, 437, 440, 434, 31, 431, 1776,
+ 431, 0, 5, 7, 3, 0, 1, 350,
+ 1, 683, 2132, 103, 1562, 2336, 311, 1508,
+ 1511, 41, 1505, 311, 0, 5, 7, 506,
+ 0, 0, 3, 0, 315, 1526, 1529, 41,
+ 1523, 315, 0, 5, 7, 3211, 3, 0,
+ 521, 1908, 1912, 0, 41, 1904, 521, 0,
+ 5, 7, 3, 0, 0, 5, 7, 3,
+ 0, 506, 313, 1517, 1520, 41, 1514, 313,
+ 0, 5, 7, 506, 0, 0, 3, 0,
+ 317, 1535, 1538, 41, 1532, 317, 0, 5,
+ 7, 3211, 3, 0, 524, 1920, 1924, 0,
+ 41, 1916, 524, 0, 5, 7, 3, 0,
+ 0, 5, 7, 3, 0, 0, 3206, 3794,
+ 527, 1932, 1936, 0, 41, 527, 1928, 527,
+ 3186, 3758, 3186, 0, 5, 7, 3206, 3,
+ 0, 1559, 1736, 1559, 530, 1944, 1948, 0,
+ 41, 530, 1940, 530, 3191, 3764, 3191, 0,
+ 5, 7, 3206, 3, 0, 1736, 1559, 533,
+ 1956, 1960, 0, 41, 533, 1952, 533, 3196,
+ 3770, 3196, 0, 5, 7, 3206, 3, 0,
+ 1736, 1559, 536, 1968, 1972, 0, 41, 1964,
+ 536, 3201, 3776, 3201, 0, 5, 7, 3,
+ 0, 1736, 1559, 1900, 3176, 3181, 3091, 3171,
+ 1900, 3752, 3841, 3752, 503, 1896, 3161, 3166,
+ 3091, 1896, 3156, 1896, 3746, 3834, 3746, 503,
+ 1892, 3146, 3151, 3091, 1892, 3141, 1892, 3740,
+ 3827, 3740, 503, 1888, 3131, 3136, 3091, 1888,
+ 3126, 1888, 3734, 3820, 3734, 503, 321, 1553,
+ 1556, 1550, 321, 1884, 3116, 3121, 3091, 3111,
+ 1884, 503, 319, 1544, 1547, 1541, 319, 1880,
+ 3101, 3106, 3091, 3096, 1880, 503, 506, 45,
+ 557, 560, 41, 554, 45, 0, 5, 7,
+ 506, 3, 0, 45, 557, 560, 41, 554,
+ 45, 0, 5, 7, 506, 3, 0, 563,
+ 1980, 1984, 41, 1976, 563, 0, 5, 7,
+ 485, 3, 0, 488, 506, 45, 557, 560,
+ 41, 554, 45, 0, 5, 7, 506, 3,
+ 0, 45, 557, 560, 41, 554, 45, 422,
+ 0, 5, 7, 3, 0, 31, 437, 440,
+ 434, 31, 422, 0, 5, 7, 3, 0,
+ 31, 437, 440, 434, 31, 422, 0, 5,
+ 7, 3, 0, 443, 1784, 1788, 1780, 443,
+ 0, 5, 7, 485, 3, 0, 488, 335,
+ 0, 5, 7, 3, 0, 506, 45, 557,
+ 560, 41, 554, 45, 0, 5, 7, 333,
+ 3, 0, 0, 5, 7, 3, 0, 127,
+ 1, 707, 0, 695, 5, 7, 698, 701,
+ 3, 0, 1, 350, 1, 109, 111, 0,
+ 2108, 683, 103, 105, 506, 704, 2156, 2160,
+ 41, 2152, 704, 2148, 3276, 2148, 0, 683,
+ 103, 107, 506, 45, 557, 560, 41, 554,
+ 45, 0, 5, 7, 333, 3, 0, 0,
+ 5, 7, 3, 0, 506, 43, 545, 548,
+ 41, 542, 43, 710, 0, 5, 7, 113,
+ 3, 0, 115, 0, 5, 7, 3, 0,
+ 1, 350, 1, 506, 43, 545, 548, 41,
+ 542, 43, 0, 5, 7, 506, 3, 0,
+ 43, 545, 548, 41, 542, 43, 0, 5,
+ 7, 113, 3, 0, 115, 0, 5, 7,
+ 3, 0, 1, 350, 1, 506, 43, 545,
+ 548, 41, 542, 43, 791, 0, 5, 7,
+ 145, 147, 149, 151, 3, 0, 0, 5,
+ 7, 3, 0, 1864, 506, 43, 545, 548,
+ 41, 542, 43, 0, 5, 7, 0, 3,
+ 0, 2172, 0, 5, 7, 0, 5, 7,
+ 0, 5, 7, 1, 3, 0, 350, 1,
+ 3, 0, 350, 1, 3, 0, 350, 1,
+ 794, 127, 0, 5, 7, 3, 0, 506,
+ 43, 545, 548, 41, 542, 43, 2112, 0,
+ 5, 7, 683, 3, 0, 3261, 103, 689,
+ 2124, 2128, 689, 2124, 2128, 689, 2124, 2128,
+ 2116, 2120, 689, 3266, 2116, 2120, 689, 3266,
+ 2116, 2120, 689, 3266, 2116, 0, 5, 7,
+ 3, 0, 506, 43, 545, 548, 41, 542,
+ 43, 0, 5, 7, 683, 3, 0, 103,
+ 692, 2140, 2144, 692, 2140, 2144, 692, 2140,
+ 2144, 2132, 2136, 692, 3271, 2132, 2136, 692,
+ 3271, 2132, 2136, 692, 3271, 2132, 0, 5,
+ 7, 3, 0, 506, 43, 545, 548, 41,
+ 542, 43, 0, 5, 7, 485, 3, 0,
+ 39, 494, 497, 39, 494, 497, 39, 494,
+ 497, 488, 491, 39, 1840, 488, 491, 39,
+ 1840, 488, 491, 39, 1840, 488, 797, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 153, 803, 806,
+ 0, 0, 0, 800, 153, 0, 5, 7,
+ 333, 3, 0, 0, 5, 7, 3, 0,
+ 506, 43, 545, 548, 41, 542, 43, 0,
+ 5, 7, 506, 3, 0, 47, 572, 575,
+ 41, 569, 47, 614, 0, 5, 7, 602,
+ 3, 0, 63, 608, 611, 61, 605, 63,
+ 0, 5, 7, 602, 3, 0, 63, 608,
+ 611, 61, 605, 63, 0, 5, 7, 506,
+ 3, 0, 563, 1980, 1984, 41, 1976, 563,
+ 0, 5, 7, 485, 3, 0, 500, 1848,
+ 1852, 1844, 500, 0, 5, 7, 127, 3,
+ 0, 1, 0, 0, 179, 920, 923, 917,
+ 179, 0, 0, 0, 173, 893, 896, 890,
+ 173, 0, 193, 983, 986, 980, 193, 0,
+ 0, 0, 0, 189, 965, 968, 962, 189,
+ 0, 0, 0, 157, 821, 824, 818, 157,
+ 0, 0, 0, 0, 0, 0, 207, 1046,
+ 1049, 1043, 207, 0, 0, 0, 0, 191,
+ 974, 977, 971, 191, 0, 0, 0, 205,
+ 1037, 1040, 1034, 205, 195, 992, 995, 989,
+ 195, 0, 0, 0, 0, 0, 225, 1127,
+ 1130, 1124, 225, 0, 227, 1136, 1139, 1133,
+ 227, 0, 0, 0, 0, 163, 848, 851,
+ 845, 163, 0, 0, 0, 0, 0, 0,
+ 0, 199, 1010, 1013, 1007, 199, 0, 0,
+ 0, 177, 911, 914, 908, 177, 187, 956,
+ 959, 953, 187, 0, 0, 0, 0, 0,
+ 219, 1100, 1103, 1097, 219, 0, 221, 1109,
+ 1112, 1106, 221, 0, 181, 929, 932, 926,
+ 181, 223, 1118, 1121, 1115, 223, 0, 0,
+ 0, 0, 0, 165, 857, 860, 854, 165,
+ 167, 866, 869, 863, 167, 0, 0, 0,
+ 0, 0, 0, 185, 947, 950, 944, 185,
+ 0, 217, 1091, 1094, 1088, 217, 155, 812,
+ 815, 0, 809, 155, 0, 203, 1028, 1031,
+ 0, 1025, 203, 209, 1055, 1058, 0, 1052,
+ 209, 0, 0, 0, 0, 211, 1064, 1067,
+ 1061, 211, 0, 0, 161, 839, 842, 836,
+ 161, 0, 0, 0, 171, 884, 887, 881,
+ 171, 0, 0, 0, 201, 1019, 1022, 1016,
+ 201, 175, 902, 905, 899, 175, 0, 0,
+ 0, 0, 0, 159, 830, 833, 827, 159,
+ 0, 215, 1082, 1085, 1079, 215, 0, 183,
+ 938, 941, 935, 183, 0, 0, 0, 197,
+ 1001, 1004, 998, 197, 0, 0, 0, 0,
+ 0, 213, 1073, 1076, 1070, 213, 0, 169,
+ 875, 878, 872, 169, 0, 0, 1868, 506,
+ 45, 557, 560, 41, 554, 45, 485, 1856,
+ 1, 506, 45, 557, 560, 41, 554, 45,
+ 0, 5, 7, 506, 3, 0, 43, 545,
+ 548, 41, 542, 43, 0, 5, 7, 333,
+ 3, 0, 0, 5, 7, 3, 0, 127,
+ 1, 127, 1, 506, 43, 545, 548, 41,
+ 542, 43, 0, 5, 7, 506, 3, 0,
+ 43, 545, 548, 41, 542, 43, 0, 5,
+ 7, 506, 3, 0, 45, 557, 560, 41,
+ 554, 45, 0, 5, 7, 29, 425, 3,
+ 0, 31, 437, 440, 434, 31, 716, 0,
+ 5, 7, 428, 3, 0, 131, 133, 0,
+ 135, 137, 0, 139, 0, 141, 143, 0,
+ 446, 129, 1, 0, 0, 115, 113, 506,
+ 43, 545, 548, 41, 542, 43, 0, 5,
+ 7, 506, 3, 0, 43, 545, 548, 41,
+ 542, 43, 0, 5, 7, 506, 3, 0,
+ 45, 557, 560, 41, 554, 45, 0, 5,
+ 7, 29, 425, 3, 0, 431, 115, 113,
+ 506, 43, 545, 548, 41, 542, 43, 0,
+ 5, 7, 506, 3, 0, 43, 545, 548,
+ 41, 542, 43, 0, 5, 7, 506, 3,
+ 0, 43, 545, 548, 41, 542, 43, 0,
+ 5, 7, 113, 3, 0, 115, 0, 5,
+ 7, 3, 0, 1, 350, 1, 506, 45,
+ 557, 560, 41, 554, 45, 0, 5, 7,
+ 683, 3, 0, 2116, 103, 506, 45, 557,
+ 560, 41, 554, 45, 0, 5, 7, 1568,
+ 3, 0, 115, 113, 115, 2168, 327, 113,
+ 115, 113, 115, 2356, 2352, 1565, 115, 2348,
+ 325, 113, 115, 2340, 1565, 115, 325, 113,
+ 115, 2344, 476, 35, 0, 470, 473, 449,
+ 467, 35, 35, 339, 362, 368, 2364, 449,
+ 353, 35, 1740, 1577, 1832, 35, 362, 368,
+ 2092, 2092, 2092, 2092, 2092, 2092, 2092, 2092,
+ 2092, 2092, 2092, 2092, 2092, 2092, 353, 35,
+ 3066, 3081, 3251, 3251, 3251, 3251, 3251, 3251,
+ 3251, 3251, 3251, 3251, 3251, 3251, 3251, 3251,
+ 1824, 656, 91, 2084, 2088, 2076, 653, 91,
+ 2080, 656, 362, 368, 353, 35, 362, 368,
+ 2992, 35, 35, 362, 368, 35, 1577, 3722,
+ 3728, 3788, 3788, 3788, 3788, 3788, 3788, 3788,
+ 3788, 3788, 3788, 3788, 3788, 3788, 3788, 1752
+};
+
+static const short _zone_scanner_eof_actions[] = {
+ 0, 1872, 2012, 345, 1592, 337, 1571, 9,
+ 9, 337, 1571, 337, 1571, 1571, 3086, 3782,
+ 1589, 345, 345, 345, 1592, 1571, 345, 345,
+ 345, 1592, 345, 345, 345, 345, 1592, 345,
+ 345, 345, 1592, 345, 345, 345, 1592, 1592,
+ 345, 345, 345, 345, 1592, 345, 1592, 345,
+ 345, 345, 345, 1592, 345, 345, 345, 345,
+ 345, 345, 345, 345, 345, 345, 1592, 345,
+ 345, 1592, 1592, 345, 345, 1592, 345, 1592,
+ 345, 1592, 1592, 345, 345, 345, 345, 1592,
+ 1592, 345, 345, 345, 345, 1592, 345, 1592,
+ 1592, 345, 1592, 1592, 345, 345, 345, 345,
+ 1592, 345, 345, 1592, 345, 1592, 345, 345,
+ 345, 1592, 1592, 345, 345, 1592, 345, 1592,
+ 345, 1592, 345, 345, 345, 1592, 345, 345,
+ 345, 1592, 345, 1592, 345, 345, 518, 1876,
+ 345, 1872, 345, 345, 518, 2012, 2012, 2012,
+ 2012, 345, 9, 93, 93, 93, 93, 93,
+ 93, 93, 93, 37, 518, 0, 3071, 518,
+ 345, 2012, 2012, 2012, 345, 1836, 1876, 2376,
+ 1571, 1872, 9, 1571, 9, 3086, 2376, 2376,
+ 2376, 2376, 2376, 2376, 2376, 2376, 2376, 2376,
+ 2376, 2376, 2376, 1571, 2360, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 1828, 3813,
+ 1872, 1589, 3076, 3086, 3076, 3076, 3076, 3076,
+ 3076, 3076, 3076, 3076, 3076, 3076, 3076, 3076,
+ 3076, 479, 3086, 1571, 9, 1571, 345, 345,
+ 1592, 345, 345, 345, 1592, 345, 1592, 1571,
+ 1571, 9, 1571, 1571, 337, 1571, 482, 482,
+ 482, 482, 482, 482, 482, 482, 482, 482,
+ 482, 482, 482, 9, 1589, 482, 1589, 0,
+ 0, 27, 27, 27, 27, 395, 395, 395,
+ 395, 27, 27, 620, 620, 2052, 2052, 2052,
+ 2052, 620, 67, 2052, 2052, 2052, 2052, 73,
+ 509, 3221, 374, 374, 3221, 2004, 3221, 73,
+ 77, 77, 77, 377, 377, 377, 77, 398,
+ 398, 398, 398, 377, 77, 0, 83, 644,
+ 650, 85, 650, 9, 9, 85, 401, 401,
+ 401, 401, 650, 9, 85, 0, 0, 125,
+ 125, 125, 125, 125, 125, 125, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 309, 309,
+ 309, 309, 309, 309, 309, 309, 323, 512,
+ 512, 2164, 2164, 2164, 2164, 323, 323, 323,
+ 512, 512, 2164, 2164, 2164, 2164, 323, 512,
+ 323, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 329, 329, 329, 329, 329, 329, 329, 329,
+ 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 331, 331, 331, 331, 331, 331, 331,
+ 331, 686, 686, 337, 337, 337, 337, 337,
+ 337, 515, 515, 515, 2008, 515, 2008, 515,
+ 2008, 515, 2008, 2008, 2008, 2008, 337, 2008,
+ 2008, 2008, 337, 2008, 2008, 2008, 337, 2008,
+ 2008, 2008, 337, 337, 337, 337, 337, 337,
+ 337, 337, 337, 337, 337, 337, 337, 515,
+ 515, 337, 337, 337, 337, 337, 337, 337,
+ 686, 686, 1562, 1562, 1562, 1562, 1562, 1562,
+ 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562,
+ 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562,
+ 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562,
+ 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562,
+ 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562,
+ 1562, 1562, 1562, 1562, 1562, 1562, 1562, 1562,
+ 1562, 515, 515, 515, 515, 515, 515, 337,
+ 337, 337, 337, 337, 515, 515, 515, 515,
+ 337, 337, 337, 337, 337, 337, 337, 337,
+ 337, 337, 337, 337, 337, 337, 337, 515,
+ 515, 337, 337, 337, 337, 337, 337, 337,
+ 707, 707, 707, 2108, 2108, 707, 707, 337,
+ 707, 2108, 2108, 515, 515, 337, 337, 515,
+ 515, 710, 710, 710, 710, 337, 337, 337,
+ 515, 515, 515, 515, 710, 710, 710, 710,
+ 337, 337, 515, 515, 791, 791, 1864, 1864,
+ 791, 2172, 794, 794, 794, 794, 794, 794,
+ 794, 791, 791, 791, 1864, 1864, 2112, 3261,
+ 791, 791, 791, 1864, 1864, 2112, 3261, 791,
+ 791, 791, 1864, 1864, 791, 2172, 791, 791,
+ 337, 797, 797, 337, 337, 515, 515, 515,
+ 515, 614, 614, 614, 614, 515, 515, 337,
+ 337, 337, 337, 337, 337, 337, 337, 337,
+ 337, 337, 337, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 797, 797, 797,
+ 797, 797, 797, 797, 797, 1868, 1868, 337,
+ 337, 337, 515, 515, 515, 515, 337, 337,
+ 337, 337, 337, 337, 337, 337, 337, 515,
+ 515, 515, 515, 515, 515, 710, 710, 716,
+ 716, 716, 716, 716, 716, 716, 716, 716,
+ 337, 716, 716, 716, 716, 716, 337, 710,
+ 710, 337, 337, 337, 515, 515, 515, 515,
+ 515, 515, 710, 710, 710, 710, 337, 337,
+ 337, 515, 515, 515, 515, 515, 515, 710,
+ 710, 710, 710, 337, 337, 337, 515, 515,
+ 686, 686, 337, 515, 515, 710, 710, 710,
+ 710, 2168, 710, 710, 710, 710, 2356, 337,
+ 710, 710, 2348, 710, 710, 2348, 710, 710,
+ 2348, 710, 710, 2348, 0, 0, 0, 0,
+ 91, 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, 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, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+static const int zone_scanner_start = 1060;
+static const int zone_scanner_first_final = 1060;
+static const int zone_scanner_error = 0;
+
+static const int zone_scanner_en_err_line = 247;
+static const int zone_scanner_en_dname_ = 249;
+static const int zone_scanner_en_text_ = 259;
+static const int zone_scanner_en_default_ttl_ = 271;
+static const int zone_scanner_en_zone_origin_ = 280;
+static const int zone_scanner_en_include_file_ = 293;
+static const int zone_scanner_en_base64_ = 311;
+static const int zone_scanner_en_bitmap_ = 318;
+static const int zone_scanner_en_nonempty_hex_r_data = 438;
+static const int zone_scanner_en_hex_r_data = 447;
+static const int zone_scanner_en_dns_alg_ = 457;
+static const int zone_scanner_en_cert_type_ = 552;
+static const int zone_scanner_en_r_data_a = 593;
+static const int zone_scanner_en_r_data_ns = 595;
+static const int zone_scanner_en_r_data_soa = 597;
+static const int zone_scanner_en_r_data_hinfo = 629;
+static const int zone_scanner_en_r_data_minfo = 634;
+static const int zone_scanner_en_r_data_mx = 639;
+static const int zone_scanner_en_r_data_txt = 644;
+static const int zone_scanner_en_r_data_aaaa = 648;
+static const int zone_scanner_en_r_data_loc = 650;
+static const int zone_scanner_en_r_data_srv = 705;
+static const int zone_scanner_en_r_data_naptr = 716;
+static const int zone_scanner_en_r_data_cert = 733;
+static const int zone_scanner_en_r_data_apl = 744;
+static const int zone_scanner_en_r_data_ds = 755;
+static const int zone_scanner_en_r_data_sshfp = 768;
+static const int zone_scanner_en_r_data_ipseckey = 778;
+static const int zone_scanner_en_r_data_rrsig = 817;
+static const int zone_scanner_en_r_data_nsec = 959;
+static const int zone_scanner_en_r_data_dnskey = 962;
+static const int zone_scanner_en_r_data_dhcid = 973;
+static const int zone_scanner_en_r_data_nsec3 = 975;
+static const int zone_scanner_en_r_data_nsec3param = 1004;
+static const int zone_scanner_en_r_data_tlsa = 1017;
+static const int zone_scanner_en_r_data_l32 = 1030;
+static const int zone_scanner_en_r_data_l64 = 1035;
+static const int zone_scanner_en_r_data_eui48 = 1048;
+static const int zone_scanner_en_r_data_eui64 = 1054;
+static const int zone_scanner_en_main = 1060;
+
+
+#line 82 "./zscanner/scanner.rl"
+
+
+scanner_t* scanner_create(const char *file_name)
+{
+ scanner_t *s = calloc(1, sizeof(scanner_t));
+ if (s == NULL) {
+ return NULL;
+ }
+
+ s->file_name = strdup(file_name);
+ s->line_counter = 1;
+
+ // Nonzero initial scanner state.
+ s->cs = zone_scanner_start;
+
+ return s;
+}
+
+void scanner_free(scanner_t *s)
+{
+ if (s != NULL) {
+ free(s->file_name);
+ free(s);
+ }
+}
+
+int scanner_process(const char *start,
+ const char *end,
+ const bool is_last_block,
+ scanner_t *s)
+{
+ // Necessary scanner variables.
+ const char *p = start;
+ const char *pe = end;
+ char *eof = NULL;
+ int stack[RAGEL_STACK_SIZE];
+
+ // Auxiliary variables which are used in scanner body.
+ struct in_addr addr4;
+ struct in6_addr addr6;
+ uint32_t timestamp;
+ int16_t window;
+ int ret;
+
+ // Next 2 variables are for better performance.
+ // Restoring r_data pointer to next free space.
+ uint8_t *rdata_tail = s->r_data + s->r_data_tail;
+ // Initialization of the last r_data byte.
+ uint8_t *rdata_stop = s->r_data + MAX_RDATA_LENGTH - 1;
+
+ // Restoring scanner states.
+ int cs = s->cs;
+ int top = s->top;
+ memcpy(stack, s->stack, sizeof(stack));
+
+ // End of file check.
+ if (is_last_block == true) {
+ eof = (char *)pe;
+ }
+
+ // Writing scanner body (in C).
+
+#line 5016 "zscanner/scanner.c"
+ {
+ int _klen;
+ unsigned int _trans;
+ short _widec;
+ const short *_acts;
+ unsigned int _nacts;
+ const short *_keys;
+
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _widec = (*p);
+ _klen = _zone_scanner_cond_lengths[cs];
+ _keys = _zone_scanner_cond_keys + (_zone_scanner_cond_offsets[cs]*2);
+ if ( _klen > 0 ) {
+ const short *_lower = _keys;
+ const short *_mid;
+ const short *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( _widec < _mid[0] )
+ _upper = _mid - 2;
+ else if ( _widec > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ switch ( _zone_scanner_cond_spaces[_zone_scanner_cond_offsets[cs] + ((_mid - _keys)>>1)] ) {
+ case 0: {
+ _widec = (short)(640 + ((*p) - -128));
+ if (
+#line 54 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ break;
+ }
+ case 1: {
+ _widec = (short)(1152 + ((*p) - -128));
+ if (
+#line 63 "./zscanner/scanner_body.rl"
+ !s->multiline ) _widec += 256;
+ break;
+ }
+ case 2: {
+ _widec = (short)(128 + ((*p) - -128));
+ if (
+#line 559 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ break;
+ }
+ case 3: {
+ _widec = (short)(2688 + ((*p) - -128));
+ if (
+#line 1197 "./zscanner/scanner_body.rl"
+ s->number64 != 0 ) _widec += 256;
+ break;
+ }
+ case 4: {
+ _widec = (short)(4224 + ((*p) - -128));
+ if (
+#line 1198 "./zscanner/scanner_body.rl"
+ s->number64 == 0 ) _widec += 256;
+ break;
+ }
+ case 5: {
+ _widec = (short)(1664 + ((*p) - -128));
+ if (
+#line 54 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ if (
+#line 63 "./zscanner/scanner_body.rl"
+ !s->multiline ) _widec += 512;
+ break;
+ }
+ case 6: {
+ _widec = (short)(3200 + ((*p) - -128));
+ if (
+#line 54 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ if (
+#line 1197 "./zscanner/scanner_body.rl"
+ s->number64 != 0 ) _widec += 512;
+ break;
+ }
+ case 7: {
+ _widec = (short)(4736 + ((*p) - -128));
+ if (
+#line 54 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ if (
+#line 1198 "./zscanner/scanner_body.rl"
+ s->number64 == 0 ) _widec += 512;
+ break;
+ }
+ case 8: {
+ _widec = (short)(5760 + ((*p) - -128));
+ if (
+#line 1197 "./zscanner/scanner_body.rl"
+ s->number64 != 0 ) _widec += 256;
+ if (
+#line 1198 "./zscanner/scanner_body.rl"
+ s->number64 == 0 ) _widec += 512;
+ break;
+ }
+ case 9: {
+ _widec = (short)(12928 + ((*p) - -128));
+ if (
+#line 54 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ if (
+#line 63 "./zscanner/scanner_body.rl"
+ !s->multiline ) _widec += 512;
+ if (
+#line 1198 "./zscanner/scanner_body.rl"
+ s->number64 == 0 ) _widec += 1024;
+ break;
+ }
+ case 10: {
+ _widec = (short)(6784 + ((*p) - -128));
+ if (
+#line 54 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ if (
+#line 1197 "./zscanner/scanner_body.rl"
+ s->number64 != 0 ) _widec += 512;
+ if (
+#line 1198 "./zscanner/scanner_body.rl"
+ s->number64 == 0 ) _widec += 1024;
+ break;
+ }
+ case 11: {
+ _widec = (short)(8832 + ((*p) - -128));
+ if (
+#line 54 "./zscanner/scanner_body.rl"
+ s->multiline ) _widec += 256;
+ if (
+#line 63 "./zscanner/scanner_body.rl"
+ !s->multiline ) _widec += 512;
+ if (
+#line 1197 "./zscanner/scanner_body.rl"
+ s->number64 != 0 ) _widec += 1024;
+ if (
+#line 1198 "./zscanner/scanner_body.rl"
+ s->number64 == 0 ) _widec += 2048;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ _keys = _zone_scanner_trans_keys + _zone_scanner_key_offsets[cs];
+ _trans = _zone_scanner_index_offsets[cs];
+
+ _klen = _zone_scanner_single_lengths[cs];
+ if ( _klen > 0 ) {
+ const short *_lower = _keys;
+ const short *_mid;
+ const short *_upper = _keys + _klen - 1;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( _widec < *_mid )
+ _upper = _mid - 1;
+ else if ( _widec > *_mid )
+ _lower = _mid + 1;
+ else {
+ _trans += (unsigned int)(_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _zone_scanner_range_lengths[cs];
+ if ( _klen > 0 ) {
+ const short *_lower = _keys;
+ const short *_mid;
+ const short *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( _widec < _mid[0] )
+ _upper = _mid - 2;
+ else if ( _widec > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ _trans += (unsigned int)((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += _klen;
+ }
+
+_match:
+ _trans = _zone_scanner_indicies[_trans];
+ cs = _zone_scanner_trans_targs[_trans];
+
+ if ( _zone_scanner_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _zone_scanner_actions + _zone_scanner_trans_actions[_trans];
+ _nacts = (unsigned int) *_acts++;
+ while ( _nacts-- > 0 )
+ {
+ switch ( *_acts++ )
+ {
+ case 0:
+#line 20 "./zscanner/scanner_body.rl"
+ {
+ p--; {cs = stack[--top]; goto _again;}
+ }
+ break;
+ case 1:
+#line 25 "./zscanner/scanner_body.rl"
+ {
+ s->line_counter++;
+ }
+ break;
+ case 2:
+#line 29 "./zscanner/scanner_body.rl"
+ {
+ if (s->multiline == true) {
+ SCANNER_ERROR(ZSCANNER_ELEFT_PARENTHESIS);
+ p--; {cs = 247; goto _again;}
+ }
+ s->multiline = true;
+ }
+ break;
+ case 3:
+#line 36 "./zscanner/scanner_body.rl"
+ {
+ if (s->multiline == false) {
+ SCANNER_ERROR(ZSCANNER_ERIGHT_PARENTHESIS);
+ p--; {cs = 247; goto _again;}
+ }
+ s->multiline = false;
+ }
+ break;
+ case 4:
+#line 44 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_REST);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 5:
+#line 67 "./zscanner/scanner_body.rl"
+ {
+ s->buffer_length = 0;
+ }
+ break;
+ case 6:
+#line 70 "./zscanner/scanner_body.rl"
+ {
+ if (s->buffer_length < sizeof(s->buffer) - 1) {
+ s->buffer[s->buffer_length++] = (*p);
+ }
+ }
+ break;
+ case 7:
+#line 75 "./zscanner/scanner_body.rl"
+ {
+ // Ending string in buffer.
+ s->buffer[s->buffer_length++] = 0;
+
+ // Error counter incrementation.
+ s->error_counter++;
+
+ // Initialization of fcall stack.
+ top = 0;
+
+ // Process error message.
+ s->process_error(s);
+
+ // Reset.
+ s->error_code = KNOT_EOK;
+ s->multiline = false;
+
+ // In case of serious error, stop scanner.
+ if (s->stop == true) {
+ return -1;
+ }
+ }
+ break;
+ case 8:
+#line 100 "./zscanner/scanner_body.rl"
+ { {cs = 1060; goto _again;} }
+ break;
+ case 9:
+#line 104 "./zscanner/scanner_body.rl"
+ {
+ s->item_length = 0;
+ s->item_length_position = s->dname_tmp_length++;
+ }
+ break;
+ case 10:
+#line 108 "./zscanner/scanner_body.rl"
+ {
+ if (s->item_length < MAX_LABEL_LENGTH) {
+ (s->dname)[s->dname_tmp_length++] = (*p);
+ s->item_length++;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ELABEL_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 11:
+#line 117 "./zscanner/scanner_body.rl"
+ {
+ if (s->dname_tmp_length < MAX_DNAME_LENGTH) {
+ (s->dname)[s->item_length_position] =
+ (uint8_t)(s->item_length);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EDNAME_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 12:
+#line 127 "./zscanner/scanner_body.rl"
+ {
+ if (s->item_length < MAX_LABEL_LENGTH) {
+ (s->dname)[s->dname_tmp_length] = 0;
+ s->item_length++;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ELABEL_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 13:
+#line 136 "./zscanner/scanner_body.rl"
+ {
+ (s->dname)[s->dname_tmp_length] *= 10;
+ (s->dname)[s->dname_tmp_length] += digit_to_num[(uint8_t)(*p)];
+ }
+ break;
+ case 14:
+#line 140 "./zscanner/scanner_body.rl"
+ {
+ s->dname_tmp_length++;
+ }
+ break;
+ case 15:
+#line 143 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 16:
+#line 162 "./zscanner/scanner_body.rl"
+ {
+ (s->dname)[s->dname_tmp_length++] = 0;
+ }
+ break;
+ case 17:
+#line 165 "./zscanner/scanner_body.rl"
+ {
+ memcpy(s->dname + s->dname_tmp_length,
+ s->zone_origin,
+ s->zone_origin_length);
+
+ s->dname_tmp_length += s->zone_origin_length;
+
+ if (s->dname_tmp_length > MAX_DNAME_LENGTH) {
+ SCANNER_WARNING(ZSCANNER_EDNAME_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 18:
+#line 177 "./zscanner/scanner_body.rl"
+ {
+ memcpy(s->dname,
+ s->zone_origin,
+ s->zone_origin_length);
+
+ s->dname_tmp_length = s->zone_origin_length;
+ }
+ break;
+ case 19:
+#line 185 "./zscanner/scanner_body.rl"
+ {
+ s->item_length_position = 0;
+ s->dname_tmp_length = 0;
+ }
+ break;
+ case 20:
+#line 189 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_DNAME_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 21:
+#line 201 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 249; goto _again;} }
+ break;
+ case 22:
+#line 205 "./zscanner/scanner_body.rl"
+ {
+ s->item_length_location = rdata_tail++;
+ }
+ break;
+ case 23:
+#line 208 "./zscanner/scanner_body.rl"
+ {
+ s->item_length = rdata_tail - s->item_length_location - 1;
+
+ if (s->item_length <= MAX_ITEM_LENGTH) {
+ *(s->item_length_location) = (uint8_t)(s->item_length);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EITEM_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 24:
+#line 219 "./zscanner/scanner_body.rl"
+ {
+ s->r_data_blocks[++(s->r_data_blocks_count)] =
+ rdata_tail - s->r_data;
+ }
+ break;
+ case 25:
+#line 229 "./zscanner/scanner_body.rl"
+ {
+ s->dname = s->r_owner;
+ s->r_owner_length = 0;
+ }
+ break;
+ case 26:
+#line 233 "./zscanner/scanner_body.rl"
+ {
+ s->r_owner_length = s->dname_tmp_length;
+ }
+ break;
+ case 27:
+#line 236 "./zscanner/scanner_body.rl"
+ {
+ if (s->r_owner_length == 0) {
+ SCANNER_WARNING(ZSCANNER_EBAD_PREVIOUS_OWNER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 28:
+#line 242 "./zscanner/scanner_body.rl"
+ {
+ s->r_owner_length = 0;
+ SCANNER_WARNING(ZSCANNER_EBAD_OWNER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 29:
+#line 254 "./zscanner/scanner_body.rl"
+ {
+ s->dname = rdata_tail;
+ }
+ break;
+ case 30:
+#line 257 "./zscanner/scanner_body.rl"
+ {
+ rdata_tail += s->dname_tmp_length;
+ }
+ break;
+ case 31:
+#line 265 "./zscanner/scanner_body.rl"
+ {
+ // Overflow check: 10*(s->number64) + fc - ASCII_0 <= UINT64_MAX
+ if ((s->number64 < (UINT64_MAX / 10)) || // Dominant fast check.
+ ((s->number64 == (UINT64_MAX / 10)) && // Marginal case.
+ ((uint8_t)(*p) <= (UINT64_MAX % 10) + ASCII_0)
+ )
+ ) {
+ s->number64 *= 10;
+ s->number64 += digit_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER64_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 32:
+#line 282 "./zscanner/scanner_body.rl"
+ {
+ s->number64 = 0;
+ }
+ break;
+ case 33:
+#line 285 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 34:
+#line 293 "./zscanner/scanner_body.rl"
+ {
+ s->decimal_counter = 0;
+ }
+ break;
+ case 35:
+#line 296 "./zscanner/scanner_body.rl"
+ {
+ s->number64_tmp = s->number64;
+ }
+ break;
+ case 36:
+#line 299 "./zscanner/scanner_body.rl"
+ {
+ s->decimal_counter++;
+ }
+ break;
+ case 37:
+#line 303 "./zscanner/scanner_body.rl"
+ {
+ if (s->decimal_counter == 0 && s->number64 < UINT32_MAX) {
+ s->number64 *= pow(10, s->decimals);
+ } else if (s->decimal_counter <= s->decimals &&
+ s->number64_tmp < UINT32_MAX) {
+ s->number64 *= pow(10, s->decimals - s->decimal_counter);
+ s->number64 += s->number64_tmp * pow(10, s->decimals);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EFLOAT_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 38:
+#line 320 "./zscanner/scanner_body.rl"
+ {
+ s->decimals = 2;
+ }
+ break;
+ case 39:
+#line 323 "./zscanner/scanner_body.rl"
+ {
+ s->decimals = 3;
+ }
+ break;
+ case 40:
+#line 332 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT8_MAX) {
+ *rdata_tail = (uint8_t)(s->number64);
+ rdata_tail += 1;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER8_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 41:
+#line 341 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT16_MAX) {
+ *((uint16_t *)rdata_tail) = htons((uint16_t)(s->number64));
+ rdata_tail += 2;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 42:
+#line 350 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT32_MAX) {
+ *((uint32_t *)rdata_tail) = htonl((uint32_t)(s->number64));
+ rdata_tail += 4;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 43:
+#line 360 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT16_MAX) {
+ s->r_type = (uint16_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 44:
+#line 369 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT16_MAX) {
+ s->r_data_length = (uint16_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 45:
+#line 386 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIME_UNIT);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 46:
+#line 393 "./zscanner/scanner_body.rl"
+ { if (s->number64 <= (UINT32_MAX / 60)) {
+ s->number64 *= 60;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 47:
+#line 400 "./zscanner/scanner_body.rl"
+ { if (s->number64 <= (UINT32_MAX / 3600)) {
+ s->number64 *= 3600;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 48:
+#line 407 "./zscanner/scanner_body.rl"
+ { if (s->number64 <= (UINT32_MAX / 86400)) {
+ s->number64 *= 86400;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 49:
+#line 414 "./zscanner/scanner_body.rl"
+ { if (s->number64 <= (UINT32_MAX / 604800)) {
+ s->number64 *= 604800;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 50:
+#line 424 "./zscanner/scanner_body.rl"
+ {
+ s->number64_tmp = s->number64;
+ }
+ break;
+ case 51:
+#line 427 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 + s->number64_tmp < UINT32_MAX) {
+ s->number64 += s->number64_tmp;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 52:
+#line 445 "./zscanner/scanner_body.rl"
+ {
+ s->buffer_length = 0;
+ }
+ break;
+ case 53:
+#line 448 "./zscanner/scanner_body.rl"
+ {
+ if (s->buffer_length < MAX_RDATA_LENGTH) {
+ s->buffer[s->buffer_length++] = (*p);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 54:
+#line 456 "./zscanner/scanner_body.rl"
+ {
+ s->buffer[s->buffer_length] = 0;
+
+ if (s->buffer_length == 14) { // Date; 14 = len("YYYYMMDDHHmmSS").
+ ret = date_to_timestamp(s->buffer, &timestamp);
+
+ if (ret == KNOT_EOK) {
+ *((uint32_t *)rdata_tail) = htonl(timestamp);
+ rdata_tail += 4;
+ } else {
+ SCANNER_WARNING(ret);
+ p--; {cs = 247; goto _again;}
+ }
+ } else if (s->buffer_length <= 10) { // Timestamp format.
+ char *end;
+
+ s->number64 = strtoull((char *)(s->buffer), &end, 10);
+
+ if (end == (char *)(s->buffer) || *end != '\0') {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIMESTAMP);
+ p--; {cs = 247; goto _again;}
+ }
+
+ if (s->number64 <= UINT32_MAX) {
+ *((uint32_t *)rdata_tail) = htonl((uint32_t)s->number64);
+ rdata_tail += 4;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIMESTAMP_LENGTH);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 55:
+#line 491 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIMESTAMP_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 56:
+#line 501 "./zscanner/scanner_body.rl"
+ {
+ if (rdata_tail <= rdata_stop) {
+ *(rdata_tail++) = (*p);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ETEXT_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 57:
+#line 509 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TEXT_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 58:
+#line 513 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TEXT);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 59:
+#line 518 "./zscanner/scanner_body.rl"
+ {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = 0;
+ s->item_length++;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ETEXT_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 60:
+#line 527 "./zscanner/scanner_body.rl"
+ {
+ if ((*rdata_tail < (UINT8_MAX / 10)) || // Dominant fast check.
+ ((*rdata_tail == (UINT8_MAX / 10)) && // Marginal case.
+ ((*p) <= (UINT8_MAX % 10) + ASCII_0)
+ )
+ ) {
+ *rdata_tail *= 10;
+ *rdata_tail += digit_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER8_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 61:
+#line 540 "./zscanner/scanner_body.rl"
+ {
+ rdata_tail++;
+ }
+ break;
+ case 62:
+#line 543 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 63:
+#line 565 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 259; goto _again;} }
+ break;
+ case 64:
+#line 575 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT32_MAX) {
+ s->default_ttl = (uint32_t)(s->number64);
+ } else {
+ SCANNER_ERROR(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 65:
+#line 583 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_TTL);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 66:
+#line 590 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 271; goto _again;} }
+ break;
+ case 67:
+#line 594 "./zscanner/scanner_body.rl"
+ {
+ s->dname = s->zone_origin;
+ }
+ break;
+ case 68:
+#line 597 "./zscanner/scanner_body.rl"
+ {
+ s->zone_origin_length = s->dname_tmp_length;
+ }
+ break;
+ case 69:
+#line 600 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_ORIGIN);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 70:
+#line 607 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 280; goto _again;} }
+ break;
+ case 71:
+#line 611 "./zscanner/scanner_body.rl"
+ {
+ rdata_tail = s->r_data;
+ }
+ break;
+ case 72:
+#line 614 "./zscanner/scanner_body.rl"
+ {
+ *rdata_tail = 0; // Ending filename string.
+ strncpy((char*)(s->include_filename), (char*)(s->r_data),
+ sizeof(s->include_filename));
+
+ // Check for correct string copy.
+ if (strlen(s->include_filename) !=
+ (size_t)(rdata_tail - s->r_data)) {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_FILENAME);
+ p--; {cs = 247; goto _again;}
+ }
+
+ // For detection whether origin is not present.
+ s->dname = NULL;
+ }
+ break;
+ case 73:
+#line 629 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_FILENAME);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 74:
+#line 634 "./zscanner/scanner_body.rl"
+ {
+ s->dname = s->r_data;
+ }
+ break;
+ case 75:
+#line 637 "./zscanner/scanner_body.rl"
+ {
+ s->r_data_length = s->dname_tmp_length;
+ }
+ break;
+ case 76:
+#line 640 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_ORIGIN);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 77:
+#line 645 "./zscanner/scanner_body.rl"
+ {
+ char text_origin[MAX_DNAME_LENGTH];
+
+ // Origin conversion from wire to text form.
+ if (s->dname == NULL) { // Use current origin.
+ wire_dname_to_str(s->zone_origin,
+ s->zone_origin_length,
+ text_origin);
+ } else { // Use specified origin.
+ wire_dname_to_str(s->r_data,
+ s->r_data_length,
+ text_origin);
+ }
+
+ if (s->include_filename[0] != '/') { // Relative file path.
+ // Get absolute path of the current zone file.
+ if (realpath(s->file_name, (char*)(s->buffer)) != NULL) {
+ char *full_current_zone_file_name =
+ strdup((char*)(s->buffer));
+
+ // Creating full include file name.
+ snprintf((char*)(s->buffer), sizeof(s->buffer),
+ "%s/%s",
+ dirname(full_current_zone_file_name),
+ s->include_filename);
+
+ free(full_current_zone_file_name);
+ } else {
+ SCANNER_ERROR(ZSCANNER_EUNPROCESSED_INCLUDE);
+ p--; {cs = 247; goto _again;}
+ }
+ } else {
+ strncpy((char*)(s->buffer), (char*)(s->include_filename),
+ sizeof(s->buffer));
+ }
+
+ // Create new file loader for included zone file.
+ file_loader_t *fl = file_loader_create((char*)(s->buffer),
+ text_origin,
+ DEFAULT_CLASS,
+ DEFAULT_TTL,
+ s->process_record,
+ s->process_error,
+ s->data);
+ if (fl != NULL) {
+ // Process included zone file.
+ ret = file_loader_process(fl);
+ file_loader_free(fl);
+
+ if (ret != 0) {
+ SCANNER_ERROR(ZSCANNER_EUNPROCESSED_INCLUDE);
+ p--; {cs = 247; goto _again;}
+ }
+ } else {
+ SCANNER_ERROR(ZSCANNER_EUNOPENED_INCLUDE);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 78:
+#line 711 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 293; goto _again;} }
+ break;
+ case 79:
+#line 717 "./zscanner/scanner_body.rl"
+ {
+ s->stop = true;
+ }
+ break;
+ case 80:
+#line 721 "./zscanner/scanner_body.rl"
+ {
+ s->stop = false;
+ }
+ break;
+ case 81:
+#line 724 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_DIRECTIVE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 82:
+#line 736 "./zscanner/scanner_body.rl"
+ {
+ s->r_class = s->default_class;
+ }
+ break;
+ case 83:
+#line 740 "./zscanner/scanner_body.rl"
+ {
+ s->r_ttl = s->default_ttl;
+ }
+ break;
+ case 84:
+#line 744 "./zscanner/scanner_body.rl"
+ {
+ s->r_class = KNOT_CLASS_IN;
+ }
+ break;
+ case 85:
+#line 748 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT32_MAX) {
+ s->r_ttl = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 86:
+#line 763 "./zscanner/scanner_body.rl"
+ {
+ s->buffer_length = 0;
+ }
+ break;
+ case 87:
+#line 766 "./zscanner/scanner_body.rl"
+ {
+ if (s->buffer_length < MAX_RDATA_LENGTH) {
+ s->buffer[s->buffer_length++] = (*p);
+ }
+ else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 88:
+#line 775 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_ADDRESS_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 89:
+#line 780 "./zscanner/scanner_body.rl"
+ {
+ s->buffer[s->buffer_length] = 0;
+
+ if (inet_pton(AF_INET, (char *)s->buffer, &addr4) <= 0) {
+ SCANNER_WARNING(ZSCANNER_EBAD_IPV4);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 90:
+#line 788 "./zscanner/scanner_body.rl"
+ {
+ memcpy(rdata_tail, &(addr4.s_addr), INET4_ADDR_LENGTH);
+ rdata_tail += INET4_ADDR_LENGTH;
+ }
+ break;
+ case 91:
+#line 793 "./zscanner/scanner_body.rl"
+ {
+ s->buffer[s->buffer_length] = 0;
+
+ if (inet_pton(AF_INET6, (char *)s->buffer, &addr6) <= 0) {
+ SCANNER_WARNING(ZSCANNER_EBAD_IPV6);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 92:
+#line 801 "./zscanner/scanner_body.rl"
+ {
+ memcpy(rdata_tail, &(addr6.s6_addr), INET6_ADDR_LENGTH);
+ rdata_tail += INET6_ADDR_LENGTH;
+ }
+ break;
+ case 93:
+#line 818 "./zscanner/scanner_body.rl"
+ {
+ memset(&(s->apl), 0, sizeof(s->apl));
+ }
+ break;
+ case 94:
+#line 821 "./zscanner/scanner_body.rl"
+ {
+ s->apl.excl_flag = 128; // dec 128 = bin 10000000.
+ }
+ break;
+ case 95:
+#line 824 "./zscanner/scanner_body.rl"
+ {
+ s->apl.addr_family = 1;
+ }
+ break;
+ case 96:
+#line 827 "./zscanner/scanner_body.rl"
+ {
+ s->apl.addr_family = 2;
+ }
+ break;
+ case 97:
+#line 830 "./zscanner/scanner_body.rl"
+ {
+ if ((s->apl.addr_family == 1 && s->number64 <= 32) ||
+ (s->apl.addr_family == 2 && s->number64 <= 128)) {
+ s->apl.prefix_length = (uint8_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_APL);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 98:
+#line 839 "./zscanner/scanner_body.rl"
+ {
+ // Write address family.
+ *((uint16_t *)rdata_tail) = htons(s->apl.addr_family);
+ rdata_tail += 2;
+ // Write prefix length in bites.
+ *(rdata_tail) = s->apl.prefix_length;
+ rdata_tail += 1;
+ // Copy address to buffer.
+ uint8_t len;
+ switch (s->apl.addr_family) {
+ case 1:
+ len = INET4_ADDR_LENGTH;
+ memcpy(s->buffer, &(addr4.s_addr), len);
+ break;
+ case 2:
+ len = INET6_ADDR_LENGTH;
+ memcpy(s->buffer, &(addr6.s6_addr), len);
+ break;
+ default:
+ SCANNER_WARNING(ZSCANNER_EBAD_APL);
+ p--; {cs = 247; goto _again;}
+ }
+ // Find prefix without trailing zeroes.
+ while (len > 0) {
+ if ((s->buffer[len - 1] & 255) != 0) {
+ break;
+ }
+ len--;
+ }
+ // Write negation flag + prefix length in bytes.
+ *(rdata_tail) = len + s->apl.excl_flag;
+ rdata_tail += 1;
+ // Write address prefix non-null data.
+ memcpy(rdata_tail, s->buffer, len);
+ rdata_tail += len;
+ }
+ break;
+ case 99:
+#line 875 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_APL);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 100:
+#line 893 "./zscanner/scanner_body.rl"
+ {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = first_hex_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 101:
+#line 901 "./zscanner/scanner_body.rl"
+ {
+ *rdata_tail += second_hex_to_num[(uint8_t)(*p)];
+ rdata_tail++;
+ }
+ break;
+ case 102:
+#line 905 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 103:
+#line 919 "./zscanner/scanner_body.rl"
+ {
+ if ((rdata_tail - s->r_data) != s->r_data_length) {
+ SCANNER_WARNING(ZSCANNER_EBAD_RDATA_LENGTH);
+ p--; {cs = 247; goto _again;}
+ }
+
+ ret = find_rdata_blocks(s);
+ if (ret != KNOT_EOK) {
+ SCANNER_WARNING(ret);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 104:
+#line 932 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_RDATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 105:
+#line 942 "./zscanner/scanner_body.rl"
+ {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = first_base64_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 106:
+#line 950 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += second_left_base64_to_num[(uint8_t)(*p)];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = second_right_base64_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 107:
+#line 960 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += third_left_base64_to_num[(uint8_t)(*p)];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = third_right_base64_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 108:
+#line 970 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += fourth_base64_to_num[(uint8_t)(*p)];
+ }
+ break;
+ case 109:
+#line 974 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_BASE64_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 110:
+#line 996 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 311; goto _again;} }
+ break;
+ case 111:
+#line 1000 "./zscanner/scanner_body.rl"
+ {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = first_base32hex_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 112:
+#line 1008 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += second_left_base32hex_to_num[(uint8_t)(*p)];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = second_right_base32hex_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 113:
+#line 1018 "./zscanner/scanner_body.rl"
+ {
+ *rdata_tail += third_base32hex_to_num[(uint8_t)(*p)];
+ }
+ break;
+ case 114:
+#line 1021 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += fourth_left_base32hex_to_num[(uint8_t)(*p)];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = fourth_right_base32hex_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 115:
+#line 1031 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += fifth_left_base32hex_to_num[(uint8_t)(*p)];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = fifth_right_base32hex_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 116:
+#line 1041 "./zscanner/scanner_body.rl"
+ {
+ *rdata_tail += sixth_base32hex_to_num[(uint8_t)(*p)];
+ }
+ break;
+ case 117:
+#line 1044 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += seventh_left_base32hex_to_num[(uint8_t)(*p)];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = seventh_right_base32hex_to_num[(uint8_t)(*p)];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 118:
+#line 1054 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) += eighth_base32hex_to_num[(uint8_t)(*p)];
+ }
+ break;
+ case 119:
+#line 1058 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_BASE32HEX_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 120:
+#line 1093 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 0;
+ }
+ break;
+ case 121:
+#line 1096 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 1;
+ }
+ break;
+ case 122:
+#line 1099 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 2;
+ }
+ break;
+ case 123:
+#line 1102 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 3;
+ }
+ break;
+ case 124:
+#line 1105 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 5;
+ }
+ break;
+ case 125:
+#line 1108 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 6;
+ }
+ break;
+ case 126:
+#line 1111 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 7;
+ }
+ break;
+ case 127:
+#line 1114 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 8;
+ }
+ break;
+ case 128:
+#line 1117 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 10;
+ }
+ break;
+ case 129:
+#line 1120 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 12;
+ }
+ break;
+ case 130:
+#line 1123 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 13;
+ }
+ break;
+ case 131:
+#line 1126 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 14;
+ }
+ break;
+ case 132:
+#line 1129 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 252;
+ }
+ break;
+ case 133:
+#line 1132 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 253;
+ }
+ break;
+ case 134:
+#line 1135 "./zscanner/scanner_body.rl"
+ {
+ *(rdata_tail++) = 254;
+ }
+ break;
+ case 135:
+#line 1139 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(1);
+ rdata_tail += 2;
+ }
+ break;
+ case 136:
+#line 1143 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(2);
+ rdata_tail += 2;
+ }
+ break;
+ case 137:
+#line 1147 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(3);
+ rdata_tail += 2;
+ }
+ break;
+ case 138:
+#line 1151 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(4);
+ rdata_tail += 2;
+ }
+ break;
+ case 139:
+#line 1155 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(5);
+ rdata_tail += 2;
+ }
+ break;
+ case 140:
+#line 1159 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(6);
+ rdata_tail += 2;
+ }
+ break;
+ case 141:
+#line 1163 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(7);
+ rdata_tail += 2;
+ }
+ break;
+ case 142:
+#line 1167 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(8);
+ rdata_tail += 2;
+ }
+ break;
+ case 143:
+#line 1171 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(253);
+ rdata_tail += 2;
+ }
+ break;
+ case 144:
+#line 1175 "./zscanner/scanner_body.rl"
+ {
+ *((uint16_t *)rdata_tail) = htons(254);
+ rdata_tail += 2;
+ }
+ break;
+ case 145:
+#line 1182 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_GATEWAY);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 146:
+#line 1186 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_GATEWAY_KEY);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 147:
+#line 1204 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EUNSUPPORTED_TYPE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 148:
+#line 1210 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_A, &rdata_tail); }
+ break;
+ case 149:
+#line 1211 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_NS, &rdata_tail); }
+ break;
+ case 150:
+#line 1212 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_CNAME, &rdata_tail); }
+ break;
+ case 151:
+#line 1213 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_SOA, &rdata_tail); }
+ break;
+ case 152:
+#line 1214 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_PTR, &rdata_tail); }
+ break;
+ case 153:
+#line 1215 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_HINFO, &rdata_tail); }
+ break;
+ case 154:
+#line 1216 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_MINFO, &rdata_tail); }
+ break;
+ case 155:
+#line 1217 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_MX, &rdata_tail); }
+ break;
+ case 156:
+#line 1218 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_TXT, &rdata_tail); }
+ break;
+ case 157:
+#line 1219 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_RP, &rdata_tail); }
+ break;
+ case 158:
+#line 1220 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_AFSDB, &rdata_tail); }
+ break;
+ case 159:
+#line 1221 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_RT, &rdata_tail); }
+ break;
+ case 160:
+#line 1222 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_KEY, &rdata_tail); }
+ break;
+ case 161:
+#line 1223 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_AAAA, &rdata_tail); }
+ break;
+ case 162:
+#line 1224 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_LOC, &rdata_tail); }
+ break;
+ case 163:
+#line 1225 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_SRV, &rdata_tail); }
+ break;
+ case 164:
+#line 1226 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_NAPTR, &rdata_tail); }
+ break;
+ case 165:
+#line 1227 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_KX, &rdata_tail); }
+ break;
+ case 166:
+#line 1228 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_CERT, &rdata_tail); }
+ break;
+ case 167:
+#line 1229 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_DNAME, &rdata_tail); }
+ break;
+ case 168:
+#line 1230 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_APL, &rdata_tail); }
+ break;
+ case 169:
+#line 1231 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_DS, &rdata_tail); }
+ break;
+ case 170:
+#line 1232 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_SSHFP, &rdata_tail); }
+ break;
+ case 171:
+#line 1233 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_IPSECKEY, &rdata_tail); }
+ break;
+ case 172:
+#line 1234 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_RRSIG, &rdata_tail); }
+ break;
+ case 173:
+#line 1235 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_NSEC, &rdata_tail); }
+ break;
+ case 174:
+#line 1236 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_DNSKEY, &rdata_tail); }
+ break;
+ case 175:
+#line 1237 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_DHCID, &rdata_tail); }
+ break;
+ case 176:
+#line 1238 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_NSEC3, &rdata_tail); }
+ break;
+ case 177:
+#line 1239 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_NSEC3PARAM, &rdata_tail); }
+ break;
+ case 178:
+#line 1240 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_TLSA, &rdata_tail); }
+ break;
+ case 179:
+#line 1241 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_SPF, &rdata_tail); }
+ break;
+ case 180:
+#line 1242 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_NID, &rdata_tail); }
+ break;
+ case 181:
+#line 1243 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_L32, &rdata_tail); }
+ break;
+ case 182:
+#line 1244 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_L64, &rdata_tail); }
+ break;
+ case 183:
+#line 1245 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_LP, &rdata_tail); }
+ break;
+ case 184:
+#line 1246 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_EUI48, &rdata_tail); }
+ break;
+ case 185:
+#line 1247 "./zscanner/scanner_body.rl"
+ { type_num(KNOT_RRTYPE_EUI64, &rdata_tail); }
+ break;
+ case 186:
+#line 1253 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= UINT16_MAX) {
+ window_add_bit(s->number64, s);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 187:
+#line 1266 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_A, s); }
+ break;
+ case 188:
+#line 1267 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_NS, s); }
+ break;
+ case 189:
+#line 1268 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_CNAME, s); }
+ break;
+ case 190:
+#line 1269 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_SOA, s); }
+ break;
+ case 191:
+#line 1270 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_PTR, s); }
+ break;
+ case 192:
+#line 1271 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_HINFO, s); }
+ break;
+ case 193:
+#line 1272 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_MINFO, s); }
+ break;
+ case 194:
+#line 1273 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_MX, s); }
+ break;
+ case 195:
+#line 1274 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_TXT, s); }
+ break;
+ case 196:
+#line 1275 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_RP, s); }
+ break;
+ case 197:
+#line 1276 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_AFSDB, s); }
+ break;
+ case 198:
+#line 1277 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_RT, s); }
+ break;
+ case 199:
+#line 1278 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_KEY, s); }
+ break;
+ case 200:
+#line 1279 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_AAAA, s); }
+ break;
+ case 201:
+#line 1280 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_LOC, s); }
+ break;
+ case 202:
+#line 1281 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_SRV, s); }
+ break;
+ case 203:
+#line 1282 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_NAPTR, s); }
+ break;
+ case 204:
+#line 1283 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_KX, s); }
+ break;
+ case 205:
+#line 1284 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_CERT, s); }
+ break;
+ case 206:
+#line 1285 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_DNAME, s); }
+ break;
+ case 207:
+#line 1286 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_APL, s); }
+ break;
+ case 208:
+#line 1287 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_DS, s); }
+ break;
+ case 209:
+#line 1288 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_SSHFP, s); }
+ break;
+ case 210:
+#line 1289 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_IPSECKEY, s); }
+ break;
+ case 211:
+#line 1290 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_RRSIG, s); }
+ break;
+ case 212:
+#line 1291 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_NSEC, s); }
+ break;
+ case 213:
+#line 1292 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_DNSKEY, s); }
+ break;
+ case 214:
+#line 1293 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_DHCID, s); }
+ break;
+ case 215:
+#line 1294 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_NSEC3, s); }
+ break;
+ case 216:
+#line 1295 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_NSEC3PARAM, s); }
+ break;
+ case 217:
+#line 1296 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_TLSA, s); }
+ break;
+ case 218:
+#line 1297 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_SPF, s); }
+ break;
+ case 219:
+#line 1298 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_NID, s); }
+ break;
+ case 220:
+#line 1299 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_L32, s); }
+ break;
+ case 221:
+#line 1300 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_L64, s); }
+ break;
+ case 222:
+#line 1301 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_LP, s); }
+ break;
+ case 223:
+#line 1302 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_EUI48, s); }
+ break;
+ case 224:
+#line 1303 "./zscanner/scanner_body.rl"
+ { window_add_bit(KNOT_RRTYPE_EUI64, s); }
+ break;
+ case 225:
+#line 1307 "./zscanner/scanner_body.rl"
+ {
+ memset(s->windows, 0, sizeof(s->windows));
+ s->last_window = -1;
+ }
+ break;
+ case 226:
+#line 1311 "./zscanner/scanner_body.rl"
+ {
+ for (window = 0; window <= s->last_window; window++) {
+ if ((s->windows[window]).length > 0) {
+ if (rdata_tail + 2 + (s->windows[window]).length <= rdata_stop)
+ {
+ // Window number.
+ *rdata_tail = (uint8_t)window;
+ rdata_tail += 1;
+ // Bitmap length.
+ *rdata_tail = (s->windows[window]).length;
+ rdata_tail += 1;
+ // Copying bitmap.
+ memcpy(rdata_tail,
+ (s->windows[window]).bitmap,
+ (s->windows[window]).length);
+ rdata_tail += (s->windows[window]).length;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ }
+ }
+ break;
+ case 227:
+#line 1334 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_BITMAP);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 228:
+#line 1342 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 318; goto _again;} }
+ break;
+ case 229:
+#line 1346 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 90) {
+ s->loc.d1 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 230:
+#line 1354 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 180) {
+ s->loc.d2 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 231:
+#line 1362 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 59) {
+ s->loc.m1 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 232:
+#line 1370 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 59) {
+ s->loc.m2 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 233:
+#line 1378 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 59999) {
+ s->loc.s1 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 234:
+#line 1386 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 59999) {
+ s->loc.s2 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 235:
+#line 1394 "./zscanner/scanner_body.rl"
+ {
+ if ((s->loc.alt_sign == 1 && s->number64 <= 4284967295) ||
+ (s->loc.alt_sign == -1 && s->number64 <= 10000000))
+ {
+ s->loc.alt = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 236:
+#line 1404 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 9000000000ULL) {
+ s->loc.siz = s->number64;
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 237:
+#line 1412 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 9000000000ULL) {
+ s->loc.hp = s->number64;
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 238:
+#line 1420 "./zscanner/scanner_body.rl"
+ {
+ if (s->number64 <= 9000000000ULL) {
+ s->loc.vp = s->number64;
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 239:
+#line 1428 "./zscanner/scanner_body.rl"
+ {
+ s->loc.lat_sign = -1;
+ }
+ break;
+ case 240:
+#line 1431 "./zscanner/scanner_body.rl"
+ {
+ s->loc.long_sign = -1;
+ }
+ break;
+ case 241:
+#line 1434 "./zscanner/scanner_body.rl"
+ {
+ s->loc.alt_sign = -1;
+ }
+ break;
+ case 242:
+#line 1451 "./zscanner/scanner_body.rl"
+ {
+ memset(&(s->loc), 0, sizeof(s->loc));
+ // Defaults.
+ s->loc.siz = 100;
+ s->loc.vp = 1000;
+ s->loc.hp = 1000000;
+ s->loc.lat_sign = 1;
+ s->loc.long_sign = 1;
+ s->loc.alt_sign = 1;
+ }
+ break;
+ case 243:
+#line 1461 "./zscanner/scanner_body.rl"
+ {
+ // Write version.
+ *(rdata_tail) = 0;
+ rdata_tail += 1;
+ // Write size.
+ *(rdata_tail) = loc64to8(s->loc.siz);
+ rdata_tail += 1;
+ // Write horizontal precision.
+ *(rdata_tail) = loc64to8(s->loc.hp);
+ rdata_tail += 1;
+ // Write vertical precision.
+ *(rdata_tail) = loc64to8(s->loc.vp);
+ rdata_tail += 1;
+ // Write latitude.
+ *((uint32_t *)rdata_tail) = htonl(LOC_LAT_ZERO + s->loc.lat_sign *
+ (3600000 * s->loc.d1 + 60000 * s->loc.m1 + s->loc.s1));
+ rdata_tail += 4;
+ // Write longitude.
+ *((uint32_t *)rdata_tail) = htonl(LOC_LONG_ZERO + s->loc.long_sign *
+ (3600000 * s->loc.d2 + 60000 * s->loc.m2 + s->loc.s2));
+ rdata_tail += 4;
+ // Write altitude.
+ *((uint32_t *)rdata_tail) = htonl(LOC_ALT_ZERO + s->loc.alt_sign *
+ (s->loc.alt));
+ rdata_tail += 4;
+ }
+ break;
+ case 244:
+#line 1487 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_LOC_DATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 245:
+#line 1500 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_RDATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 246:
+#line 1518 "./zscanner/scanner_body.rl"
+ {
+ s->item_length = 0;
+ }
+ break;
+ case 247:
+#line 1521 "./zscanner/scanner_body.rl"
+ {
+ s->item_length++;
+ }
+ break;
+ case 248:
+#line 1524 "./zscanner/scanner_body.rl"
+ {
+ if (s->item_length != 6) {
+ SCANNER_WARNING(ZSCANNER_EBAD_EUI_LENGTH);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 249:
+#line 1530 "./zscanner/scanner_body.rl"
+ {
+ if (s->item_length != 8) {
+ SCANNER_WARNING(ZSCANNER_EBAD_EUI_LENGTH);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 250:
+#line 1536 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_CHAR_DASH);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 251:
+#line 1551 "./zscanner/scanner_body.rl"
+ {
+ s->item_length = 0;
+ }
+ break;
+ case 252:
+#line 1554 "./zscanner/scanner_body.rl"
+ {
+ s->item_length++;
+ }
+ break;
+ case 253:
+#line 1557 "./zscanner/scanner_body.rl"
+ {
+ if (s->item_length != 4) {
+ SCANNER_WARNING(ZSCANNER_EBAD_L64_LENGTH);
+ p--; {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 254:
+#line 1563 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_CHAR_COLON);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 255:
+#line 1576 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_ALGORITHM);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 256:
+#line 1580 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_CERT_TYPE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 257:
+#line 1602 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 457; goto _again;} }
+ break;
+ case 258:
+#line 1617 "./zscanner/scanner_body.rl"
+ { p--; {stack[top++] = cs; cs = 552; goto _again;} }
+ break;
+ case 259:
+#line 1621 "./zscanner/scanner_body.rl"
+ {
+ s->r_data_blocks[0] = 0;
+ s->r_data_blocks_count = 0;
+ rdata_tail = s->r_data;
+ }
+ break;
+ case 260:
+#line 1626 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_RDATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 261:
+#line 1744 "./zscanner/scanner_body.rl"
+ {
+ p--;
+ switch (s->r_type) {
+ case KNOT_RRTYPE_A:
+ {stack[top++] = cs; cs = 593; goto _again;}
+ case KNOT_RRTYPE_NS:
+ case KNOT_RRTYPE_CNAME:
+ case KNOT_RRTYPE_PTR:
+ case KNOT_RRTYPE_DNAME:
+ {stack[top++] = cs; cs = 595; goto _again;}
+ case KNOT_RRTYPE_SOA:
+ {stack[top++] = cs; cs = 597; goto _again;}
+ case KNOT_RRTYPE_HINFO:
+ {stack[top++] = cs; cs = 629; goto _again;}
+ case KNOT_RRTYPE_MINFO:
+ case KNOT_RRTYPE_RP:
+ {stack[top++] = cs; cs = 634; goto _again;}
+ case KNOT_RRTYPE_MX:
+ case KNOT_RRTYPE_AFSDB:
+ case KNOT_RRTYPE_RT:
+ case KNOT_RRTYPE_KX:
+ case KNOT_RRTYPE_LP:
+ {stack[top++] = cs; cs = 639; goto _again;}
+ case KNOT_RRTYPE_TXT:
+ case KNOT_RRTYPE_SPF:
+ {stack[top++] = cs; cs = 644; goto _again;}
+ case KNOT_RRTYPE_AAAA:
+ {stack[top++] = cs; cs = 648; goto _again;}
+ case KNOT_RRTYPE_LOC:
+ {stack[top++] = cs; cs = 650; goto _again;}
+ case KNOT_RRTYPE_SRV:
+ {stack[top++] = cs; cs = 705; goto _again;}
+ case KNOT_RRTYPE_NAPTR:
+ {stack[top++] = cs; cs = 716; goto _again;}
+ case KNOT_RRTYPE_CERT:
+ {stack[top++] = cs; cs = 733; goto _again;}
+ case KNOT_RRTYPE_APL:
+ {stack[top++] = cs; cs = 744; goto _again;}
+ case KNOT_RRTYPE_DS:
+ {stack[top++] = cs; cs = 755; goto _again;}
+ case KNOT_RRTYPE_SSHFP:
+ {stack[top++] = cs; cs = 768; goto _again;}
+ case KNOT_RRTYPE_IPSECKEY:
+ {stack[top++] = cs; cs = 778; goto _again;}
+ case KNOT_RRTYPE_RRSIG:
+ {stack[top++] = cs; cs = 817; goto _again;}
+ case KNOT_RRTYPE_NSEC:
+ {stack[top++] = cs; cs = 959; goto _again;}
+ case KNOT_RRTYPE_KEY:
+ case KNOT_RRTYPE_DNSKEY:
+ {stack[top++] = cs; cs = 962; goto _again;}
+ case KNOT_RRTYPE_DHCID:
+ {stack[top++] = cs; cs = 973; goto _again;}
+ case KNOT_RRTYPE_NSEC3:
+ {stack[top++] = cs; cs = 975; goto _again;}
+ case KNOT_RRTYPE_NSEC3PARAM:
+ {stack[top++] = cs; cs = 1004; goto _again;}
+ case KNOT_RRTYPE_TLSA:
+ {stack[top++] = cs; cs = 1017; goto _again;}
+ case KNOT_RRTYPE_NID:
+ case KNOT_RRTYPE_L64:
+ {stack[top++] = cs; cs = 1035; goto _again;}
+ case KNOT_RRTYPE_L32:
+ {stack[top++] = cs; cs = 1030; goto _again;}
+ case KNOT_RRTYPE_EUI48:
+ {stack[top++] = cs; cs = 1048; goto _again;}
+ case KNOT_RRTYPE_EUI64:
+ {stack[top++] = cs; cs = 1054; goto _again;}
+ default:
+ SCANNER_WARNING(ZSCANNER_ECANNOT_TEXT_DATA);
+ {cs = 247; goto _again;}
+ }
+ }
+ break;
+ case 262:
+#line 1817 "./zscanner/scanner_body.rl"
+ {
+ switch (s->r_type) {
+ // Next types must not have empty rdata.
+ case KNOT_RRTYPE_A:
+ case KNOT_RRTYPE_NS:
+ case KNOT_RRTYPE_CNAME:
+ case KNOT_RRTYPE_PTR:
+ case KNOT_RRTYPE_DNAME:
+ case KNOT_RRTYPE_SOA:
+ case KNOT_RRTYPE_HINFO:
+ case KNOT_RRTYPE_MINFO:
+ case KNOT_RRTYPE_MX:
+ case KNOT_RRTYPE_AFSDB:
+ case KNOT_RRTYPE_RT:
+ case KNOT_RRTYPE_KX:
+ case KNOT_RRTYPE_TXT:
+ case KNOT_RRTYPE_SPF:
+ case KNOT_RRTYPE_RP:
+ case KNOT_RRTYPE_AAAA:
+ case KNOT_RRTYPE_LOC:
+ case KNOT_RRTYPE_SRV:
+ case KNOT_RRTYPE_NAPTR:
+ case KNOT_RRTYPE_CERT:
+ case KNOT_RRTYPE_DS:
+ case KNOT_RRTYPE_SSHFP:
+ case KNOT_RRTYPE_IPSECKEY:
+ case KNOT_RRTYPE_RRSIG:
+ case KNOT_RRTYPE_NSEC:
+ case KNOT_RRTYPE_KEY:
+ case KNOT_RRTYPE_DNSKEY:
+ case KNOT_RRTYPE_DHCID:
+ case KNOT_RRTYPE_NSEC3:
+ case KNOT_RRTYPE_NSEC3PARAM:
+ case KNOT_RRTYPE_TLSA:
+ case KNOT_RRTYPE_NID:
+ case KNOT_RRTYPE_L32:
+ case KNOT_RRTYPE_L64:
+ case KNOT_RRTYPE_LP:
+ case KNOT_RRTYPE_EUI48:
+ case KNOT_RRTYPE_EUI64:
+ {stack[top++] = cs; cs = 438; goto _again;}
+ // Next types can have empty rdata.
+ case KNOT_RRTYPE_APL:
+ default:
+ {stack[top++] = cs; cs = 447; goto _again;}
+ }
+ }
+ break;
+ case 263:
+#line 1865 "./zscanner/scanner_body.rl"
+ {
+ s->r_data_blocks[++(s->r_data_blocks_count)] =
+ (uint16_t)(rdata_tail - s->r_data);
+ }
+ break;
+ case 264:
+#line 1873 "./zscanner/scanner_body.rl"
+ { p--; }
+ break;
+ case 265:
+#line 1880 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EUNSUPPORTED_TYPE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 266:
+#line 1886 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_A; }
+ break;
+ case 267:
+#line 1887 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_NS; }
+ break;
+ case 268:
+#line 1888 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_CNAME; }
+ break;
+ case 269:
+#line 1889 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_SOA; }
+ break;
+ case 270:
+#line 1890 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_PTR; }
+ break;
+ case 271:
+#line 1891 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_HINFO; }
+ break;
+ case 272:
+#line 1892 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_MINFO; }
+ break;
+ case 273:
+#line 1893 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_MX; }
+ break;
+ case 274:
+#line 1894 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_TXT; }
+ break;
+ case 275:
+#line 1895 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_RP; }
+ break;
+ case 276:
+#line 1896 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_AFSDB; }
+ break;
+ case 277:
+#line 1897 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_RT; }
+ break;
+ case 278:
+#line 1898 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_KEY; }
+ break;
+ case 279:
+#line 1899 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_AAAA; }
+ break;
+ case 280:
+#line 1900 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_LOC; }
+ break;
+ case 281:
+#line 1901 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_SRV; }
+ break;
+ case 282:
+#line 1902 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_NAPTR; }
+ break;
+ case 283:
+#line 1903 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_KX; }
+ break;
+ case 284:
+#line 1904 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_CERT; }
+ break;
+ case 285:
+#line 1905 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_DNAME; }
+ break;
+ case 286:
+#line 1906 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_APL; }
+ break;
+ case 287:
+#line 1907 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_DS; }
+ break;
+ case 288:
+#line 1908 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_SSHFP; }
+ break;
+ case 289:
+#line 1909 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_IPSECKEY; }
+ break;
+ case 290:
+#line 1910 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_RRSIG; }
+ break;
+ case 291:
+#line 1911 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_NSEC; }
+ break;
+ case 292:
+#line 1912 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_DNSKEY; }
+ break;
+ case 293:
+#line 1913 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_DHCID; }
+ break;
+ case 294:
+#line 1914 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_NSEC3; }
+ break;
+ case 295:
+#line 1915 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_NSEC3PARAM; }
+ break;
+ case 296:
+#line 1916 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_TLSA; }
+ break;
+ case 297:
+#line 1917 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_SPF; }
+ break;
+ case 298:
+#line 1918 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_NID; }
+ break;
+ case 299:
+#line 1919 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_L32; }
+ break;
+ case 300:
+#line 1920 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_L64; }
+ break;
+ case 301:
+#line 1921 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_LP; }
+ break;
+ case 302:
+#line 1922 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_EUI48; }
+ break;
+ case 303:
+#line 1923 "./zscanner/scanner_body.rl"
+ { s->r_type = KNOT_RRTYPE_EUI64; }
+ break;
+ case 304:
+#line 1929 "./zscanner/scanner_body.rl"
+ {
+ if (rdata_tail - s->r_data > UINT16_MAX) {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ p--; {cs = 247; goto _again;}
+ }
+ s->r_data_length = rdata_tail - s->r_data;
+
+ s->process_record(s);
+ }
+ break;
+#line 7499 "zscanner/scanner.c"
+ }
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ const short *__acts = _zone_scanner_actions + _zone_scanner_eof_actions[cs];
+ unsigned int __nacts = (unsigned int) *__acts++;
+ while ( __nacts-- > 0 ) {
+ switch ( *__acts++ ) {
+ case 4:
+#line 44 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_REST);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 15:
+#line 143 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 20:
+#line 189 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_DNAME_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 28:
+#line 242 "./zscanner/scanner_body.rl"
+ {
+ s->r_owner_length = 0;
+ SCANNER_WARNING(ZSCANNER_EBAD_OWNER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 33:
+#line 285 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 45:
+#line 386 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIME_UNIT);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 55:
+#line 491 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIMESTAMP_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 57:
+#line 509 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TEXT_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 58:
+#line 513 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_TEXT);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 62:
+#line 543 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 65:
+#line 583 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_TTL);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 69:
+#line 600 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_ORIGIN);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 73:
+#line 629 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_FILENAME);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 76:
+#line 640 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_ORIGIN);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 80:
+#line 721 "./zscanner/scanner_body.rl"
+ {
+ s->stop = false;
+ }
+ break;
+ case 81:
+#line 724 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_ERROR(ZSCANNER_EBAD_DIRECTIVE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 88:
+#line 775 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_ADDRESS_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 99:
+#line 875 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_APL);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 102:
+#line 905 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 104:
+#line 932 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_RDATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 109:
+#line 974 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_BASE64_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 119:
+#line 1058 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_BASE32HEX_CHAR);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 145:
+#line 1182 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_GATEWAY);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 146:
+#line 1186 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_GATEWAY_KEY);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 147:
+#line 1204 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EUNSUPPORTED_TYPE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 227:
+#line 1334 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_BITMAP);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 244:
+#line 1487 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_LOC_DATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 245:
+#line 1500 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_RDATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 250:
+#line 1536 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_CHAR_DASH);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 254:
+#line 1563 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_CHAR_COLON);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 255:
+#line 1576 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_ALGORITHM);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 256:
+#line 1580 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_CERT_TYPE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 260:
+#line 1626 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EBAD_RDATA);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+ case 265:
+#line 1880 "./zscanner/scanner_body.rl"
+ {
+ SCANNER_WARNING(ZSCANNER_EUNSUPPORTED_TYPE);
+ p--; {cs = 247; goto _again;}
+ }
+ break;
+#line 7753 "zscanner/scanner.c"
+ }
+ }
+ }
+
+ _out: {}
+ }
+
+#line 144 "./zscanner/scanner.rl"
+
+ // Check if scanner state machine is in uncovered state.
+ if (cs == zone_scanner_error) {
+ SCANNER_ERROR(ZSCANNER_UNCOVERED_STATE);
+ s->error_counter++;
+
+ // Fill error context data.
+ for (s->buffer_length = 0;
+ ((p + s->buffer_length) < pe) &&
+ (s->buffer_length < sizeof(s->buffer) - 1);
+ s->buffer_length++)
+ {
+ // Only rest of the current line.
+ if (*(p + s->buffer_length) == '\n') {
+ break;
+ }
+ s->buffer[s->buffer_length] = *(p + s->buffer_length);
+ }
+
+ // Ending string in buffer.
+ s->buffer[s->buffer_length++] = 0;
+
+ // Processing error.
+ s->process_error(s);
+
+ return -1;
+ }
+
+ // Storing scanner states.
+ s->cs = cs;
+ s->top = top;
+ memcpy(s->stack, stack, sizeof(stack));
+
+ // Storing r_data pointer.
+ s->r_data_tail = rdata_tail - s->r_data;
+
+ // Check if any errors has occured.
+ if (s->error_counter > 0) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/zscanner/scanner.h b/src/zscanner/scanner.h
new file mode 100644
index 0000000..e8ff355
--- /dev/null
+++ b/src/zscanner/scanner.h
@@ -0,0 +1,270 @@
+/* Copyright (C) 2011 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 scanner.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Zone scanner.
+ *
+ * \addtogroup zone_scanner
+ * @{
+ */
+
+#ifndef _ZSCANNER__SCANNER_H_
+#define _ZSCANNER__SCANNER_H_
+
+#include <stdint.h> // uint32_t
+#include <stdbool.h> // bool
+
+/*! \brief Maximal length of rdata. */
+#define MAX_RDATA_LENGTH 65535
+/*! \brief Maximal length of rdata item. */
+#define MAX_ITEM_LENGTH 255
+/*! \brief Maximal length of domain name. */
+#define MAX_DNAME_LENGTH 255
+/*! \brief Maximal length of domain name label. */
+#define MAX_LABEL_LENGTH 63
+/*! \brief Maximal number or rdata items. */
+#define MAX_RDATA_ITEMS 64
+
+/*! \brief Number of bitmap windows. */
+#define BITMAP_WINDOWS 256
+
+/*! \brief Length of ipv4 address in wire format. */
+#define INET4_ADDR_LENGTH 4
+/*! \brief Length of ipv6 address in wire format. */
+#define INET6_ADDR_LENGTH 16
+
+/*! \brief Ragel call stack size (see Ragel internals). */
+#define RAGEL_STACK_SIZE 16
+
+/*! \brief ASCII value of '0' character. */
+#define ASCII_0 48
+
+/*! \brief Latitude value for equator (2^31). */
+#define LOC_LAT_ZERO (uint32_t)2147483648
+/*! \brief Longitude value for meridian (2^31). */
+#define LOC_LONG_ZERO (uint32_t)2147483648
+/*! \brief Zero level altitude value. */
+#define LOC_ALT_ZERO (uint32_t)10000000
+
+/*! \brief Auxiliary structure for storing bitmap window items (see RFC4034). */
+typedef struct {
+ uint8_t bitmap[32];
+ uint8_t length;
+} window_t;
+
+/*! \brief Auxiliary structure for storing one APL record (see RFC3123). */
+typedef struct {
+ uint8_t excl_flag;
+ uint16_t addr_family;
+ uint8_t prefix_length;
+} apl_t;
+
+/*! \brief Auxiliary structure for storing LOC information (see RFC1876). */
+typedef struct {
+ uint32_t d1, d2;
+ uint32_t m1, m2;
+ uint32_t s1, s2;
+ uint32_t alt;
+ uint64_t siz, hp, vp;
+ int8_t lat_sign, long_sign, alt_sign;
+} loc_t;
+
+/*!
+ * \brief Context structure for Ragel scanner.
+ *
+ * This structure contains folowing items:
+ * - Copies of Ragel internal variables. The scanner is called many times
+ * for each block of zone file. So it is necessary to preserve internal
+ * values between subsequent scanner callings.
+ * - Auxiliary variables which are used during processing zone data.
+ * - Zone file and error information.
+ * - Pointers to callback functions and pointer to any arbitrary data which
+ * can be used in callback functions.
+ * - Output variables containing all parts of zone record. These data are
+ * usefull during processing via callback function.
+ */
+typedef struct scanner scanner_t; // Forward declaration due to arguments.
+struct scanner {
+ /*! Current state (Ragel internals). */
+ int cs;
+ /*! Stack top (Ragel internals). */
+ int top;
+ /*! Call stack (Ragel internals). */
+ int stack[RAGEL_STACK_SIZE];
+
+ /*! Zone file name. */
+ char *file_name;
+ /*! Zone file line counter. */
+ uint64_t line_counter;
+
+ /*! Last occured error/warning code. */
+ int error_code;
+ /*! Errors/warnings counter. */
+ uint64_t error_counter;
+ /*!
+ * Indicates serious warning which is considered as an error and
+ * forces zone processing to stop.
+ */
+ bool stop;
+
+ /*! Callback function for correct zone record. */
+ void (*process_record)(const scanner_t *);
+ /*! Callback function for wrong situations. */
+ void (*process_error)(const scanner_t *);
+ /*! Arbitrary data useful inside callback functions. */
+ void *data;
+
+ /*! Indicates whether current record is multiline. */
+ bool multiline;
+ /*! Auxiliary number for all numeric operations. */
+ uint64_t number64;
+ /*! Auxiliary variable for time and other numeric operations. */
+ uint64_t number64_tmp;
+ /*! Auxiliary variable for float numeric operations. */
+ uint32_t decimals;
+ /*! Auxiliary variable for float numeric operations. */
+ uint32_t decimal_counter;
+
+ /*! Auxiliary variable for item length (label, base64, ...). */
+ uint32_t item_length;
+ /*! Auxiliary index for item length position in array. */
+ uint32_t item_length_position;
+ /*! Auxiliary pointer to item length. */
+ uint8_t *item_length_location;
+ /*! Auxiliary buffer for data storing. */
+ uint8_t buffer[MAX_RDATA_LENGTH];
+ /*! Auxiliary buffer length. */
+ uint32_t buffer_length;
+ /*! Auxiliary buffer for current included file name. */
+ char include_filename[MAX_RDATA_LENGTH + 1];
+
+ /*! Auxiliary array of bitmap window blocks. */
+ window_t windows[BITMAP_WINDOWS];
+ /*! Last window block which is used (-1 means no window). */
+ int16_t last_window;
+ /*! Auxiliary apl structure. */
+ apl_t apl;
+ /*! Auxiliary loc structure. */
+ loc_t loc;
+
+ /*! Pointer to the actual dname storage (origin/owner/rdata). */
+ uint8_t *dname;
+ /*! Pointer to the actual dname length storage. */
+ uint32_t *dname_length;
+ /*!
+ * Temporary dname length which is copied to dname_length after
+ * dname processing.
+ */
+ uint32_t dname_tmp_length;
+ /*! Position of the last free r_data byte. */
+ uint32_t r_data_tail;
+
+ /*! Wire format of the current origin (ORIGIN directive sets this). */
+ uint8_t zone_origin[MAX_DNAME_LENGTH];
+ /*! Length of the current origin. */
+ uint32_t zone_origin_length;
+ /*! Value of the default class. */
+ uint16_t default_class;
+ /*! Value of the current default ttl (TTL directive sets this). */
+ uint32_t default_ttl;
+
+ /*!
+ * Owner of the current record.
+ *
+ * \note The double length of the r_owner is due to dname length
+ * check is after concatenation of relative and origin dnames.
+ */
+ uint8_t r_owner[2 * MAX_DNAME_LENGTH];
+ /*! Length of the current record owner. */
+ uint32_t r_owner_length;
+ /*! Class of the current record. */
+ uint16_t r_class;
+ /*! TTL of the current record. */
+ uint32_t r_ttl;
+ /*! Type of the current record data. */
+ uint16_t r_type;
+ /*! Current rdata. */
+ uint8_t r_data[MAX_RDATA_LENGTH];
+ /*! Length of the current rdata. */
+ uint32_t r_data_length;
+ /*! Indexes of the current rdata blocks. */
+ uint16_t r_data_blocks[MAX_RDATA_ITEMS];
+ /*! Number or the current rdata blocks. */
+ uint32_t r_data_blocks_count;
+
+ /*
+ * Example: a. IN 60 MX 1 b.
+ *
+ * r_owner = 016100
+ * r_owner_length = 3
+ * r_class = 1
+ * r_ttl = 60
+ * r_type = 15
+ * r_data = 0001016200
+ * r_data_length = 5
+ * r_data_blocks_count = 2
+ * r_data_blocks = [0, 2, 5]
+ */
+};
+
+/*!
+ * \brief Creates zone scanner structure.
+ *
+ * \note After creation scanner structure, it is necessary to set next items:
+ * process_record, process_error, default_class, default_ttl, zone_origin.
+ *
+ * \param file_name Zone file name. If parsing from memory use arbitrary
+ * directory name (like "."), because relative includes
+ * are considered to this file.
+ *
+ * \retval scanner if success.
+ * \retval 0 if error.
+ */
+scanner_t* scanner_create(const char *file_name);
+
+/*!
+ * \brief Destroys zone scanner structure.
+ *
+ * \param scanner Zone scanner structure.
+ */
+void scanner_free(scanner_t *scanner);
+
+/*!
+ * \brief Executes zone scanner on data block.
+ *
+ * \note Zone scanner error code and other information are stored in
+ * the scanner structure.
+ *
+ * \param start First byte of the zone data to scan.
+ * \param end Last byte of the zone data to scan.
+ * \param is_last_block Indicates if current block is last.
+ * \param scanner Zone scanner structure.
+ *
+ * \retval 0 if success.
+ * \retval -1 if error.
+ */
+int scanner_process(const char *start,
+ const char *end,
+ const bool is_last_block,
+ scanner_t *scanner);
+
+
+#endif // _ZSCANNER__SCANNER_H_
+
+/*! @} */
diff --git a/src/zscanner/scanner.rl b/src/zscanner/scanner.rl
new file mode 100644
index 0000000..833e043
--- /dev/null
+++ b/src/zscanner/scanner.rl
@@ -0,0 +1,186 @@
+/* Copyright (C) 2011 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 "zscanner/scanner.h"
+
+#include <stdint.h> // uint32_t
+#include <stdlib.h> // calloc
+#include <stdio.h> // sprintf
+#include <libgen.h> // dirname
+#include <stdbool.h> // bool
+#include <math.h> // pow
+#include <string.h> // strdup
+#include <sys/types.h> // (OpenBSD)
+#include <sys/socket.h> // AF_INET (BSD)
+#include <netinet/in.h> // in_addr (BSD)
+#include <arpa/inet.h> // inet_pton
+
+#include "common/errcode.h" // error codes
+#include "common/descriptor.h" // KNOT_RRTYPE_A
+#include "zscanner/file_loader.h" // file_loader
+#include "zscanner/scanner_functions.h" // Base64
+
+/*! \brief Shorthand for setting warning data. */
+#define SCANNER_WARNING(code) { s->error_code = code; }
+/*! \brief Shorthand for setting error data. */
+#define SCANNER_ERROR(code) { s->error_code = code; s->stop = true; }
+
+/*!
+ * \brief Writes record type number to r_data.
+ *
+ * \param type Type number.
+ * \param rdata_tail Position where to write type number to.
+ */
+static inline void type_num(const uint16_t type, uint8_t **rdata_tail)
+{
+ *((uint16_t *)*rdata_tail) = htons(type);
+ *rdata_tail += 2;
+}
+
+/*!
+ * \brief Sets bit to bitmap window.
+ *
+ * \param type Type number.
+ * \param s Scanner context.
+ */
+static inline void window_add_bit(const uint16_t type, scanner_t *s) {
+ uint8_t win = type / 256;
+ uint8_t bit_pos = type % 256;
+ uint8_t byte_pos = bit_pos / 8;
+
+ ((s->windows[win]).bitmap)[byte_pos] |= 128 >> (bit_pos % 8);
+
+ if ((s->windows[win]).length < byte_pos + 1) {
+ (s->windows[win]).length = byte_pos + 1;
+ }
+
+ if (s->last_window < win) {
+ s->last_window = win;
+ }
+}
+
+// Include scanner file (in Ragel).
+%%{
+ machine zone_scanner;
+
+ include "scanner_body.rl";
+
+ write data;
+}%%
+
+scanner_t* scanner_create(const char *file_name)
+{
+ scanner_t *s = calloc(1, sizeof(scanner_t));
+ if (s == NULL) {
+ return NULL;
+ }
+
+ s->file_name = strdup(file_name);
+ s->line_counter = 1;
+
+ // Nonzero initial scanner state.
+ s->cs = zone_scanner_start;
+
+ return s;
+}
+
+void scanner_free(scanner_t *s)
+{
+ if (s != NULL) {
+ free(s->file_name);
+ free(s);
+ }
+}
+
+int scanner_process(const char *start,
+ const char *end,
+ const bool is_last_block,
+ scanner_t *s)
+{
+ // Necessary scanner variables.
+ const char *p = start;
+ const char *pe = end;
+ char *eof = NULL;
+ int stack[RAGEL_STACK_SIZE];
+
+ // Auxiliary variables which are used in scanner body.
+ struct in_addr addr4;
+ struct in6_addr addr6;
+ uint32_t timestamp;
+ int16_t window;
+ int ret;
+
+ // Next 2 variables are for better performance.
+ // Restoring r_data pointer to next free space.
+ uint8_t *rdata_tail = s->r_data + s->r_data_tail;
+ // Initialization of the last r_data byte.
+ uint8_t *rdata_stop = s->r_data + MAX_RDATA_LENGTH - 1;
+
+ // Restoring scanner states.
+ int cs = s->cs;
+ int top = s->top;
+ memcpy(stack, s->stack, sizeof(stack));
+
+ // End of file check.
+ if (is_last_block == true) {
+ eof = (char *)pe;
+ }
+
+ // Writing scanner body (in C).
+ %% write exec;
+
+ // Check if scanner state machine is in uncovered state.
+ if (cs == zone_scanner_error) {
+ SCANNER_ERROR(ZSCANNER_UNCOVERED_STATE);
+ s->error_counter++;
+
+ // Fill error context data.
+ for (s->buffer_length = 0;
+ ((p + s->buffer_length) < pe) &&
+ (s->buffer_length < sizeof(s->buffer) - 1);
+ s->buffer_length++)
+ {
+ // Only rest of the current line.
+ if (*(p + s->buffer_length) == '\n') {
+ break;
+ }
+ s->buffer[s->buffer_length] = *(p + s->buffer_length);
+ }
+
+ // Ending string in buffer.
+ s->buffer[s->buffer_length++] = 0;
+
+ // Processing error.
+ s->process_error(s);
+
+ return -1;
+ }
+
+ // Storing scanner states.
+ s->cs = cs;
+ s->top = top;
+ memcpy(s->stack, stack, sizeof(stack));
+
+ // Storing r_data pointer.
+ s->r_data_tail = rdata_tail - s->r_data;
+
+ // Check if any errors has occured.
+ if (s->error_counter > 0) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/zscanner/scanner_body.rl b/src/zscanner/scanner_body.rl
new file mode 100644
index 0000000..ea76c54
--- /dev/null
+++ b/src/zscanner/scanner_body.rl
@@ -0,0 +1,1956 @@
+/* Copyright (C) 2011 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/>.
+ */
+%%{
+ machine zone_scanner;
+
+ # Comeback function to calling state machine.
+ action _ret {
+ fhold; fret;
+ }
+
+ # BEGIN - Blank space processing
+ action _newline {
+ s->line_counter++;
+ }
+
+ action _check_multiline_begin {
+ if (s->multiline == true) {
+ SCANNER_ERROR(ZSCANNER_ELEFT_PARENTHESIS);
+ fhold; fgoto err_line;
+ }
+ s->multiline = true;
+ }
+ action _check_multiline_end {
+ if (s->multiline == false) {
+ SCANNER_ERROR(ZSCANNER_ERIGHT_PARENTHESIS);
+ fhold; fgoto err_line;
+ }
+ s->multiline = false;
+ }
+
+ action _rest_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_REST);
+ fhold; fgoto err_line;
+ }
+
+ newline = '\n' $_newline;
+ comment = ';' . (^newline)*;
+
+ # White space separation. With respect to parentheses and included comments.
+ sep = ( [ \t] # Blank characters.
+ | (comment? . newline) when { s->multiline } # Comment in multiline.
+ | '(' $_check_multiline_begin # Start of multiline.
+ | ')' $_check_multiline_end # End of multiline.
+ )+; # Apply more times.
+
+ rest = (sep? :> comment?) $!_rest_error; # Useless text after record.
+
+ # Artificial machines which are used for next state transition only!
+ all_wchar = [ \t\n;()];
+ end_wchar = [\n;] when { !s->multiline }; # For noncontinuous ending tokens.
+ # END
+
+ # BEGIN - Error line processing
+ action _err_line_init {
+ s->buffer_length = 0;
+ }
+ action _err_line {
+ if (s->buffer_length < sizeof(s->buffer) - 1) {
+ s->buffer[s->buffer_length++] = fc;
+ }
+ }
+ action _err_line_exit {
+ // Ending string in buffer.
+ s->buffer[s->buffer_length++] = 0;
+
+ // Error counter incrementation.
+ s->error_counter++;
+
+ // Initialization of fcall stack.
+ top = 0;
+
+ // Process error message.
+ s->process_error(s);
+
+ // Reset.
+ s->error_code = KNOT_EOK;
+ s->multiline = false;
+
+ // In case of serious error, stop scanner.
+ if (s->stop == true) {
+ return -1;
+ }
+ }
+
+ # Fill rest of the line to buffer and skip to main loop.
+ err_line := (^newline $_err_line)* >_err_line_init
+ %_err_line_exit . newline @{ fgoto main; };
+ # END
+
+ # BEGIN - Domain name labels processing
+ action _label_init {
+ s->item_length = 0;
+ s->item_length_position = s->dname_tmp_length++;
+ }
+ action _label_char {
+ if (s->item_length < MAX_LABEL_LENGTH) {
+ (s->dname)[s->dname_tmp_length++] = fc;
+ s->item_length++;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ELABEL_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _label_exit {
+ if (s->dname_tmp_length < MAX_DNAME_LENGTH) {
+ (s->dname)[s->item_length_position] =
+ (uint8_t)(s->item_length);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EDNAME_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ action _label_dec_init {
+ if (s->item_length < MAX_LABEL_LENGTH) {
+ (s->dname)[s->dname_tmp_length] = 0;
+ s->item_length++;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ELABEL_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _label_dec {
+ (s->dname)[s->dname_tmp_length] *= 10;
+ (s->dname)[s->dname_tmp_length] += digit_to_num[(uint8_t)fc];
+ }
+ action _label_dec_exit {
+ s->dname_tmp_length++;
+ }
+ action _label_dec_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+
+ label_char =
+ ( (alnum | [\-_/]) $_label_char # One common char.
+ | ('\\' . ^digit) @_label_char # One "\x" char.
+ | ('\\' %_label_dec_init # Initial "\" char.
+ . digit {3} $_label_dec %_label_dec_exit # "DDD" rest.
+ $!_label_dec_error
+ )
+ );
+
+ label = (label_char+ | ('*' $_label_char)) >_label_init %_label_exit;
+ labels = (label . '.')* . label;
+ # END
+
+ # BEGIN - Domain name processing.
+ action _absolute_dname_exit {
+ (s->dname)[s->dname_tmp_length++] = 0;
+ }
+ action _relative_dname_exit {
+ memcpy(s->dname + s->dname_tmp_length,
+ s->zone_origin,
+ s->zone_origin_length);
+
+ s->dname_tmp_length += s->zone_origin_length;
+
+ if (s->dname_tmp_length > MAX_DNAME_LENGTH) {
+ SCANNER_WARNING(ZSCANNER_EDNAME_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _origin_dname_exit {
+ memcpy(s->dname,
+ s->zone_origin,
+ s->zone_origin_length);
+
+ s->dname_tmp_length = s->zone_origin_length;
+ }
+
+ action _dname_init {
+ s->item_length_position = 0;
+ s->dname_tmp_length = 0;
+ }
+ action _dname_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_DNAME_CHAR);
+ fhold; fgoto err_line;
+ }
+
+ relative_dname = (labels ) >_dname_init %_relative_dname_exit;
+ absolute_dname = (labels? . '.') >_dname_init %_absolute_dname_exit;
+
+ dname_ := ( relative_dname
+ | absolute_dname
+ | '@' %_origin_dname_exit
+ ) $!_dname_error %_ret . all_wchar;
+ dname = (alnum | [\-_/\\] | [*.@]) ${ fhold; fcall dname_; };
+ # END
+
+ # BEGIN - Common r_data item processing
+ action _item_length_init {
+ s->item_length_location = rdata_tail++;
+ }
+ action _item_length_exit {
+ s->item_length = rdata_tail - s->item_length_location - 1;
+
+ if (s->item_length <= MAX_ITEM_LENGTH) {
+ *(s->item_length_location) = (uint8_t)(s->item_length);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EITEM_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ action _separate {
+ s->r_data_blocks[++(s->r_data_blocks_count)] =
+ rdata_tail - s->r_data;
+ }
+
+ # Rdata blocks dividing.
+ blk_sep = zlen >_separate;
+ # END
+
+ # BEGIN - Owner processing
+ action _r_owner_init {
+ s->dname = s->r_owner;
+ s->r_owner_length = 0;
+ }
+ action _r_owner_exit {
+ s->r_owner_length = s->dname_tmp_length;
+ }
+ action _r_owner_empty_exit {
+ if (s->r_owner_length == 0) {
+ SCANNER_WARNING(ZSCANNER_EBAD_PREVIOUS_OWNER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _r_owner_error {
+ s->r_owner_length = 0;
+ SCANNER_WARNING(ZSCANNER_EBAD_OWNER);
+ fhold; fgoto err_line;
+ }
+
+ r_owner = ( dname >_r_owner_init %_r_owner_exit
+ | zlen %_r_owner_empty_exit # Empty owner - use the previous one.
+ ) $!_r_owner_error;
+ # END
+
+ # BEGIN - domain name in record data processing
+ action _r_dname_init {
+ s->dname = rdata_tail;
+ }
+ action _r_dname_exit {
+ rdata_tail += s->dname_tmp_length;
+ }
+
+ r_dname = dname >_r_dname_init %_r_dname_exit;
+ # END
+
+ # BEGIN - Number processing
+ action _number_digit {
+ // Overflow check: 10*(s->number64) + fc - ASCII_0 <= UINT64_MAX
+ if ((s->number64 < (UINT64_MAX / 10)) || // Dominant fast check.
+ ((s->number64 == (UINT64_MAX / 10)) && // Marginal case.
+ ((uint8_t)fc <= (UINT64_MAX % 10) + ASCII_0)
+ )
+ ) {
+ s->number64 *= 10;
+ s->number64 += digit_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER64_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ number_digit = [0-9] $_number_digit;
+
+ action _number_init {
+ s->number64 = 0;
+ }
+ action _number_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+
+ # General integer number that cover all necessary integer ranges.
+ number = number_digit+ >_number_init;
+
+ action _float_init {
+ s->decimal_counter = 0;
+ }
+ action _decimal_init {
+ s->number64_tmp = s->number64;
+ }
+ action _decimal_digit {
+ s->decimal_counter++;
+ }
+
+ action _float_exit {
+ if (s->decimal_counter == 0 && s->number64 < UINT32_MAX) {
+ s->number64 *= pow(10, s->decimals);
+ } else if (s->decimal_counter <= s->decimals &&
+ s->number64_tmp < UINT32_MAX) {
+ s->number64 *= pow(10, s->decimals - s->decimal_counter);
+ s->number64 += s->number64_tmp * pow(10, s->decimals);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EFLOAT_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ # Next float can't be used directly (doesn't contain decimals init)!
+ float = (number . ('.' . number? >_decimal_init $_decimal_digit)?)
+ >_float_init %_float_exit;
+
+ action _float2_init {
+ s->decimals = 2;
+ }
+ action _float3_init {
+ s->decimals = 3;
+ }
+
+ # Float number (in hundredths)with 2 possible decimal digits.
+ float2 = float >_float2_init;
+ # Float number (in thousandths) with 3 possible decimal digits.
+ float3 = float >_float3_init;
+
+ action _num8_write {
+ if (s->number64 <= UINT8_MAX) {
+ *rdata_tail = (uint8_t)(s->number64);
+ rdata_tail += 1;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER8_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _num16_write {
+ if (s->number64 <= UINT16_MAX) {
+ *((uint16_t *)rdata_tail) = htons((uint16_t)(s->number64));
+ rdata_tail += 2;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _num32_write {
+ if (s->number64 <= UINT32_MAX) {
+ *((uint32_t *)rdata_tail) = htonl((uint32_t)(s->number64));
+ rdata_tail += 4;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ action _type_number_exit {
+ if (s->number64 <= UINT16_MAX) {
+ s->r_type = (uint16_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ action _length_number_exit {
+ if (s->number64 <= UINT16_MAX) {
+ s->r_data_length = (uint16_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ num8 = number %_num8_write $!_number_error;
+ num16 = number %_num16_write $!_number_error;
+ num32 = number %_num32_write $!_number_error;
+
+ type_number = number %_type_number_exit $!_number_error;
+ length_number = number %_length_number_exit $!_number_error;
+ # END
+
+ # BEGIN - Time processing
+ action _time_unit_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIME_UNIT);
+ fhold; fgoto err_line;
+ }
+
+ time_unit =
+ ( 's'i
+ | 'm'i ${ if (s->number64 <= (UINT32_MAX / 60)) {
+ s->number64 *= 60;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ | 'h'i ${ if (s->number64 <= (UINT32_MAX / 3600)) {
+ s->number64 *= 3600;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ | 'd'i ${ if (s->number64 <= (UINT32_MAX / 86400)) {
+ s->number64 *= 86400;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ | 'w'i ${ if (s->number64 <= (UINT32_MAX / 604800)) {
+ s->number64 *= 604800;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ ) $!_time_unit_error;
+
+
+ action _time_block_init {
+ s->number64_tmp = s->number64;
+ }
+ action _time_block_exit {
+ if (s->number64 + s->number64_tmp < UINT32_MAX) {
+ s->number64 += s->number64_tmp;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ time_block = (number . time_unit) >_time_block_init %_time_block_exit;
+
+ # Time is either a number or a sequence of time blocks (1w1h1m)
+ time = (number . (time_unit . (time_block)*)?) $!_number_error;
+
+ time32 = time %_num32_write;
+ # END
+
+ # BEGIN - Timestamp processing
+ action _timestamp_init {
+ s->buffer_length = 0;
+ }
+ action _timestamp {
+ if (s->buffer_length < MAX_RDATA_LENGTH) {
+ s->buffer[s->buffer_length++] = fc;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _timestamp_exit {
+ s->buffer[s->buffer_length] = 0;
+
+ if (s->buffer_length == 14) { // Date; 14 = len("YYYYMMDDHHmmSS").
+ ret = date_to_timestamp(s->buffer, &timestamp);
+
+ if (ret == KNOT_EOK) {
+ *((uint32_t *)rdata_tail) = htonl(timestamp);
+ rdata_tail += 4;
+ } else {
+ SCANNER_WARNING(ret);
+ fhold; fgoto err_line;
+ }
+ } else if (s->buffer_length <= 10) { // Timestamp format.
+ char *end;
+
+ s->number64 = strtoull((char *)(s->buffer), &end, 10);
+
+ if (end == (char *)(s->buffer) || *end != '\0') {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIMESTAMP);
+ fhold; fgoto err_line;
+ }
+
+ if (s->number64 <= UINT32_MAX) {
+ *((uint32_t *)rdata_tail) = htonl((uint32_t)s->number64);
+ rdata_tail += 4;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIMESTAMP_LENGTH);
+ fhold; fgoto err_line;
+ }
+ }
+ action _timestamp_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_TIMESTAMP_CHAR);
+ fhold; fgoto err_line;
+ }
+
+ timestamp = digit+ >_timestamp_init $_timestamp
+ %_timestamp_exit $!_timestamp_error;
+ # END
+
+ # BEGIN - Text processing
+ action _text_char {
+ if (rdata_tail <= rdata_stop) {
+ *(rdata_tail++) = fc;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ETEXT_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _text_char_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_TEXT_CHAR);
+ fhold; fgoto err_line;
+ }
+ action _text_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_TEXT);
+ fhold; fgoto err_line;
+ }
+
+ action _text_dec_init {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = 0;
+ s->item_length++;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ETEXT_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _text_dec {
+ if ((*rdata_tail < (UINT8_MAX / 10)) || // Dominant fast check.
+ ((*rdata_tail == (UINT8_MAX / 10)) && // Marginal case.
+ (fc <= (UINT8_MAX % 10) + ASCII_0)
+ )
+ ) {
+ *rdata_tail *= 10;
+ *rdata_tail += digit_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER8_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _text_dec_exit {
+ rdata_tail++;
+ }
+ action _text_dec_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+
+ text_char =
+ ( (33..126 - [\\;\"]) $_text_char # One printable char.
+ | ('\\' . ^digit) @_text_char # One "\x" char.
+ | ('\\' %_text_dec_init # Initial "\" char.
+ . digit {3} $_text_dec %_text_dec_exit # "DDD" rest.
+ $!_text_dec_error
+ )
+ ) $!_text_char_error;
+
+ quoted_text_char =
+ ( text_char
+ | ([ \t;] | [\n] when { s->multiline }) $_text_char
+ ) $!_text_char_error;
+
+ # Text string machine instantiation (for smaller code).
+ text_ := (('\"' . quoted_text_char* . '\"') | text_char+)
+ $!_text_error %_ret . all_wchar;
+ text = ^all_wchar ${ fhold; fcall text_; };
+
+ # Text string with forward 1-byte length.
+ text_string = text >_item_length_init %_item_length_exit;
+
+ # Text string array as one rdata item.
+ text_array = (text_string . (sep . text_string)* . sep?);
+ # END
+
+ # BEGIN - TTL directive processing
+ action _default_ttl_exit {
+ if (s->number64 <= UINT32_MAX) {
+ s->default_ttl = (uint32_t)(s->number64);
+ } else {
+ SCANNER_ERROR(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _default_ttl_error {
+ SCANNER_ERROR(ZSCANNER_EBAD_TTL);
+ fhold; fgoto err_line;
+ }
+
+ default_ttl_ := (sep . time . rest) $!_default_ttl_error
+ %_default_ttl_exit %_ret . newline;
+ default_ttl = all_wchar ${ fhold; fcall default_ttl_; };
+ # END
+
+ # BEGIN - ORIGIN directive processing
+ action _zone_origin_init {
+ s->dname = s->zone_origin;
+ }
+ action _zone_origin_exit {
+ s->zone_origin_length = s->dname_tmp_length;
+ }
+ action _zone_origin_error {
+ SCANNER_ERROR(ZSCANNER_EBAD_ORIGIN);
+ fhold; fgoto err_line;
+ }
+
+ zone_origin_ := (sep . absolute_dname >_zone_origin_init . rest)
+ $!_zone_origin_error %_zone_origin_exit %_ret . newline;
+ zone_origin = all_wchar ${ fhold; fcall zone_origin_; };
+ # END
+
+ # BEGIN - INCLUDE directive processing
+ action _incl_filename_init {
+ rdata_tail = s->r_data;
+ }
+ action _incl_filename_exit {
+ *rdata_tail = 0; // Ending filename string.
+ strncpy((char*)(s->include_filename), (char*)(s->r_data),
+ sizeof(s->include_filename));
+
+ // Check for correct string copy.
+ if (strlen(s->include_filename) !=
+ (size_t)(rdata_tail - s->r_data)) {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_FILENAME);
+ fhold; fgoto err_line;
+ }
+
+ // For detection whether origin is not present.
+ s->dname = NULL;
+ }
+ action _incl_filename_error {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_FILENAME);
+ fhold; fgoto err_line;
+ }
+
+ action _incl_origin_init {
+ s->dname = s->r_data;
+ }
+ action _incl_origin_exit {
+ s->r_data_length = s->dname_tmp_length;
+ }
+ action _incl_origin_error {
+ SCANNER_ERROR(ZSCANNER_EBAD_INCLUDE_ORIGIN);
+ fhold; fgoto err_line;
+ }
+
+ action _include_exit {
+ char text_origin[MAX_DNAME_LENGTH];
+
+ // Origin conversion from wire to text form.
+ if (s->dname == NULL) { // Use current origin.
+ wire_dname_to_str(s->zone_origin,
+ s->zone_origin_length,
+ text_origin);
+ } else { // Use specified origin.
+ wire_dname_to_str(s->r_data,
+ s->r_data_length,
+ text_origin);
+ }
+
+ if (s->include_filename[0] != '/') { // Relative file path.
+ // Get absolute path of the current zone file.
+ if (realpath(s->file_name, (char*)(s->buffer)) != NULL) {
+ char *full_current_zone_file_name =
+ strdup((char*)(s->buffer));
+
+ // Creating full include file name.
+ snprintf((char*)(s->buffer), sizeof(s->buffer),
+ "%s/%s",
+ dirname(full_current_zone_file_name),
+ s->include_filename);
+
+ free(full_current_zone_file_name);
+ } else {
+ SCANNER_ERROR(ZSCANNER_EUNPROCESSED_INCLUDE);
+ fhold; fgoto err_line;
+ }
+ } else {
+ strncpy((char*)(s->buffer), (char*)(s->include_filename),
+ sizeof(s->buffer));
+ }
+
+ // Create new file loader for included zone file.
+ file_loader_t *fl = file_loader_create((char*)(s->buffer),
+ text_origin,
+ DEFAULT_CLASS,
+ DEFAULT_TTL,
+ s->process_record,
+ s->process_error,
+ s->data);
+ if (fl != NULL) {
+ // Process included zone file.
+ ret = file_loader_process(fl);
+ file_loader_free(fl);
+
+ if (ret != 0) {
+ SCANNER_ERROR(ZSCANNER_EUNPROCESSED_INCLUDE);
+ fhold; fgoto err_line;
+ }
+ } else {
+ SCANNER_ERROR(ZSCANNER_EUNOPENED_INCLUDE);
+ fhold; fgoto err_line;
+ }
+ }
+
+ include_file_ :=
+ (sep . text >_incl_filename_init %_incl_filename_exit
+ $!_incl_filename_error .
+ (sep . absolute_dname >_incl_origin_init %_incl_origin_exit
+ $!_incl_origin_error
+ )? . rest
+ ) %_include_exit %_ret newline;
+ include_file = all_wchar ${ fhold; fcall include_file_; };
+ # END
+
+ # BEGIN - Directive switch
+ # Each error/warning in directive should stop processing.
+ # Some internal errors cause warning only. This causes stop processing.
+ action _directive_init {
+ s->stop = true;
+ }
+ # Remove stop processing flag.
+ action _directive_exit {
+ s->stop = false;
+ }
+ action _directive_error {
+ SCANNER_ERROR(ZSCANNER_EBAD_DIRECTIVE);
+ fhold; fgoto err_line;
+ }
+
+ directive = '$' . ( ("TTL"i . default_ttl)
+ | ("ORIGIN"i . zone_origin)
+ | ("INCLUDE"i . include_file)
+ ) >_directive_init %_directive_exit $!_directive_error;
+ # END
+
+ # BEGIN - RRecord class and ttl processing
+ action _default_r_class_exit {
+ s->r_class = s->default_class;
+ }
+
+ action _default_r_ttl_exit {
+ s->r_ttl = s->default_ttl;
+ }
+
+ action _r_class_in_exit {
+ s->r_class = KNOT_CLASS_IN;
+ }
+
+ action _r_ttl_exit {
+ if (s->number64 <= UINT32_MAX) {
+ s->r_ttl = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER32_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ r_class = "IN"i %_r_class_in_exit;
+
+ r_ttl = time %_r_ttl_exit;
+ # END
+
+ # BEGIN - IPv4 and IPv6 address processing
+ action _addr_init {
+ s->buffer_length = 0;
+ }
+ action _addr {
+ if (s->buffer_length < MAX_RDATA_LENGTH) {
+ s->buffer[s->buffer_length++] = fc;
+ }
+ else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _addr_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_ADDRESS_CHAR);
+ fhold; fgoto err_line;
+ }
+
+ action _ipv4_addr_exit {
+ s->buffer[s->buffer_length] = 0;
+
+ if (inet_pton(AF_INET, (char *)s->buffer, &addr4) <= 0) {
+ SCANNER_WARNING(ZSCANNER_EBAD_IPV4);
+ fhold; fgoto err_line;
+ }
+ }
+ action _ipv4_addr_write {
+ memcpy(rdata_tail, &(addr4.s_addr), INET4_ADDR_LENGTH);
+ rdata_tail += INET4_ADDR_LENGTH;
+ }
+
+ action _ipv6_addr_exit {
+ s->buffer[s->buffer_length] = 0;
+
+ if (inet_pton(AF_INET6, (char *)s->buffer, &addr6) <= 0) {
+ SCANNER_WARNING(ZSCANNER_EBAD_IPV6);
+ fhold; fgoto err_line;
+ }
+ }
+ action _ipv6_addr_write {
+ memcpy(rdata_tail, &(addr6.s6_addr), INET6_ADDR_LENGTH);
+ rdata_tail += INET6_ADDR_LENGTH;
+ }
+
+ # Address parsers only.
+ ipv4_addr = (digit | '.')+ >_addr_init $_addr %_ipv4_addr_exit
+ $!_addr_error;
+ ipv6_addr = (xdigit | [.:])+ >_addr_init $_addr %_ipv6_addr_exit
+ $!_addr_error;
+
+ # Write parsed address to r_data.
+ ipv4_addr_write = ipv4_addr %_ipv4_addr_write;
+ ipv6_addr_write = ipv6_addr %_ipv6_addr_write;
+ # END
+
+ # BEGIN - apl record processing
+ action _apl_init {
+ memset(&(s->apl), 0, sizeof(s->apl));
+ }
+ action _apl_excl_flag {
+ s->apl.excl_flag = 128; // dec 128 = bin 10000000.
+ }
+ action _apl_addr_1 {
+ s->apl.addr_family = 1;
+ }
+ action _apl_addr_2 {
+ s->apl.addr_family = 2;
+ }
+ action _apl_prefix_length {
+ if ((s->apl.addr_family == 1 && s->number64 <= 32) ||
+ (s->apl.addr_family == 2 && s->number64 <= 128)) {
+ s->apl.prefix_length = (uint8_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_APL);
+ fhold; fgoto err_line;
+ }
+ }
+ action _apl_exit {
+ // Write address family.
+ *((uint16_t *)rdata_tail) = htons(s->apl.addr_family);
+ rdata_tail += 2;
+ // Write prefix length in bites.
+ *(rdata_tail) = s->apl.prefix_length;
+ rdata_tail += 1;
+ // Copy address to buffer.
+ uint8_t len;
+ switch (s->apl.addr_family) {
+ case 1:
+ len = INET4_ADDR_LENGTH;
+ memcpy(s->buffer, &(addr4.s_addr), len);
+ break;
+ case 2:
+ len = INET6_ADDR_LENGTH;
+ memcpy(s->buffer, &(addr6.s6_addr), len);
+ break;
+ default:
+ SCANNER_WARNING(ZSCANNER_EBAD_APL);
+ fhold; fgoto err_line;
+ }
+ // Find prefix without trailing zeroes.
+ while (len > 0) {
+ if ((s->buffer[len - 1] & 255) != 0) {
+ break;
+ }
+ len--;
+ }
+ // Write negation flag + prefix length in bytes.
+ *(rdata_tail) = len + s->apl.excl_flag;
+ rdata_tail += 1;
+ // Write address prefix non-null data.
+ memcpy(rdata_tail, s->buffer, len);
+ rdata_tail += len;
+ }
+ action _apl_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_APL);
+ fhold; fgoto err_line;
+ }
+
+ apl = ('!'? $_apl_excl_flag .
+ ( ('1' $_apl_addr_1 . ':' . ipv4_addr . '/' . number
+ %_apl_prefix_length)
+ | ('2' $_apl_addr_2 . ':' . ipv6_addr . '/' . number
+ %_apl_prefix_length)
+ )
+ ) >_apl_init %_apl_exit $!_apl_error;
+
+ # Array of APL records (can be empty).
+ apl_array = apl? . (sep . apl)* . sep?;
+ # END
+
+ # BEGIN - Hexadecimal string array processing
+ action _first_hex_char {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = first_hex_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _second_hex_char {
+ *rdata_tail += second_hex_to_num[(uint8_t)fc];
+ rdata_tail++;
+ }
+ action _hex_char_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_CHAR);
+ fhold; fgoto err_line;
+ }
+
+ hex_char = (xdigit $_first_hex_char . xdigit $_second_hex_char);
+
+ # Hex array with possibility of inside white spaces and multiline.
+ hex_array = (hex_char+ . sep?)+ $!_hex_char_error;
+
+ # Continuous hex array (or "-") with forward length processing.
+ salt = (hex_char+ | '-') >_item_length_init %_item_length_exit
+ $!_hex_char_error;
+
+ action _type_data_exit {
+ if ((rdata_tail - s->r_data) != s->r_data_length) {
+ SCANNER_WARNING(ZSCANNER_EBAD_RDATA_LENGTH);
+ fhold; fgoto err_line;
+ }
+
+ ret = find_rdata_blocks(s);
+ if (ret != KNOT_EOK) {
+ SCANNER_WARNING(ret);
+ fhold; fgoto err_line;
+ }
+ }
+
+ action _type_data_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_RDATA);
+ fhold; fgoto err_line;
+ }
+
+ # Hex array with control to forward length statement.
+ type_data = hex_array %_type_data_exit $!_type_data_error;
+ # END
+
+ # BEGIN - Base64 processing (RFC 4648)
+ action _first_base64_char {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = first_base64_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _second_base64_char {
+ *(rdata_tail++) += second_left_base64_to_num[(uint8_t)fc];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = second_right_base64_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _third_base64_char {
+ *(rdata_tail++) += third_left_base64_to_num[(uint8_t)fc];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = third_right_base64_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _fourth_base64_char {
+ *(rdata_tail++) += fourth_base64_to_num[(uint8_t)fc];
+ }
+
+ action _base64_char_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_BASE64_CHAR);
+ fhold; fgoto err_line;
+ }
+
+ base64_char = alnum | [+/];
+ base64_padd = '=';
+ base64_quartet =
+ ( base64_char $_first_base64_char . # A
+ base64_char $_second_base64_char . # AB
+ ( ( base64_char $_third_base64_char . # ABC
+ ( base64_char $_fourth_base64_char # ABCD
+ | base64_padd{1} # ABC=
+ )
+ )
+ | base64_padd{2} # AB==
+ )
+ );
+
+ # Base64 array with possibility of inside white spaces and multiline.
+ base64_ := (base64_quartet+ . sep?)+ $!_base64_char_error
+ %_ret . end_wchar;
+ base64 = base64_char ${ fhold; fcall base64_; };
+ # END
+
+ # BEGIN - Base32hex processing (RFC 4648)
+ action _first_base32hex_char {
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = first_base32hex_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _second_base32hex_char {
+ *(rdata_tail++) += second_left_base32hex_to_num[(uint8_t)fc];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = second_right_base32hex_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _third_base32hex_char {
+ *rdata_tail += third_base32hex_to_num[(uint8_t)fc];
+ }
+ action _fourth_base32hex_char {
+ *(rdata_tail++) += fourth_left_base32hex_to_num[(uint8_t)fc];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = fourth_right_base32hex_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _fifth_base32hex_char {
+ *(rdata_tail++) += fifth_left_base32hex_to_num[(uint8_t)fc];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = fifth_right_base32hex_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _sixth_base32hex_char {
+ *rdata_tail += sixth_base32hex_to_num[(uint8_t)fc];
+ }
+ action _seventh_base32hex_char {
+ *(rdata_tail++) += seventh_left_base32hex_to_num[(uint8_t)fc];
+
+ if (rdata_tail <= rdata_stop) {
+ *rdata_tail = seventh_right_base32hex_to_num[(uint8_t)fc];
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ action _eighth_base32hex_char {
+ *(rdata_tail++) += eighth_base32hex_to_num[(uint8_t)fc];
+ }
+
+ action _base32hex_char_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_BASE32HEX_CHAR);
+ fhold; fgoto err_line;
+ }
+
+ base32hex_char = [0-9a-vA-V];
+ base32hex_padd = '=';
+ base32hex_octet =
+ ( base32hex_char $_first_base32hex_char . # A
+ base32hex_char $_second_base32hex_char . # AB
+ ( ( base32hex_char $_third_base32hex_char . # ABC
+ base32hex_char $_fourth_base32hex_char . # ABCD
+ ( ( base32hex_char $_fifth_base32hex_char . # ABCDE
+ ( ( base32hex_char $_sixth_base32hex_char . # ABCDEF
+ base32hex_char $_seventh_base32hex_char . # ABCDEFG
+ ( base32hex_char $_eighth_base32hex_char # ABCDEFGH
+ | base32hex_padd{1} # ABCDEFG=
+ )
+ )
+ | base32hex_padd{3} # ABCDE===
+ )
+ )
+ | base32hex_padd{4} # ABCD====
+ )
+ )
+ | base32hex_padd{6} # AB======
+ )
+ );
+
+ # Continuous base32hex (with padding!) array with forward length processing.
+ hash = base32hex_octet+ >_item_length_init %_item_length_exit
+ $!_base32hex_char_error;
+ # END
+
+ # BEGIN - Simple number write functions.
+ action _write8_0 {
+ *(rdata_tail++) = 0;
+ }
+ action _write8_1 {
+ *(rdata_tail++) = 1;
+ }
+ action _write8_2 {
+ *(rdata_tail++) = 2;
+ }
+ action _write8_3 {
+ *(rdata_tail++) = 3;
+ }
+ action _write8_5 {
+ *(rdata_tail++) = 5;
+ }
+ action _write8_6 {
+ *(rdata_tail++) = 6;
+ }
+ action _write8_7 {
+ *(rdata_tail++) = 7;
+ }
+ action _write8_8 {
+ *(rdata_tail++) = 8;
+ }
+ action _write8_10 {
+ *(rdata_tail++) = 10;
+ }
+ action _write8_12 {
+ *(rdata_tail++) = 12;
+ }
+ action _write8_13 {
+ *(rdata_tail++) = 13;
+ }
+ action _write8_14 {
+ *(rdata_tail++) = 14;
+ }
+ action _write8_252 {
+ *(rdata_tail++) = 252;
+ }
+ action _write8_253 {
+ *(rdata_tail++) = 253;
+ }
+ action _write8_254 {
+ *(rdata_tail++) = 254;
+ }
+
+ action _write16_1 {
+ *((uint16_t *)rdata_tail) = htons(1);
+ rdata_tail += 2;
+ }
+ action _write16_2 {
+ *((uint16_t *)rdata_tail) = htons(2);
+ rdata_tail += 2;
+ }
+ action _write16_3 {
+ *((uint16_t *)rdata_tail) = htons(3);
+ rdata_tail += 2;
+ }
+ action _write16_4 {
+ *((uint16_t *)rdata_tail) = htons(4);
+ rdata_tail += 2;
+ }
+ action _write16_5 {
+ *((uint16_t *)rdata_tail) = htons(5);
+ rdata_tail += 2;
+ }
+ action _write16_6 {
+ *((uint16_t *)rdata_tail) = htons(6);
+ rdata_tail += 2;
+ }
+ action _write16_7 {
+ *((uint16_t *)rdata_tail) = htons(7);
+ rdata_tail += 2;
+ }
+ action _write16_8 {
+ *((uint16_t *)rdata_tail) = htons(8);
+ rdata_tail += 2;
+ }
+ action _write16_253 {
+ *((uint16_t *)rdata_tail) = htons(253);
+ rdata_tail += 2;
+ }
+ action _write16_254 {
+ *((uint16_t *)rdata_tail) = htons(254);
+ rdata_tail += 2;
+ }
+ # END
+
+ # BEGIN - Gateway
+ action _gateway_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_GATEWAY);
+ fhold; fgoto err_line;
+ }
+ action _gateway_key_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_GATEWAY_KEY);
+ fhold; fgoto err_line;
+ }
+
+ gateway = (( ('0' $_write8_0 . sep . num8 . sep . '.')
+ | ('1' $_write8_1 . sep . num8 . sep . ipv4_addr_write)
+ | ('2' $_write8_2 . sep . num8 . sep . ipv6_addr_write)
+ | ('3' $_write8_3 . sep . num8 . sep . r_dname)
+ ) $!_gateway_error .
+ # If algorithm is 0 then key isn't present and vice versa.
+ ( ((sep . base64) when { s->number64 != 0 })
+ | ((sep?) when { s->number64 == 0 }) # remove blank space
+ ) $!_gateway_key_error
+ );
+ # END
+
+ # BEGIN - Type processing
+ action _type_error {
+ SCANNER_WARNING(ZSCANNER_EUNSUPPORTED_TYPE);
+ fhold; fgoto err_line;
+ }
+
+ type_num =
+ ( "A"i %{ type_num(KNOT_RRTYPE_A, &rdata_tail); }
+ | "NS"i %{ type_num(KNOT_RRTYPE_NS, &rdata_tail); }
+ | "CNAME"i %{ type_num(KNOT_RRTYPE_CNAME, &rdata_tail); }
+ | "SOA"i %{ type_num(KNOT_RRTYPE_SOA, &rdata_tail); }
+ | "PTR"i %{ type_num(KNOT_RRTYPE_PTR, &rdata_tail); }
+ | "HINFO"i %{ type_num(KNOT_RRTYPE_HINFO, &rdata_tail); }
+ | "MINFO"i %{ type_num(KNOT_RRTYPE_MINFO, &rdata_tail); }
+ | "MX"i %{ type_num(KNOT_RRTYPE_MX, &rdata_tail); }
+ | "TXT"i %{ type_num(KNOT_RRTYPE_TXT, &rdata_tail); }
+ | "RP"i %{ type_num(KNOT_RRTYPE_RP, &rdata_tail); }
+ | "AFSDB"i %{ type_num(KNOT_RRTYPE_AFSDB, &rdata_tail); }
+ | "RT"i %{ type_num(KNOT_RRTYPE_RT, &rdata_tail); }
+ | "KEY"i %{ type_num(KNOT_RRTYPE_KEY, &rdata_tail); }
+ | "AAAA"i %{ type_num(KNOT_RRTYPE_AAAA, &rdata_tail); }
+ | "LOC"i %{ type_num(KNOT_RRTYPE_LOC, &rdata_tail); }
+ | "SRV"i %{ type_num(KNOT_RRTYPE_SRV, &rdata_tail); }
+ | "NAPTR"i %{ type_num(KNOT_RRTYPE_NAPTR, &rdata_tail); }
+ | "KX"i %{ type_num(KNOT_RRTYPE_KX, &rdata_tail); }
+ | "CERT"i %{ type_num(KNOT_RRTYPE_CERT, &rdata_tail); }
+ | "DNAME"i %{ type_num(KNOT_RRTYPE_DNAME, &rdata_tail); }
+ | "APL"i %{ type_num(KNOT_RRTYPE_APL, &rdata_tail); }
+ | "DS"i %{ type_num(KNOT_RRTYPE_DS, &rdata_tail); }
+ | "SSHFP"i %{ type_num(KNOT_RRTYPE_SSHFP, &rdata_tail); }
+ | "IPSECKEY"i %{ type_num(KNOT_RRTYPE_IPSECKEY, &rdata_tail); }
+ | "RRSIG"i %{ type_num(KNOT_RRTYPE_RRSIG, &rdata_tail); }
+ | "NSEC"i %{ type_num(KNOT_RRTYPE_NSEC, &rdata_tail); }
+ | "DNSKEY"i %{ type_num(KNOT_RRTYPE_DNSKEY, &rdata_tail); }
+ | "DHCID"i %{ type_num(KNOT_RRTYPE_DHCID, &rdata_tail); }
+ | "NSEC3"i %{ type_num(KNOT_RRTYPE_NSEC3, &rdata_tail); }
+ | "NSEC3PARAM"i %{ type_num(KNOT_RRTYPE_NSEC3PARAM, &rdata_tail); }
+ | "TLSA"i %{ type_num(KNOT_RRTYPE_TLSA, &rdata_tail); }
+ | "SPF"i %{ type_num(KNOT_RRTYPE_SPF, &rdata_tail); }
+ | "NID"i %{ type_num(KNOT_RRTYPE_NID, &rdata_tail); }
+ | "L32"i %{ type_num(KNOT_RRTYPE_L32, &rdata_tail); }
+ | "L64"i %{ type_num(KNOT_RRTYPE_L64, &rdata_tail); }
+ | "LP"i %{ type_num(KNOT_RRTYPE_LP, &rdata_tail); }
+ | "EUI48"i %{ type_num(KNOT_RRTYPE_EUI48, &rdata_tail); }
+ | "EUI64"i %{ type_num(KNOT_RRTYPE_EUI64, &rdata_tail); }
+ | "TYPE"i . num16 # TYPE0-TYPE65535.
+ ) $!_type_error;
+ # END
+
+ # BEGIN - Bitmap processing
+ action _type_bitmap_exit {
+ if (s->number64 <= UINT16_MAX) {
+ window_add_bit(s->number64, s);
+ } else {
+ SCANNER_WARNING(ZSCANNER_ENUMBER16_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+
+ # TYPE0-TYPE65535.
+ type_bitmap = number %_type_bitmap_exit;
+
+ type_bit =
+ ( "A"i %{ window_add_bit(KNOT_RRTYPE_A, s); }
+ | "NS"i %{ window_add_bit(KNOT_RRTYPE_NS, s); }
+ | "CNAME"i %{ window_add_bit(KNOT_RRTYPE_CNAME, s); }
+ | "SOA"i %{ window_add_bit(KNOT_RRTYPE_SOA, s); }
+ | "PTR"i %{ window_add_bit(KNOT_RRTYPE_PTR, s); }
+ | "HINFO"i %{ window_add_bit(KNOT_RRTYPE_HINFO, s); }
+ | "MINFO"i %{ window_add_bit(KNOT_RRTYPE_MINFO, s); }
+ | "MX"i %{ window_add_bit(KNOT_RRTYPE_MX, s); }
+ | "TXT"i %{ window_add_bit(KNOT_RRTYPE_TXT, s); }
+ | "RP"i %{ window_add_bit(KNOT_RRTYPE_RP, s); }
+ | "AFSDB"i %{ window_add_bit(KNOT_RRTYPE_AFSDB, s); }
+ | "RT"i %{ window_add_bit(KNOT_RRTYPE_RT, s); }
+ | "KEY"i %{ window_add_bit(KNOT_RRTYPE_KEY, s); }
+ | "AAAA"i %{ window_add_bit(KNOT_RRTYPE_AAAA, s); }
+ | "LOC"i %{ window_add_bit(KNOT_RRTYPE_LOC, s); }
+ | "SRV"i %{ window_add_bit(KNOT_RRTYPE_SRV, s); }
+ | "NAPTR"i %{ window_add_bit(KNOT_RRTYPE_NAPTR, s); }
+ | "KX"i %{ window_add_bit(KNOT_RRTYPE_KX, s); }
+ | "CERT"i %{ window_add_bit(KNOT_RRTYPE_CERT, s); }
+ | "DNAME"i %{ window_add_bit(KNOT_RRTYPE_DNAME, s); }
+ | "APL"i %{ window_add_bit(KNOT_RRTYPE_APL, s); }
+ | "DS"i %{ window_add_bit(KNOT_RRTYPE_DS, s); }
+ | "SSHFP"i %{ window_add_bit(KNOT_RRTYPE_SSHFP, s); }
+ | "IPSECKEY"i %{ window_add_bit(KNOT_RRTYPE_IPSECKEY, s); }
+ | "RRSIG"i %{ window_add_bit(KNOT_RRTYPE_RRSIG, s); }
+ | "NSEC"i %{ window_add_bit(KNOT_RRTYPE_NSEC, s); }
+ | "DNSKEY"i %{ window_add_bit(KNOT_RRTYPE_DNSKEY, s); }
+ | "DHCID"i %{ window_add_bit(KNOT_RRTYPE_DHCID, s); }
+ | "NSEC3"i %{ window_add_bit(KNOT_RRTYPE_NSEC3, s); }
+ | "NSEC3PARAM"i %{ window_add_bit(KNOT_RRTYPE_NSEC3PARAM, s); }
+ | "TLSA"i %{ window_add_bit(KNOT_RRTYPE_TLSA, s); }
+ | "SPF"i %{ window_add_bit(KNOT_RRTYPE_SPF, s); }
+ | "NID"i %{ window_add_bit(KNOT_RRTYPE_NID, s); }
+ | "L32"i %{ window_add_bit(KNOT_RRTYPE_L32, s); }
+ | "L64"i %{ window_add_bit(KNOT_RRTYPE_L64, s); }
+ | "LP"i %{ window_add_bit(KNOT_RRTYPE_LP, s); }
+ | "EUI48"i %{ window_add_bit(KNOT_RRTYPE_EUI48, s); }
+ | "EUI64"i %{ window_add_bit(KNOT_RRTYPE_EUI64, s); }
+ | "TYPE"i . type_bitmap # TYPE0-TYPE65535.
+ );
+
+ action _bitmap_init {
+ memset(s->windows, 0, sizeof(s->windows));
+ s->last_window = -1;
+ }
+ action _bitmap_exit {
+ for (window = 0; window <= s->last_window; window++) {
+ if ((s->windows[window]).length > 0) {
+ if (rdata_tail + 2 + (s->windows[window]).length <= rdata_stop)
+ {
+ // Window number.
+ *rdata_tail = (uint8_t)window;
+ rdata_tail += 1;
+ // Bitmap length.
+ *rdata_tail = (s->windows[window]).length;
+ rdata_tail += 1;
+ // Copying bitmap.
+ memcpy(rdata_tail,
+ (s->windows[window]).bitmap,
+ (s->windows[window]).length);
+ rdata_tail += (s->windows[window]).length;
+ } else {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ }
+ }
+ }
+ action _bitmap_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_BITMAP);
+ fhold; fgoto err_line;
+ }
+
+ # Blank bitmap is allowed too.
+ bitmap_ := ((sep . type_bit)* . sep?) >_bitmap_init
+ %_bitmap_exit %_ret $!_bitmap_error . end_wchar;
+ bitmap = all_wchar ${ fhold; fcall bitmap_; };
+ # END
+
+ # BEGIN - Location processing
+ action _d1_exit {
+ if (s->number64 <= 90) {
+ s->loc.d1 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _d2_exit {
+ if (s->number64 <= 180) {
+ s->loc.d2 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _m1_exit {
+ if (s->number64 <= 59) {
+ s->loc.m1 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _m2_exit {
+ if (s->number64 <= 59) {
+ s->loc.m2 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _s1_exit {
+ if (s->number64 <= 59999) {
+ s->loc.s1 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _s2_exit {
+ if (s->number64 <= 59999) {
+ s->loc.s2 = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _alt_exit {
+ if ((s->loc.alt_sign == 1 && s->number64 <= 4284967295) ||
+ (s->loc.alt_sign == -1 && s->number64 <= 10000000))
+ {
+ s->loc.alt = (uint32_t)(s->number64);
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _siz_exit {
+ if (s->number64 <= 9000000000ULL) {
+ s->loc.siz = s->number64;
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _hp_exit {
+ if (s->number64 <= 9000000000ULL) {
+ s->loc.hp = s->number64;
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _vp_exit {
+ if (s->number64 <= 9000000000ULL) {
+ s->loc.vp = s->number64;
+ } else {
+ SCANNER_WARNING(ZSCANNER_EBAD_NUMBER);
+ fhold; fgoto err_line;
+ }
+ }
+ action _lat_sign {
+ s->loc.lat_sign = -1;
+ }
+ action _long_sign {
+ s->loc.long_sign = -1;
+ }
+ action _alt_sign {
+ s->loc.alt_sign = -1;
+ }
+
+ d1 = number %_d1_exit;
+ d2 = number %_d2_exit;
+ m1 = number %_m1_exit;
+ m2 = number %_m2_exit;
+ s1 = float3 %_s1_exit;
+ s2 = float3 %_s2_exit;
+ siz = float2 %_siz_exit;
+ hp = float2 %_hp_exit;
+ vp = float2 %_vp_exit;
+ alt = ('-' %_alt_sign)? . float2 %_alt_exit;
+ lat_sign = 'N' | 'S' %_lat_sign;
+ long_sign = 'E' | 'W' %_long_sign;
+
+ action _loc_init {
+ memset(&(s->loc), 0, sizeof(s->loc));
+ // Defaults.
+ s->loc.siz = 100;
+ s->loc.vp = 1000;
+ s->loc.hp = 1000000;
+ s->loc.lat_sign = 1;
+ s->loc.long_sign = 1;
+ s->loc.alt_sign = 1;
+ }
+ action _loc_exit {
+ // Write version.
+ *(rdata_tail) = 0;
+ rdata_tail += 1;
+ // Write size.
+ *(rdata_tail) = loc64to8(s->loc.siz);
+ rdata_tail += 1;
+ // Write horizontal precision.
+ *(rdata_tail) = loc64to8(s->loc.hp);
+ rdata_tail += 1;
+ // Write vertical precision.
+ *(rdata_tail) = loc64to8(s->loc.vp);
+ rdata_tail += 1;
+ // Write latitude.
+ *((uint32_t *)rdata_tail) = htonl(LOC_LAT_ZERO + s->loc.lat_sign *
+ (3600000 * s->loc.d1 + 60000 * s->loc.m1 + s->loc.s1));
+ rdata_tail += 4;
+ // Write longitude.
+ *((uint32_t *)rdata_tail) = htonl(LOC_LONG_ZERO + s->loc.long_sign *
+ (3600000 * s->loc.d2 + 60000 * s->loc.m2 + s->loc.s2));
+ rdata_tail += 4;
+ // Write altitude.
+ *((uint32_t *)rdata_tail) = htonl(LOC_ALT_ZERO + s->loc.alt_sign *
+ (s->loc.alt));
+ rdata_tail += 4;
+ }
+ action _loc_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_LOC_DATA);
+ fhold; fgoto err_line;
+ }
+
+ loc = (d1 . sep . (m1 . sep . (s1 . sep)?)? . lat_sign . sep .
+ d2 . sep . (m2 . sep . (s2 . sep)?)? . long_sign . sep .
+ alt 'm'? . (sep . siz 'm'? . (sep . hp 'm'? . (sep . vp 'm'?)?)?)? .
+ sep?
+ ) >_loc_init %_loc_exit $!_loc_error;
+ # END
+
+ # BEGIN - Hexadecimal rdata processing
+ action _hex_r_data_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_HEX_RDATA);
+ fhold; fgoto err_line;
+ }
+
+ nonempty_hex_r_data :=
+ (sep . length_number . sep . type_data)
+ $!_hex_r_data_error %_ret . end_wchar;
+
+ hex_r_data :=
+ (sep .
+ ( ('0' %_ret . all_wchar)
+ | (length_number . sep . type_data %_ret . end_wchar)
+ )
+ ) $!_hex_r_data_error;
+ # END
+
+ # BEGIN - EUI processing
+ action _eui_init {
+ s->item_length = 0;
+ }
+ action _eui_count {
+ s->item_length++;
+ }
+ action _eui48_exit {
+ if (s->item_length != 6) {
+ SCANNER_WARNING(ZSCANNER_EBAD_EUI_LENGTH);
+ fhold; fgoto err_line;
+ }
+ }
+ action _eui64_exit {
+ if (s->item_length != 8) {
+ SCANNER_WARNING(ZSCANNER_EBAD_EUI_LENGTH);
+ fhold; fgoto err_line;
+ }
+ }
+ action _eui_sep_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_CHAR_DASH);
+ fhold; fgoto err_line;
+ }
+
+ eui48 = (hex_char %_eui_count .
+ ('-' >!_eui_sep_error . hex_char %_eui_count)+
+ ) $!_hex_char_error >_eui_init %_eui48_exit;
+
+ eui64 = (hex_char %_eui_count .
+ ('-' >!_eui_sep_error . hex_char %_eui_count)+
+ ) $!_hex_char_error >_eui_init %_eui64_exit;
+ # END
+
+ # BEGIN - ILNP processing
+ action _l64_init {
+ s->item_length = 0;
+ }
+ action _l64_count {
+ s->item_length++;
+ }
+ action _l64_exit {
+ if (s->item_length != 4) {
+ SCANNER_WARNING(ZSCANNER_EBAD_L64_LENGTH);
+ fhold; fgoto err_line;
+ }
+ }
+ action _l64_sep_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_CHAR_COLON);
+ fhold; fgoto err_line;
+ }
+
+ l64_label = (hex_char . hex_char) $!_hex_char_error %_l64_count;
+ l64 = (l64_label . (':' >!_l64_sep_error . l64_label)+
+ ) $!_hex_char_error >_l64_init %_l64_exit;
+
+ l32 = ipv4_addr %_ipv4_addr_write;
+ # END
+
+ # BEGIN - Mnemomic names processing
+ action _dns_alg_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_ALGORITHM);
+ fhold; fgoto err_line;
+ }
+ action _cert_type_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_CERT_TYPE);
+ fhold; fgoto err_line;
+ }
+
+ dns_alg_ :=
+ ( number %_num8_write
+ | "RSAMD5"i %_write8_1
+ | "DH"i %_write8_2
+ | "DSA"i %_write8_3
+ | "RSASHA1"i %_write8_5
+ | "DSA-NSEC3-SHA1"i %_write8_6
+ | "RSASHA1-NSEC3-SHA1"i %_write8_7
+ | "RSASHA256"i %_write8_8
+ | "RSASHA512"i %_write8_10
+ | "ECC-GOST"i %_write8_12
+ | "ECDSAP256SHA256"i %_write8_13
+ | "ECDSAP384SHA384"i %_write8_14
+ | "INDIRECT"i %_write8_252
+ | "PRIVATEDNS"i %_write8_253
+ | "PRIVATEOID"i %_write8_254
+ ) $!_dns_alg_error %_ret . all_wchar;
+ dns_alg = alnum ${ fhold; fcall dns_alg_; };
+
+ cert_type_ :=
+ ( number %_num16_write
+ | "PKIX"i %_write16_1
+ | "SPKI"i %_write16_2
+ | "PGP"i %_write16_3
+ | "IPKIX"i %_write16_4
+ | "ISPKI"i %_write16_5
+ | "IPGP"i %_write16_6
+ | "ACPKIX"i %_write16_7
+ | "IACPKIX"i %_write16_8
+ | "URI"i %_write16_253
+ | "OID"i %_write16_254
+ ) $!_cert_type_error %_ret . all_wchar;
+ cert_type = alnum ${ fhold; fcall cert_type_; };
+ # END
+
+ # BEGIN - Rdata processing
+ action _r_data_init {
+ s->r_data_blocks[0] = 0;
+ s->r_data_blocks_count = 0;
+ rdata_tail = s->r_data;
+ }
+ action _r_data_error {
+ SCANNER_WARNING(ZSCANNER_EBAD_RDATA);
+ fhold; fgoto err_line;
+ }
+
+ r_data_a :=
+ (ipv4_addr_write)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_ns :=
+ (r_dname)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_soa :=
+ (r_dname . blk_sep . sep . r_dname . blk_sep . sep . num32 .
+ sep . time32 . sep . time32 . sep . time32 . sep . time32)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_hinfo :=
+ (text_string . sep . text_string)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_minfo :=
+ (r_dname . blk_sep . sep . r_dname)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_mx :=
+ (num16 . blk_sep . sep . r_dname)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_txt :=
+ (text_array)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_aaaa :=
+ (ipv6_addr_write)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_loc :=
+ (loc)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_srv :=
+ (num16 . sep . num16 . sep . num16 . blk_sep . sep . r_dname)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_naptr :=
+ (num16 . sep . num16 . sep . text_string . sep . text_string .
+ sep . text_string . blk_sep . sep . r_dname)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_cert :=
+ (cert_type . sep . num16 . sep . dns_alg . sep . base64)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_apl :=
+ (apl_array)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_ds :=
+ (num16 . sep . dns_alg . sep . num8 . sep . hex_array)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_sshfp :=
+ (num8 . sep . num8 . sep . hex_array)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_ipseckey :=
+ (num8 . sep . gateway)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_rrsig :=
+ (type_num . sep . dns_alg . sep . num8 . sep . num32 . sep .
+ timestamp . sep . timestamp . sep . num16 . blk_sep . sep .
+ r_dname . blk_sep . sep . base64)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_nsec :=
+ (r_dname . blk_sep . bitmap)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_dnskey :=
+ (num16 . sep . num8 . sep . dns_alg . sep . base64)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_dhcid :=
+ (base64)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_nsec3 :=
+ (num8 . sep . num8 . sep . num16 . sep . salt . sep .
+ hash . bitmap)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_nsec3param :=
+ (num8 . sep . num8 . sep . num16 . sep . salt)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_tlsa :=
+ (num8 . sep . num8 . sep . num8 . sep . hex_array)
+ $!_r_data_error %_ret . end_wchar;
+
+ r_data_l32 :=
+ (num16 . sep . l32)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_l64 :=
+ (num16 . sep . l64)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_eui48 :=
+ (eui48)
+ $!_r_data_error %_ret . all_wchar;
+
+ r_data_eui64 :=
+ (eui64)
+ $!_r_data_error %_ret . all_wchar;
+
+ action _text_r_data {
+ fhold;
+ switch (s->r_type) {
+ case KNOT_RRTYPE_A:
+ fcall r_data_a;
+ case KNOT_RRTYPE_NS:
+ case KNOT_RRTYPE_CNAME:
+ case KNOT_RRTYPE_PTR:
+ case KNOT_RRTYPE_DNAME:
+ fcall r_data_ns;
+ case KNOT_RRTYPE_SOA:
+ fcall r_data_soa;
+ case KNOT_RRTYPE_HINFO:
+ fcall r_data_hinfo;
+ case KNOT_RRTYPE_MINFO:
+ case KNOT_RRTYPE_RP:
+ fcall r_data_minfo;
+ case KNOT_RRTYPE_MX:
+ case KNOT_RRTYPE_AFSDB:
+ case KNOT_RRTYPE_RT:
+ case KNOT_RRTYPE_KX:
+ case KNOT_RRTYPE_LP:
+ fcall r_data_mx;
+ case KNOT_RRTYPE_TXT:
+ case KNOT_RRTYPE_SPF:
+ fcall r_data_txt;
+ case KNOT_RRTYPE_AAAA:
+ fcall r_data_aaaa;
+ case KNOT_RRTYPE_LOC:
+ fcall r_data_loc;
+ case KNOT_RRTYPE_SRV:
+ fcall r_data_srv;
+ case KNOT_RRTYPE_NAPTR:
+ fcall r_data_naptr;
+ case KNOT_RRTYPE_CERT:
+ fcall r_data_cert;
+ case KNOT_RRTYPE_APL:
+ fcall r_data_apl;
+ case KNOT_RRTYPE_DS:
+ fcall r_data_ds;
+ case KNOT_RRTYPE_SSHFP:
+ fcall r_data_sshfp;
+ case KNOT_RRTYPE_IPSECKEY:
+ fcall r_data_ipseckey;
+ case KNOT_RRTYPE_RRSIG:
+ fcall r_data_rrsig;
+ case KNOT_RRTYPE_NSEC:
+ fcall r_data_nsec;
+ case KNOT_RRTYPE_KEY:
+ case KNOT_RRTYPE_DNSKEY:
+ fcall r_data_dnskey;
+ case KNOT_RRTYPE_DHCID:
+ fcall r_data_dhcid;
+ case KNOT_RRTYPE_NSEC3:
+ fcall r_data_nsec3;
+ case KNOT_RRTYPE_NSEC3PARAM:
+ fcall r_data_nsec3param;
+ case KNOT_RRTYPE_TLSA:
+ fcall r_data_tlsa;
+ case KNOT_RRTYPE_NID:
+ case KNOT_RRTYPE_L64:
+ fcall r_data_l64;
+ case KNOT_RRTYPE_L32:
+ fcall r_data_l32;
+ case KNOT_RRTYPE_EUI48:
+ fcall r_data_eui48;
+ case KNOT_RRTYPE_EUI64:
+ fcall r_data_eui64;
+ default:
+ SCANNER_WARNING(ZSCANNER_ECANNOT_TEXT_DATA);
+ fgoto err_line;
+ }
+ }
+ action _hex_r_data {
+ switch (s->r_type) {
+ // Next types must not have empty rdata.
+ case KNOT_RRTYPE_A:
+ case KNOT_RRTYPE_NS:
+ case KNOT_RRTYPE_CNAME:
+ case KNOT_RRTYPE_PTR:
+ case KNOT_RRTYPE_DNAME:
+ case KNOT_RRTYPE_SOA:
+ case KNOT_RRTYPE_HINFO:
+ case KNOT_RRTYPE_MINFO:
+ case KNOT_RRTYPE_MX:
+ case KNOT_RRTYPE_AFSDB:
+ case KNOT_RRTYPE_RT:
+ case KNOT_RRTYPE_KX:
+ case KNOT_RRTYPE_TXT:
+ case KNOT_RRTYPE_SPF:
+ case KNOT_RRTYPE_RP:
+ case KNOT_RRTYPE_AAAA:
+ case KNOT_RRTYPE_LOC:
+ case KNOT_RRTYPE_SRV:
+ case KNOT_RRTYPE_NAPTR:
+ case KNOT_RRTYPE_CERT:
+ case KNOT_RRTYPE_DS:
+ case KNOT_RRTYPE_SSHFP:
+ case KNOT_RRTYPE_IPSECKEY:
+ case KNOT_RRTYPE_RRSIG:
+ case KNOT_RRTYPE_NSEC:
+ case KNOT_RRTYPE_KEY:
+ case KNOT_RRTYPE_DNSKEY:
+ case KNOT_RRTYPE_DHCID:
+ case KNOT_RRTYPE_NSEC3:
+ case KNOT_RRTYPE_NSEC3PARAM:
+ case KNOT_RRTYPE_TLSA:
+ case KNOT_RRTYPE_NID:
+ case KNOT_RRTYPE_L32:
+ case KNOT_RRTYPE_L64:
+ case KNOT_RRTYPE_LP:
+ case KNOT_RRTYPE_EUI48:
+ case KNOT_RRTYPE_EUI64:
+ fcall nonempty_hex_r_data;
+ // Next types can have empty rdata.
+ case KNOT_RRTYPE_APL:
+ default:
+ fcall hex_r_data;
+ }
+ }
+
+ action _text_r_data_exit {
+ s->r_data_blocks[++(s->r_data_blocks_count)] =
+ (uint16_t)(rdata_tail - s->r_data);
+ }
+
+ # rdata can be in text or hex format with leading "\#" string
+ r_data =
+ ( sep . ^('\\' | all_wchar) $_text_r_data %_text_r_data_exit
+ | sep . '\\' . ^'#' ${ fhold; } $_text_r_data %_text_r_data_exit
+ | sep . '\\' . '#' $_hex_r_data # Hex format.
+ | sep? . end_wchar $_text_r_data # Empty rdata.
+ ) >_r_data_init $!_r_data_error;
+ # END
+
+ # BEGIN - Record type processing
+ action _r_type_error {
+ SCANNER_WARNING(ZSCANNER_EUNSUPPORTED_TYPE);
+ fhold; fgoto err_line;
+ }
+
+ r_type =
+ ( "A"i %{ s->r_type = KNOT_RRTYPE_A; }
+ | "NS"i %{ s->r_type = KNOT_RRTYPE_NS; }
+ | "CNAME"i %{ s->r_type = KNOT_RRTYPE_CNAME; }
+ | "SOA"i %{ s->r_type = KNOT_RRTYPE_SOA; }
+ | "PTR"i %{ s->r_type = KNOT_RRTYPE_PTR; }
+ | "HINFO"i %{ s->r_type = KNOT_RRTYPE_HINFO; }
+ | "MINFO"i %{ s->r_type = KNOT_RRTYPE_MINFO; }
+ | "MX"i %{ s->r_type = KNOT_RRTYPE_MX; }
+ | "TXT"i %{ s->r_type = KNOT_RRTYPE_TXT; }
+ | "RP"i %{ s->r_type = KNOT_RRTYPE_RP; }
+ | "AFSDB"i %{ s->r_type = KNOT_RRTYPE_AFSDB; }
+ | "RT"i %{ s->r_type = KNOT_RRTYPE_RT; }
+ | "KEY"i %{ s->r_type = KNOT_RRTYPE_KEY; }
+ | "AAAA"i %{ s->r_type = KNOT_RRTYPE_AAAA; }
+ | "LOC"i %{ s->r_type = KNOT_RRTYPE_LOC; }
+ | "SRV"i %{ s->r_type = KNOT_RRTYPE_SRV; }
+ | "NAPTR"i %{ s->r_type = KNOT_RRTYPE_NAPTR; }
+ | "KX"i %{ s->r_type = KNOT_RRTYPE_KX; }
+ | "CERT"i %{ s->r_type = KNOT_RRTYPE_CERT; }
+ | "DNAME"i %{ s->r_type = KNOT_RRTYPE_DNAME; }
+ | "APL"i %{ s->r_type = KNOT_RRTYPE_APL; }
+ | "DS"i %{ s->r_type = KNOT_RRTYPE_DS; }
+ | "SSHFP"i %{ s->r_type = KNOT_RRTYPE_SSHFP; }
+ | "IPSECKEY"i %{ s->r_type = KNOT_RRTYPE_IPSECKEY; }
+ | "RRSIG"i %{ s->r_type = KNOT_RRTYPE_RRSIG; }
+ | "NSEC"i %{ s->r_type = KNOT_RRTYPE_NSEC; }
+ | "DNSKEY"i %{ s->r_type = KNOT_RRTYPE_DNSKEY; }
+ | "DHCID"i %{ s->r_type = KNOT_RRTYPE_DHCID; }
+ | "NSEC3"i %{ s->r_type = KNOT_RRTYPE_NSEC3; }
+ | "NSEC3PARAM"i %{ s->r_type = KNOT_RRTYPE_NSEC3PARAM; }
+ | "TLSA"i %{ s->r_type = KNOT_RRTYPE_TLSA; }
+ | "SPF"i %{ s->r_type = KNOT_RRTYPE_SPF; }
+ | "NID"i %{ s->r_type = KNOT_RRTYPE_NID; }
+ | "L32"i %{ s->r_type = KNOT_RRTYPE_L32; }
+ | "L64"i %{ s->r_type = KNOT_RRTYPE_L64; }
+ | "LP"i %{ s->r_type = KNOT_RRTYPE_LP; }
+ | "EUI48"i %{ s->r_type = KNOT_RRTYPE_EUI48; }
+ | "EUI64"i %{ s->r_type = KNOT_RRTYPE_EUI64; }
+ | "TYPE"i . type_number
+ ) $!_r_type_error;
+ # END
+
+ # BEGIN - The highest level processing
+ action _record_exit {
+ if (rdata_tail - s->r_data > UINT16_MAX) {
+ SCANNER_WARNING(ZSCANNER_ERDATA_OVERFLOW);
+ fhold; fgoto err_line;
+ }
+ s->r_data_length = rdata_tail - s->r_data;
+
+ s->process_record(s);
+ }
+
+ # Resource record.
+ record =
+ r_owner . sep .
+ ( (r_class . sep . ((r_ttl . sep) | (zlen %_default_r_ttl_exit )))
+ | (r_ttl . sep . ((r_class . sep) | (zlen %_default_r_class_exit)))
+ | zlen %_default_r_class_exit %_default_r_ttl_exit
+ ) $!_r_type_error .
+ r_type . r_data .
+ rest %_record_exit .
+ newline;
+
+ # Blank spaces with comments.
+ blank = rest . newline;
+
+ # Main processing loop.
+ main := (record | directive | blank)*;
+ # END
+}%%
diff --git a/src/zscanner/scanner_functions.c b/src/zscanner/scanner_functions.c
new file mode 100644
index 0000000..94a42da
--- /dev/null
+++ b/src/zscanner/scanner_functions.c
@@ -0,0 +1,985 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "zscanner/scanner_functions.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "common/errcode.h"
+#include "common/descriptor.h"
+#include "zscanner/scanner.h"
+
+const uint8_t digit_to_num[] = {
+ ['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4,
+ ['5'] = 5, ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9,
+};
+
+/*
+ * Hex transformation:
+ * 1 2
+ * 12345678 12345678
+ * in: AAAA BBBB
+ * out: AAAABBBB
+ */
+
+const uint8_t first_hex_to_num[] = {
+ ['0'] = ( 0 * 16), ['6'] = ( 6 * 16), ['C'] = (12 * 16), ['b'] = (11 * 16),
+ ['1'] = ( 1 * 16), ['7'] = ( 7 * 16), ['D'] = (13 * 16), ['c'] = (12 * 16),
+ ['2'] = ( 2 * 16), ['8'] = ( 8 * 16), ['E'] = (14 * 16), ['d'] = (13 * 16),
+ ['3'] = ( 3 * 16), ['9'] = ( 9 * 16), ['F'] = (15 * 16), ['e'] = (14 * 16),
+ ['4'] = ( 4 * 16), ['A'] = (10 * 16), ['a'] = (10 * 16), ['f'] = (15 * 16),
+ ['5'] = ( 5 * 16), ['B'] = (11 * 16),
+};
+
+const uint8_t second_hex_to_num[] = {
+ ['0'] = 0, ['4'] = 4, ['8'] = 8, ['C'] = 12, ['a'] = 10, ['d'] = 13,
+ ['1'] = 1, ['5'] = 5, ['9'] = 9, ['D'] = 13, ['b'] = 11, ['e'] = 14,
+ ['2'] = 2, ['6'] = 6, ['A'] = 10, ['E'] = 14, ['c'] = 12, ['f'] = 15,
+ ['3'] = 3, ['7'] = 7, ['B'] = 11, ['F'] = 15,
+};
+
+/*
+ * Base64 transformation:
+ * 1 2 3 4
+ * 12345678 12345678 12345678 12345678
+ * in: 00AAAAAA 00BBBBBB 00CCCCCC 00DDDDDD
+ * out: AAAAAABB BBBBCCCC CCDDDDDD
+ */
+
+// 0x3F = 00111111
+const uint8_t first_base64_to_num[] = {
+ ['A'] = (( 0 & 0x3F) << 2), ['g'] = ((32 & 0x3F) << 2),
+ ['B'] = (( 1 & 0x3F) << 2), ['h'] = ((33 & 0x3F) << 2),
+ ['C'] = (( 2 & 0x3F) << 2), ['i'] = ((34 & 0x3F) << 2),
+ ['D'] = (( 3 & 0x3F) << 2), ['j'] = ((35 & 0x3F) << 2),
+ ['E'] = (( 4 & 0x3F) << 2), ['k'] = ((36 & 0x3F) << 2),
+ ['F'] = (( 5 & 0x3F) << 2), ['l'] = ((37 & 0x3F) << 2),
+ ['G'] = (( 6 & 0x3F) << 2), ['m'] = ((38 & 0x3F) << 2),
+ ['H'] = (( 7 & 0x3F) << 2), ['n'] = ((39 & 0x3F) << 2),
+ ['I'] = (( 8 & 0x3F) << 2), ['o'] = ((40 & 0x3F) << 2),
+ ['J'] = (( 9 & 0x3F) << 2), ['p'] = ((41 & 0x3F) << 2),
+ ['K'] = ((10 & 0x3F) << 2), ['q'] = ((42 & 0x3F) << 2),
+ ['L'] = ((11 & 0x3F) << 2), ['r'] = ((43 & 0x3F) << 2),
+ ['M'] = ((12 & 0x3F) << 2), ['s'] = ((44 & 0x3F) << 2),
+ ['N'] = ((13 & 0x3F) << 2), ['t'] = ((45 & 0x3F) << 2),
+ ['O'] = ((14 & 0x3F) << 2), ['u'] = ((46 & 0x3F) << 2),
+ ['P'] = ((15 & 0x3F) << 2), ['v'] = ((47 & 0x3F) << 2),
+ ['Q'] = ((16 & 0x3F) << 2), ['w'] = ((48 & 0x3F) << 2),
+ ['R'] = ((17 & 0x3F) << 2), ['x'] = ((49 & 0x3F) << 2),
+ ['S'] = ((18 & 0x3F) << 2), ['y'] = ((50 & 0x3F) << 2),
+ ['T'] = ((19 & 0x3F) << 2), ['z'] = ((51 & 0x3F) << 2),
+ ['U'] = ((20 & 0x3F) << 2), ['0'] = ((52 & 0x3F) << 2),
+ ['V'] = ((21 & 0x3F) << 2), ['1'] = ((53 & 0x3F) << 2),
+ ['W'] = ((22 & 0x3F) << 2), ['2'] = ((54 & 0x3F) << 2),
+ ['X'] = ((23 & 0x3F) << 2), ['3'] = ((55 & 0x3F) << 2),
+ ['Y'] = ((24 & 0x3F) << 2), ['4'] = ((56 & 0x3F) << 2),
+ ['Z'] = ((25 & 0x3F) << 2), ['5'] = ((57 & 0x3F) << 2),
+ ['a'] = ((26 & 0x3F) << 2), ['6'] = ((58 & 0x3F) << 2),
+ ['b'] = ((27 & 0x3F) << 2), ['7'] = ((59 & 0x3F) << 2),
+ ['c'] = ((28 & 0x3F) << 2), ['8'] = ((60 & 0x3F) << 2),
+ ['d'] = ((29 & 0x3F) << 2), ['9'] = ((61 & 0x3F) << 2),
+ ['e'] = ((30 & 0x3F) << 2), ['+'] = ((62 & 0x3F) << 2),
+ ['f'] = ((31 & 0x3F) << 2), ['/'] = ((63 & 0x3F) << 2),
+};
+
+// 0x30 = 00110000
+const uint8_t second_left_base64_to_num[] = {
+ ['A'] = (( 0 & 0x30) >> 4), ['g'] = ((32 & 0x30) >> 4),
+ ['B'] = (( 1 & 0x30) >> 4), ['h'] = ((33 & 0x30) >> 4),
+ ['C'] = (( 2 & 0x30) >> 4), ['i'] = ((34 & 0x30) >> 4),
+ ['D'] = (( 3 & 0x30) >> 4), ['j'] = ((35 & 0x30) >> 4),
+ ['E'] = (( 4 & 0x30) >> 4), ['k'] = ((36 & 0x30) >> 4),
+ ['F'] = (( 5 & 0x30) >> 4), ['l'] = ((37 & 0x30) >> 4),
+ ['G'] = (( 6 & 0x30) >> 4), ['m'] = ((38 & 0x30) >> 4),
+ ['H'] = (( 7 & 0x30) >> 4), ['n'] = ((39 & 0x30) >> 4),
+ ['I'] = (( 8 & 0x30) >> 4), ['o'] = ((40 & 0x30) >> 4),
+ ['J'] = (( 9 & 0x30) >> 4), ['p'] = ((41 & 0x30) >> 4),
+ ['K'] = ((10 & 0x30) >> 4), ['q'] = ((42 & 0x30) >> 4),
+ ['L'] = ((11 & 0x30) >> 4), ['r'] = ((43 & 0x30) >> 4),
+ ['M'] = ((12 & 0x30) >> 4), ['s'] = ((44 & 0x30) >> 4),
+ ['N'] = ((13 & 0x30) >> 4), ['t'] = ((45 & 0x30) >> 4),
+ ['O'] = ((14 & 0x30) >> 4), ['u'] = ((46 & 0x30) >> 4),
+ ['P'] = ((15 & 0x30) >> 4), ['v'] = ((47 & 0x30) >> 4),
+ ['Q'] = ((16 & 0x30) >> 4), ['w'] = ((48 & 0x30) >> 4),
+ ['R'] = ((17 & 0x30) >> 4), ['x'] = ((49 & 0x30) >> 4),
+ ['S'] = ((18 & 0x30) >> 4), ['y'] = ((50 & 0x30) >> 4),
+ ['T'] = ((19 & 0x30) >> 4), ['z'] = ((51 & 0x30) >> 4),
+ ['U'] = ((20 & 0x30) >> 4), ['0'] = ((52 & 0x30) >> 4),
+ ['V'] = ((21 & 0x30) >> 4), ['1'] = ((53 & 0x30) >> 4),
+ ['W'] = ((22 & 0x30) >> 4), ['2'] = ((54 & 0x30) >> 4),
+ ['X'] = ((23 & 0x30) >> 4), ['3'] = ((55 & 0x30) >> 4),
+ ['Y'] = ((24 & 0x30) >> 4), ['4'] = ((56 & 0x30) >> 4),
+ ['Z'] = ((25 & 0x30) >> 4), ['5'] = ((57 & 0x30) >> 4),
+ ['a'] = ((26 & 0x30) >> 4), ['6'] = ((58 & 0x30) >> 4),
+ ['b'] = ((27 & 0x30) >> 4), ['7'] = ((59 & 0x30) >> 4),
+ ['c'] = ((28 & 0x30) >> 4), ['8'] = ((60 & 0x30) >> 4),
+ ['d'] = ((29 & 0x30) >> 4), ['9'] = ((61 & 0x30) >> 4),
+ ['e'] = ((30 & 0x30) >> 4), ['+'] = ((62 & 0x30) >> 4),
+ ['f'] = ((31 & 0x30) >> 4), ['/'] = ((63 & 0x30) >> 4),
+};
+
+// 0x0F = 00001111
+const uint8_t second_right_base64_to_num[] = {
+ ['A'] = (( 0 & 0x0F) << 4), ['g'] = ((32 & 0x0F) << 4),
+ ['B'] = (( 1 & 0x0F) << 4), ['h'] = ((33 & 0x0F) << 4),
+ ['C'] = (( 2 & 0x0F) << 4), ['i'] = ((34 & 0x0F) << 4),
+ ['D'] = (( 3 & 0x0F) << 4), ['j'] = ((35 & 0x0F) << 4),
+ ['E'] = (( 4 & 0x0F) << 4), ['k'] = ((36 & 0x0F) << 4),
+ ['F'] = (( 5 & 0x0F) << 4), ['l'] = ((37 & 0x0F) << 4),
+ ['G'] = (( 6 & 0x0F) << 4), ['m'] = ((38 & 0x0F) << 4),
+ ['H'] = (( 7 & 0x0F) << 4), ['n'] = ((39 & 0x0F) << 4),
+ ['I'] = (( 8 & 0x0F) << 4), ['o'] = ((40 & 0x0F) << 4),
+ ['J'] = (( 9 & 0x0F) << 4), ['p'] = ((41 & 0x0F) << 4),
+ ['K'] = ((10 & 0x0F) << 4), ['q'] = ((42 & 0x0F) << 4),
+ ['L'] = ((11 & 0x0F) << 4), ['r'] = ((43 & 0x0F) << 4),
+ ['M'] = ((12 & 0x0F) << 4), ['s'] = ((44 & 0x0F) << 4),
+ ['N'] = ((13 & 0x0F) << 4), ['t'] = ((45 & 0x0F) << 4),
+ ['O'] = ((14 & 0x0F) << 4), ['u'] = ((46 & 0x0F) << 4),
+ ['P'] = ((15 & 0x0F) << 4), ['v'] = ((47 & 0x0F) << 4),
+ ['Q'] = ((16 & 0x0F) << 4), ['w'] = ((48 & 0x0F) << 4),
+ ['R'] = ((17 & 0x0F) << 4), ['x'] = ((49 & 0x0F) << 4),
+ ['S'] = ((18 & 0x0F) << 4), ['y'] = ((50 & 0x0F) << 4),
+ ['T'] = ((19 & 0x0F) << 4), ['z'] = ((51 & 0x0F) << 4),
+ ['U'] = ((20 & 0x0F) << 4), ['0'] = ((52 & 0x0F) << 4),
+ ['V'] = ((21 & 0x0F) << 4), ['1'] = ((53 & 0x0F) << 4),
+ ['W'] = ((22 & 0x0F) << 4), ['2'] = ((54 & 0x0F) << 4),
+ ['X'] = ((23 & 0x0F) << 4), ['3'] = ((55 & 0x0F) << 4),
+ ['Y'] = ((24 & 0x0F) << 4), ['4'] = ((56 & 0x0F) << 4),
+ ['Z'] = ((25 & 0x0F) << 4), ['5'] = ((57 & 0x0F) << 4),
+ ['a'] = ((26 & 0x0F) << 4), ['6'] = ((58 & 0x0F) << 4),
+ ['b'] = ((27 & 0x0F) << 4), ['7'] = ((59 & 0x0F) << 4),
+ ['c'] = ((28 & 0x0F) << 4), ['8'] = ((60 & 0x0F) << 4),
+ ['d'] = ((29 & 0x0F) << 4), ['9'] = ((61 & 0x0F) << 4),
+ ['e'] = ((30 & 0x0F) << 4), ['+'] = ((62 & 0x0F) << 4),
+ ['f'] = ((31 & 0x0F) << 4), ['/'] = ((63 & 0x0F) << 4),
+};
+
+// 0x3C = 00111100
+const uint8_t third_left_base64_to_num[] = {
+ ['A'] = (( 0 & 0x3C) >> 2), ['g'] = ((32 & 0x3C) >> 2),
+ ['B'] = (( 1 & 0x3C) >> 2), ['h'] = ((33 & 0x3C) >> 2),
+ ['C'] = (( 2 & 0x3C) >> 2), ['i'] = ((34 & 0x3C) >> 2),
+ ['D'] = (( 3 & 0x3C) >> 2), ['j'] = ((35 & 0x3C) >> 2),
+ ['E'] = (( 4 & 0x3C) >> 2), ['k'] = ((36 & 0x3C) >> 2),
+ ['F'] = (( 5 & 0x3C) >> 2), ['l'] = ((37 & 0x3C) >> 2),
+ ['G'] = (( 6 & 0x3C) >> 2), ['m'] = ((38 & 0x3C) >> 2),
+ ['H'] = (( 7 & 0x3C) >> 2), ['n'] = ((39 & 0x3C) >> 2),
+ ['I'] = (( 8 & 0x3C) >> 2), ['o'] = ((40 & 0x3C) >> 2),
+ ['J'] = (( 9 & 0x3C) >> 2), ['p'] = ((41 & 0x3C) >> 2),
+ ['K'] = ((10 & 0x3C) >> 2), ['q'] = ((42 & 0x3C) >> 2),
+ ['L'] = ((11 & 0x3C) >> 2), ['r'] = ((43 & 0x3C) >> 2),
+ ['M'] = ((12 & 0x3C) >> 2), ['s'] = ((44 & 0x3C) >> 2),
+ ['N'] = ((13 & 0x3C) >> 2), ['t'] = ((45 & 0x3C) >> 2),
+ ['O'] = ((14 & 0x3C) >> 2), ['u'] = ((46 & 0x3C) >> 2),
+ ['P'] = ((15 & 0x3C) >> 2), ['v'] = ((47 & 0x3C) >> 2),
+ ['Q'] = ((16 & 0x3C) >> 2), ['w'] = ((48 & 0x3C) >> 2),
+ ['R'] = ((17 & 0x3C) >> 2), ['x'] = ((49 & 0x3C) >> 2),
+ ['S'] = ((18 & 0x3C) >> 2), ['y'] = ((50 & 0x3C) >> 2),
+ ['T'] = ((19 & 0x3C) >> 2), ['z'] = ((51 & 0x3C) >> 2),
+ ['U'] = ((20 & 0x3C) >> 2), ['0'] = ((52 & 0x3C) >> 2),
+ ['V'] = ((21 & 0x3C) >> 2), ['1'] = ((53 & 0x3C) >> 2),
+ ['W'] = ((22 & 0x3C) >> 2), ['2'] = ((54 & 0x3C) >> 2),
+ ['X'] = ((23 & 0x3C) >> 2), ['3'] = ((55 & 0x3C) >> 2),
+ ['Y'] = ((24 & 0x3C) >> 2), ['4'] = ((56 & 0x3C) >> 2),
+ ['Z'] = ((25 & 0x3C) >> 2), ['5'] = ((57 & 0x3C) >> 2),
+ ['a'] = ((26 & 0x3C) >> 2), ['6'] = ((58 & 0x3C) >> 2),
+ ['b'] = ((27 & 0x3C) >> 2), ['7'] = ((59 & 0x3C) >> 2),
+ ['c'] = ((28 & 0x3C) >> 2), ['8'] = ((60 & 0x3C) >> 2),
+ ['d'] = ((29 & 0x3C) >> 2), ['9'] = ((61 & 0x3C) >> 2),
+ ['e'] = ((30 & 0x3C) >> 2), ['+'] = ((62 & 0x3C) >> 2),
+ ['f'] = ((31 & 0x3C) >> 2), ['/'] = ((63 & 0x3C) >> 2),
+};
+
+// 0x03 = 00000011
+const uint8_t third_right_base64_to_num[] = {
+ ['A'] = (( 0 & 0x03) << 6), ['g'] = ((32 & 0x03) << 6),
+ ['B'] = (( 1 & 0x03) << 6), ['h'] = ((33 & 0x03) << 6),
+ ['C'] = (( 2 & 0x03) << 6), ['i'] = ((34 & 0x03) << 6),
+ ['D'] = (( 3 & 0x03) << 6), ['j'] = ((35 & 0x03) << 6),
+ ['E'] = (( 4 & 0x03) << 6), ['k'] = ((36 & 0x03) << 6),
+ ['F'] = (( 5 & 0x03) << 6), ['l'] = ((37 & 0x03) << 6),
+ ['G'] = (( 6 & 0x03) << 6), ['m'] = ((38 & 0x03) << 6),
+ ['H'] = (( 7 & 0x03) << 6), ['n'] = ((39 & 0x03) << 6),
+ ['I'] = (( 8 & 0x03) << 6), ['o'] = ((40 & 0x03) << 6),
+ ['J'] = (( 9 & 0x03) << 6), ['p'] = ((41 & 0x03) << 6),
+ ['K'] = ((10 & 0x03) << 6), ['q'] = ((42 & 0x03) << 6),
+ ['L'] = ((11 & 0x03) << 6), ['r'] = ((43 & 0x03) << 6),
+ ['M'] = ((12 & 0x03) << 6), ['s'] = ((44 & 0x03) << 6),
+ ['N'] = ((13 & 0x03) << 6), ['t'] = ((45 & 0x03) << 6),
+ ['O'] = ((14 & 0x03) << 6), ['u'] = ((46 & 0x03) << 6),
+ ['P'] = ((15 & 0x03) << 6), ['v'] = ((47 & 0x03) << 6),
+ ['Q'] = ((16 & 0x03) << 6), ['w'] = ((48 & 0x03) << 6),
+ ['R'] = ((17 & 0x03) << 6), ['x'] = ((49 & 0x03) << 6),
+ ['S'] = ((18 & 0x03) << 6), ['y'] = ((50 & 0x03) << 6),
+ ['T'] = ((19 & 0x03) << 6), ['z'] = ((51 & 0x03) << 6),
+ ['U'] = ((20 & 0x03) << 6), ['0'] = ((52 & 0x03) << 6),
+ ['V'] = ((21 & 0x03) << 6), ['1'] = ((53 & 0x03) << 6),
+ ['W'] = ((22 & 0x03) << 6), ['2'] = ((54 & 0x03) << 6),
+ ['X'] = ((23 & 0x03) << 6), ['3'] = ((55 & 0x03) << 6),
+ ['Y'] = ((24 & 0x03) << 6), ['4'] = ((56 & 0x03) << 6),
+ ['Z'] = ((25 & 0x03) << 6), ['5'] = ((57 & 0x03) << 6),
+ ['a'] = ((26 & 0x03) << 6), ['6'] = ((58 & 0x03) << 6),
+ ['b'] = ((27 & 0x03) << 6), ['7'] = ((59 & 0x03) << 6),
+ ['c'] = ((28 & 0x03) << 6), ['8'] = ((60 & 0x03) << 6),
+ ['d'] = ((29 & 0x03) << 6), ['9'] = ((61 & 0x03) << 6),
+ ['e'] = ((30 & 0x03) << 6), ['+'] = ((62 & 0x03) << 6),
+ ['f'] = ((31 & 0x03) << 6), ['/'] = ((63 & 0x03) << 6),
+};
+
+// 0x3F = 00111111
+const uint8_t fourth_base64_to_num[] = {
+ ['A'] = (( 0 & 0x3F) << 0), ['g'] = ((32 & 0x3F) << 0),
+ ['B'] = (( 1 & 0x3F) << 0), ['h'] = ((33 & 0x3F) << 0),
+ ['C'] = (( 2 & 0x3F) << 0), ['i'] = ((34 & 0x3F) << 0),
+ ['D'] = (( 3 & 0x3F) << 0), ['j'] = ((35 & 0x3F) << 0),
+ ['E'] = (( 4 & 0x3F) << 0), ['k'] = ((36 & 0x3F) << 0),
+ ['F'] = (( 5 & 0x3F) << 0), ['l'] = ((37 & 0x3F) << 0),
+ ['G'] = (( 6 & 0x3F) << 0), ['m'] = ((38 & 0x3F) << 0),
+ ['H'] = (( 7 & 0x3F) << 0), ['n'] = ((39 & 0x3F) << 0),
+ ['I'] = (( 8 & 0x3F) << 0), ['o'] = ((40 & 0x3F) << 0),
+ ['J'] = (( 9 & 0x3F) << 0), ['p'] = ((41 & 0x3F) << 0),
+ ['K'] = ((10 & 0x3F) << 0), ['q'] = ((42 & 0x3F) << 0),
+ ['L'] = ((11 & 0x3F) << 0), ['r'] = ((43 & 0x3F) << 0),
+ ['M'] = ((12 & 0x3F) << 0), ['s'] = ((44 & 0x3F) << 0),
+ ['N'] = ((13 & 0x3F) << 0), ['t'] = ((45 & 0x3F) << 0),
+ ['O'] = ((14 & 0x3F) << 0), ['u'] = ((46 & 0x3F) << 0),
+ ['P'] = ((15 & 0x3F) << 0), ['v'] = ((47 & 0x3F) << 0),
+ ['Q'] = ((16 & 0x3F) << 0), ['w'] = ((48 & 0x3F) << 0),
+ ['R'] = ((17 & 0x3F) << 0), ['x'] = ((49 & 0x3F) << 0),
+ ['S'] = ((18 & 0x3F) << 0), ['y'] = ((50 & 0x3F) << 0),
+ ['T'] = ((19 & 0x3F) << 0), ['z'] = ((51 & 0x3F) << 0),
+ ['U'] = ((20 & 0x3F) << 0), ['0'] = ((52 & 0x3F) << 0),
+ ['V'] = ((21 & 0x3F) << 0), ['1'] = ((53 & 0x3F) << 0),
+ ['W'] = ((22 & 0x3F) << 0), ['2'] = ((54 & 0x3F) << 0),
+ ['X'] = ((23 & 0x3F) << 0), ['3'] = ((55 & 0x3F) << 0),
+ ['Y'] = ((24 & 0x3F) << 0), ['4'] = ((56 & 0x3F) << 0),
+ ['Z'] = ((25 & 0x3F) << 0), ['5'] = ((57 & 0x3F) << 0),
+ ['a'] = ((26 & 0x3F) << 0), ['6'] = ((58 & 0x3F) << 0),
+ ['b'] = ((27 & 0x3F) << 0), ['7'] = ((59 & 0x3F) << 0),
+ ['c'] = ((28 & 0x3F) << 0), ['8'] = ((60 & 0x3F) << 0),
+ ['d'] = ((29 & 0x3F) << 0), ['9'] = ((61 & 0x3F) << 0),
+ ['e'] = ((30 & 0x3F) << 0), ['+'] = ((62 & 0x3F) << 0),
+ ['f'] = ((31 & 0x3F) << 0), ['/'] = ((63 & 0x3F) << 0),
+};
+
+/*
+ * Base32hex transformation (with lower-case):
+ * 1 2 3 4 5 6 7 8
+ * 12345678 12345678 12345678 12345678 12345678 12345678 12345678 12345678
+ * in: 000AAAAA 000BBBBB 000CCCCC 000DDDDD 000EEEEE 000FFFFF 000GGGGG 000HHHHH
+ * out AAAAABBB BBCCCCCD DDDDEEEE EFFFFFGG GGGHHHHH
+ */
+
+// 0x1F = 00011111
+const uint8_t first_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x1F) << 3), ['R'] = ((27 & 0x1F) << 3),
+ ['1'] = (( 1 & 0x1F) << 3), ['S'] = ((28 & 0x1F) << 3),
+ ['2'] = (( 2 & 0x1F) << 3), ['T'] = ((29 & 0x1F) << 3),
+ ['3'] = (( 3 & 0x1F) << 3), ['U'] = ((30 & 0x1F) << 3),
+ ['4'] = (( 4 & 0x1F) << 3), ['V'] = ((31 & 0x1F) << 3),
+ ['5'] = (( 5 & 0x1F) << 3), ['a'] = ((10 & 0x1F) << 3),
+ ['6'] = (( 6 & 0x1F) << 3), ['b'] = ((11 & 0x1F) << 3),
+ ['7'] = (( 7 & 0x1F) << 3), ['c'] = ((12 & 0x1F) << 3),
+ ['8'] = (( 8 & 0x1F) << 3), ['d'] = ((13 & 0x1F) << 3),
+ ['9'] = (( 9 & 0x1F) << 3), ['e'] = ((14 & 0x1F) << 3),
+ ['A'] = ((10 & 0x1F) << 3), ['f'] = ((15 & 0x1F) << 3),
+ ['B'] = ((11 & 0x1F) << 3), ['g'] = ((16 & 0x1F) << 3),
+ ['C'] = ((12 & 0x1F) << 3), ['h'] = ((17 & 0x1F) << 3),
+ ['D'] = ((13 & 0x1F) << 3), ['i'] = ((18 & 0x1F) << 3),
+ ['E'] = ((14 & 0x1F) << 3), ['j'] = ((19 & 0x1F) << 3),
+ ['F'] = ((15 & 0x1F) << 3), ['k'] = ((20 & 0x1F) << 3),
+ ['G'] = ((16 & 0x1F) << 3), ['l'] = ((21 & 0x1F) << 3),
+ ['H'] = ((17 & 0x1F) << 3), ['m'] = ((22 & 0x1F) << 3),
+ ['I'] = ((18 & 0x1F) << 3), ['n'] = ((23 & 0x1F) << 3),
+ ['J'] = ((19 & 0x1F) << 3), ['o'] = ((24 & 0x1F) << 3),
+ ['K'] = ((20 & 0x1F) << 3), ['p'] = ((25 & 0x1F) << 3),
+ ['L'] = ((21 & 0x1F) << 3), ['q'] = ((26 & 0x1F) << 3),
+ ['M'] = ((22 & 0x1F) << 3), ['r'] = ((27 & 0x1F) << 3),
+ ['N'] = ((23 & 0x1F) << 3), ['s'] = ((28 & 0x1F) << 3),
+ ['O'] = ((24 & 0x1F) << 3), ['t'] = ((29 & 0x1F) << 3),
+ ['P'] = ((25 & 0x1F) << 3), ['u'] = ((30 & 0x1F) << 3),
+ ['Q'] = ((26 & 0x1F) << 3), ['v'] = ((31 & 0x1F) << 3),
+};
+
+// 0x1C = 00011100
+const uint8_t second_left_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x1C) >> 2), ['R'] = ((27 & 0x1C) >> 2),
+ ['1'] = (( 1 & 0x1C) >> 2), ['S'] = ((28 & 0x1C) >> 2),
+ ['2'] = (( 2 & 0x1C) >> 2), ['T'] = ((29 & 0x1C) >> 2),
+ ['3'] = (( 3 & 0x1C) >> 2), ['U'] = ((30 & 0x1C) >> 2),
+ ['4'] = (( 4 & 0x1C) >> 2), ['V'] = ((31 & 0x1C) >> 2),
+ ['5'] = (( 5 & 0x1C) >> 2), ['a'] = ((10 & 0x1C) >> 2),
+ ['6'] = (( 6 & 0x1C) >> 2), ['b'] = ((11 & 0x1C) >> 2),
+ ['7'] = (( 7 & 0x1C) >> 2), ['c'] = ((12 & 0x1C) >> 2),
+ ['8'] = (( 8 & 0x1C) >> 2), ['d'] = ((13 & 0x1C) >> 2),
+ ['9'] = (( 9 & 0x1C) >> 2), ['e'] = ((14 & 0x1C) >> 2),
+ ['A'] = ((10 & 0x1C) >> 2), ['f'] = ((15 & 0x1C) >> 2),
+ ['B'] = ((11 & 0x1C) >> 2), ['g'] = ((16 & 0x1C) >> 2),
+ ['C'] = ((12 & 0x1C) >> 2), ['h'] = ((17 & 0x1C) >> 2),
+ ['D'] = ((13 & 0x1C) >> 2), ['i'] = ((18 & 0x1C) >> 2),
+ ['E'] = ((14 & 0x1C) >> 2), ['j'] = ((19 & 0x1C) >> 2),
+ ['F'] = ((15 & 0x1C) >> 2), ['k'] = ((20 & 0x1C) >> 2),
+ ['G'] = ((16 & 0x1C) >> 2), ['l'] = ((21 & 0x1C) >> 2),
+ ['H'] = ((17 & 0x1C) >> 2), ['m'] = ((22 & 0x1C) >> 2),
+ ['I'] = ((18 & 0x1C) >> 2), ['n'] = ((23 & 0x1C) >> 2),
+ ['J'] = ((19 & 0x1C) >> 2), ['o'] = ((24 & 0x1C) >> 2),
+ ['K'] = ((20 & 0x1C) >> 2), ['p'] = ((25 & 0x1C) >> 2),
+ ['L'] = ((21 & 0x1C) >> 2), ['q'] = ((26 & 0x1C) >> 2),
+ ['M'] = ((22 & 0x1C) >> 2), ['r'] = ((27 & 0x1C) >> 2),
+ ['N'] = ((23 & 0x1C) >> 2), ['s'] = ((28 & 0x1C) >> 2),
+ ['O'] = ((24 & 0x1C) >> 2), ['t'] = ((29 & 0x1C) >> 2),
+ ['P'] = ((25 & 0x1C) >> 2), ['u'] = ((30 & 0x1C) >> 2),
+ ['Q'] = ((26 & 0x1C) >> 2), ['v'] = ((31 & 0x1C) >> 2),
+};
+
+// 0x03 = 00000011
+const uint8_t second_right_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x03) << 6), ['R'] = ((27 & 0x03) << 6),
+ ['1'] = (( 1 & 0x03) << 6), ['S'] = ((28 & 0x03) << 6),
+ ['2'] = (( 2 & 0x03) << 6), ['T'] = ((29 & 0x03) << 6),
+ ['3'] = (( 3 & 0x03) << 6), ['U'] = ((30 & 0x03) << 6),
+ ['4'] = (( 4 & 0x03) << 6), ['V'] = ((31 & 0x03) << 6),
+ ['5'] = (( 5 & 0x03) << 6), ['a'] = ((10 & 0x03) << 6),
+ ['6'] = (( 6 & 0x03) << 6), ['b'] = ((11 & 0x03) << 6),
+ ['7'] = (( 7 & 0x03) << 6), ['c'] = ((12 & 0x03) << 6),
+ ['8'] = (( 8 & 0x03) << 6), ['d'] = ((13 & 0x03) << 6),
+ ['9'] = (( 9 & 0x03) << 6), ['e'] = ((14 & 0x03) << 6),
+ ['A'] = ((10 & 0x03) << 6), ['f'] = ((15 & 0x03) << 6),
+ ['B'] = ((11 & 0x03) << 6), ['g'] = ((16 & 0x03) << 6),
+ ['C'] = ((12 & 0x03) << 6), ['h'] = ((17 & 0x03) << 6),
+ ['D'] = ((13 & 0x03) << 6), ['i'] = ((18 & 0x03) << 6),
+ ['E'] = ((14 & 0x03) << 6), ['j'] = ((19 & 0x03) << 6),
+ ['F'] = ((15 & 0x03) << 6), ['k'] = ((20 & 0x03) << 6),
+ ['G'] = ((16 & 0x03) << 6), ['l'] = ((21 & 0x03) << 6),
+ ['H'] = ((17 & 0x03) << 6), ['m'] = ((22 & 0x03) << 6),
+ ['I'] = ((18 & 0x03) << 6), ['n'] = ((23 & 0x03) << 6),
+ ['J'] = ((19 & 0x03) << 6), ['o'] = ((24 & 0x03) << 6),
+ ['K'] = ((20 & 0x03) << 6), ['p'] = ((25 & 0x03) << 6),
+ ['L'] = ((21 & 0x03) << 6), ['q'] = ((26 & 0x03) << 6),
+ ['M'] = ((22 & 0x03) << 6), ['r'] = ((27 & 0x03) << 6),
+ ['N'] = ((23 & 0x03) << 6), ['s'] = ((28 & 0x03) << 6),
+ ['O'] = ((24 & 0x03) << 6), ['t'] = ((29 & 0x03) << 6),
+ ['P'] = ((25 & 0x03) << 6), ['u'] = ((30 & 0x03) << 6),
+ ['Q'] = ((26 & 0x03) << 6), ['v'] = ((31 & 0x03) << 6),
+};
+
+// 0x1F = 00011111
+const uint8_t third_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x1F) << 1), ['R'] = ((27 & 0x1F) << 1),
+ ['1'] = (( 1 & 0x1F) << 1), ['S'] = ((28 & 0x1F) << 1),
+ ['2'] = (( 2 & 0x1F) << 1), ['T'] = ((29 & 0x1F) << 1),
+ ['3'] = (( 3 & 0x1F) << 1), ['U'] = ((30 & 0x1F) << 1),
+ ['4'] = (( 4 & 0x1F) << 1), ['V'] = ((31 & 0x1F) << 1),
+ ['5'] = (( 5 & 0x1F) << 1), ['a'] = ((10 & 0x1F) << 1),
+ ['6'] = (( 6 & 0x1F) << 1), ['b'] = ((11 & 0x1F) << 1),
+ ['7'] = (( 7 & 0x1F) << 1), ['c'] = ((12 & 0x1F) << 1),
+ ['8'] = (( 8 & 0x1F) << 1), ['d'] = ((13 & 0x1F) << 1),
+ ['9'] = (( 9 & 0x1F) << 1), ['e'] = ((14 & 0x1F) << 1),
+ ['A'] = ((10 & 0x1F) << 1), ['f'] = ((15 & 0x1F) << 1),
+ ['B'] = ((11 & 0x1F) << 1), ['g'] = ((16 & 0x1F) << 1),
+ ['C'] = ((12 & 0x1F) << 1), ['h'] = ((17 & 0x1F) << 1),
+ ['D'] = ((13 & 0x1F) << 1), ['i'] = ((18 & 0x1F) << 1),
+ ['E'] = ((14 & 0x1F) << 1), ['j'] = ((19 & 0x1F) << 1),
+ ['F'] = ((15 & 0x1F) << 1), ['k'] = ((20 & 0x1F) << 1),
+ ['G'] = ((16 & 0x1F) << 1), ['l'] = ((21 & 0x1F) << 1),
+ ['H'] = ((17 & 0x1F) << 1), ['m'] = ((22 & 0x1F) << 1),
+ ['I'] = ((18 & 0x1F) << 1), ['n'] = ((23 & 0x1F) << 1),
+ ['J'] = ((19 & 0x1F) << 1), ['o'] = ((24 & 0x1F) << 1),
+ ['K'] = ((20 & 0x1F) << 1), ['p'] = ((25 & 0x1F) << 1),
+ ['L'] = ((21 & 0x1F) << 1), ['q'] = ((26 & 0x1F) << 1),
+ ['M'] = ((22 & 0x1F) << 1), ['r'] = ((27 & 0x1F) << 1),
+ ['N'] = ((23 & 0x1F) << 1), ['s'] = ((28 & 0x1F) << 1),
+ ['O'] = ((24 & 0x1F) << 1), ['t'] = ((29 & 0x1F) << 1),
+ ['P'] = ((25 & 0x1F) << 1), ['u'] = ((30 & 0x1F) << 1),
+ ['Q'] = ((26 & 0x1F) << 1), ['v'] = ((31 & 0x1F) << 1),
+};
+
+// 0x10 = 00010000
+const uint8_t fourth_left_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x10) >> 4), ['R'] = ((27 & 0x10) >> 4),
+ ['1'] = (( 1 & 0x10) >> 4), ['S'] = ((28 & 0x10) >> 4),
+ ['2'] = (( 2 & 0x10) >> 4), ['T'] = ((29 & 0x10) >> 4),
+ ['3'] = (( 3 & 0x10) >> 4), ['U'] = ((30 & 0x10) >> 4),
+ ['4'] = (( 4 & 0x10) >> 4), ['V'] = ((31 & 0x10) >> 4),
+ ['5'] = (( 5 & 0x10) >> 4), ['a'] = ((10 & 0x10) >> 4),
+ ['6'] = (( 6 & 0x10) >> 4), ['b'] = ((11 & 0x10) >> 4),
+ ['7'] = (( 7 & 0x10) >> 4), ['c'] = ((12 & 0x10) >> 4),
+ ['8'] = (( 8 & 0x10) >> 4), ['d'] = ((13 & 0x10) >> 4),
+ ['9'] = (( 9 & 0x10) >> 4), ['e'] = ((14 & 0x10) >> 4),
+ ['A'] = ((10 & 0x10) >> 4), ['f'] = ((15 & 0x10) >> 4),
+ ['B'] = ((11 & 0x10) >> 4), ['g'] = ((16 & 0x10) >> 4),
+ ['C'] = ((12 & 0x10) >> 4), ['h'] = ((17 & 0x10) >> 4),
+ ['D'] = ((13 & 0x10) >> 4), ['i'] = ((18 & 0x10) >> 4),
+ ['E'] = ((14 & 0x10) >> 4), ['j'] = ((19 & 0x10) >> 4),
+ ['F'] = ((15 & 0x10) >> 4), ['k'] = ((20 & 0x10) >> 4),
+ ['G'] = ((16 & 0x10) >> 4), ['l'] = ((21 & 0x10) >> 4),
+ ['H'] = ((17 & 0x10) >> 4), ['m'] = ((22 & 0x10) >> 4),
+ ['I'] = ((18 & 0x10) >> 4), ['n'] = ((23 & 0x10) >> 4),
+ ['J'] = ((19 & 0x10) >> 4), ['o'] = ((24 & 0x10) >> 4),
+ ['K'] = ((20 & 0x10) >> 4), ['p'] = ((25 & 0x10) >> 4),
+ ['L'] = ((21 & 0x10) >> 4), ['q'] = ((26 & 0x10) >> 4),
+ ['M'] = ((22 & 0x10) >> 4), ['r'] = ((27 & 0x10) >> 4),
+ ['N'] = ((23 & 0x10) >> 4), ['s'] = ((28 & 0x10) >> 4),
+ ['O'] = ((24 & 0x10) >> 4), ['t'] = ((29 & 0x10) >> 4),
+ ['P'] = ((25 & 0x10) >> 4), ['u'] = ((30 & 0x10) >> 4),
+ ['Q'] = ((26 & 0x10) >> 4), ['v'] = ((31 & 0x10) >> 4),
+};
+
+// 0x0F = 00001111
+const uint8_t fourth_right_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x0F) << 4), ['R'] = ((27 & 0x0F) << 4),
+ ['1'] = (( 1 & 0x0F) << 4), ['S'] = ((28 & 0x0F) << 4),
+ ['2'] = (( 2 & 0x0F) << 4), ['T'] = ((29 & 0x0F) << 4),
+ ['3'] = (( 3 & 0x0F) << 4), ['U'] = ((30 & 0x0F) << 4),
+ ['4'] = (( 4 & 0x0F) << 4), ['V'] = ((31 & 0x0F) << 4),
+ ['5'] = (( 5 & 0x0F) << 4), ['a'] = ((10 & 0x0F) << 4),
+ ['6'] = (( 6 & 0x0F) << 4), ['b'] = ((11 & 0x0F) << 4),
+ ['7'] = (( 7 & 0x0F) << 4), ['c'] = ((12 & 0x0F) << 4),
+ ['8'] = (( 8 & 0x0F) << 4), ['d'] = ((13 & 0x0F) << 4),
+ ['9'] = (( 9 & 0x0F) << 4), ['e'] = ((14 & 0x0F) << 4),
+ ['A'] = ((10 & 0x0F) << 4), ['f'] = ((15 & 0x0F) << 4),
+ ['B'] = ((11 & 0x0F) << 4), ['g'] = ((16 & 0x0F) << 4),
+ ['C'] = ((12 & 0x0F) << 4), ['h'] = ((17 & 0x0F) << 4),
+ ['D'] = ((13 & 0x0F) << 4), ['i'] = ((18 & 0x0F) << 4),
+ ['E'] = ((14 & 0x0F) << 4), ['j'] = ((19 & 0x0F) << 4),
+ ['F'] = ((15 & 0x0F) << 4), ['k'] = ((20 & 0x0F) << 4),
+ ['G'] = ((16 & 0x0F) << 4), ['l'] = ((21 & 0x0F) << 4),
+ ['H'] = ((17 & 0x0F) << 4), ['m'] = ((22 & 0x0F) << 4),
+ ['I'] = ((18 & 0x0F) << 4), ['n'] = ((23 & 0x0F) << 4),
+ ['J'] = ((19 & 0x0F) << 4), ['o'] = ((24 & 0x0F) << 4),
+ ['K'] = ((20 & 0x0F) << 4), ['p'] = ((25 & 0x0F) << 4),
+ ['L'] = ((21 & 0x0F) << 4), ['q'] = ((26 & 0x0F) << 4),
+ ['M'] = ((22 & 0x0F) << 4), ['r'] = ((27 & 0x0F) << 4),
+ ['N'] = ((23 & 0x0F) << 4), ['s'] = ((28 & 0x0F) << 4),
+ ['O'] = ((24 & 0x0F) << 4), ['t'] = ((29 & 0x0F) << 4),
+ ['P'] = ((25 & 0x0F) << 4), ['u'] = ((30 & 0x0F) << 4),
+ ['Q'] = ((26 & 0x0F) << 4), ['v'] = ((31 & 0x0F) << 4),
+};
+
+// 0x1E = 00011110
+const uint8_t fifth_left_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x1E) >> 1), ['R'] = ((27 & 0x1E) >> 1),
+ ['1'] = (( 1 & 0x1E) >> 1), ['S'] = ((28 & 0x1E) >> 1),
+ ['2'] = (( 2 & 0x1E) >> 1), ['T'] = ((29 & 0x1E) >> 1),
+ ['3'] = (( 3 & 0x1E) >> 1), ['U'] = ((30 & 0x1E) >> 1),
+ ['4'] = (( 4 & 0x1E) >> 1), ['V'] = ((31 & 0x1E) >> 1),
+ ['5'] = (( 5 & 0x1E) >> 1), ['a'] = ((10 & 0x1E) >> 1),
+ ['6'] = (( 6 & 0x1E) >> 1), ['b'] = ((11 & 0x1E) >> 1),
+ ['7'] = (( 7 & 0x1E) >> 1), ['c'] = ((12 & 0x1E) >> 1),
+ ['8'] = (( 8 & 0x1E) >> 1), ['d'] = ((13 & 0x1E) >> 1),
+ ['9'] = (( 9 & 0x1E) >> 1), ['e'] = ((14 & 0x1E) >> 1),
+ ['A'] = ((10 & 0x1E) >> 1), ['f'] = ((15 & 0x1E) >> 1),
+ ['B'] = ((11 & 0x1E) >> 1), ['g'] = ((16 & 0x1E) >> 1),
+ ['C'] = ((12 & 0x1E) >> 1), ['h'] = ((17 & 0x1E) >> 1),
+ ['D'] = ((13 & 0x1E) >> 1), ['i'] = ((18 & 0x1E) >> 1),
+ ['E'] = ((14 & 0x1E) >> 1), ['j'] = ((19 & 0x1E) >> 1),
+ ['F'] = ((15 & 0x1E) >> 1), ['k'] = ((20 & 0x1E) >> 1),
+ ['G'] = ((16 & 0x1E) >> 1), ['l'] = ((21 & 0x1E) >> 1),
+ ['H'] = ((17 & 0x1E) >> 1), ['m'] = ((22 & 0x1E) >> 1),
+ ['I'] = ((18 & 0x1E) >> 1), ['n'] = ((23 & 0x1E) >> 1),
+ ['J'] = ((19 & 0x1E) >> 1), ['o'] = ((24 & 0x1E) >> 1),
+ ['K'] = ((20 & 0x1E) >> 1), ['p'] = ((25 & 0x1E) >> 1),
+ ['L'] = ((21 & 0x1E) >> 1), ['q'] = ((26 & 0x1E) >> 1),
+ ['M'] = ((22 & 0x1E) >> 1), ['r'] = ((27 & 0x1E) >> 1),
+ ['N'] = ((23 & 0x1E) >> 1), ['s'] = ((28 & 0x1E) >> 1),
+ ['O'] = ((24 & 0x1E) >> 1), ['t'] = ((29 & 0x1E) >> 1),
+ ['P'] = ((25 & 0x1E) >> 1), ['u'] = ((30 & 0x1E) >> 1),
+ ['Q'] = ((26 & 0x1E) >> 1), ['v'] = ((31 & 0x1E) >> 1),
+};
+
+// 0x01 = 00000001
+const uint8_t fifth_right_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x01) << 7), ['R'] = ((27 & 0x01) << 7),
+ ['1'] = (( 1 & 0x01) << 7), ['S'] = ((28 & 0x01) << 7),
+ ['2'] = (( 2 & 0x01) << 7), ['T'] = ((29 & 0x01) << 7),
+ ['3'] = (( 3 & 0x01) << 7), ['U'] = ((30 & 0x01) << 7),
+ ['4'] = (( 4 & 0x01) << 7), ['V'] = ((31 & 0x01) << 7),
+ ['5'] = (( 5 & 0x01) << 7), ['a'] = ((10 & 0x01) << 7),
+ ['6'] = (( 6 & 0x01) << 7), ['b'] = ((11 & 0x01) << 7),
+ ['7'] = (( 7 & 0x01) << 7), ['c'] = ((12 & 0x01) << 7),
+ ['8'] = (( 8 & 0x01) << 7), ['d'] = ((13 & 0x01) << 7),
+ ['9'] = (( 9 & 0x01) << 7), ['e'] = ((14 & 0x01) << 7),
+ ['A'] = ((10 & 0x01) << 7), ['f'] = ((15 & 0x01) << 7),
+ ['B'] = ((11 & 0x01) << 7), ['g'] = ((16 & 0x01) << 7),
+ ['C'] = ((12 & 0x01) << 7), ['h'] = ((17 & 0x01) << 7),
+ ['D'] = ((13 & 0x01) << 7), ['i'] = ((18 & 0x01) << 7),
+ ['E'] = ((14 & 0x01) << 7), ['j'] = ((19 & 0x01) << 7),
+ ['F'] = ((15 & 0x01) << 7), ['k'] = ((20 & 0x01) << 7),
+ ['G'] = ((16 & 0x01) << 7), ['l'] = ((21 & 0x01) << 7),
+ ['H'] = ((17 & 0x01) << 7), ['m'] = ((22 & 0x01) << 7),
+ ['I'] = ((18 & 0x01) << 7), ['n'] = ((23 & 0x01) << 7),
+ ['J'] = ((19 & 0x01) << 7), ['o'] = ((24 & 0x01) << 7),
+ ['K'] = ((20 & 0x01) << 7), ['p'] = ((25 & 0x01) << 7),
+ ['L'] = ((21 & 0x01) << 7), ['q'] = ((26 & 0x01) << 7),
+ ['M'] = ((22 & 0x01) << 7), ['r'] = ((27 & 0x01) << 7),
+ ['N'] = ((23 & 0x01) << 7), ['s'] = ((28 & 0x01) << 7),
+ ['O'] = ((24 & 0x01) << 7), ['t'] = ((29 & 0x01) << 7),
+ ['P'] = ((25 & 0x01) << 7), ['u'] = ((30 & 0x01) << 7),
+ ['Q'] = ((26 & 0x01) << 7), ['v'] = ((31 & 0x01) << 7),
+};
+
+// 0x1F = 00011111
+const uint8_t sixth_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x1F) << 2), ['R'] = ((27 & 0x1F) << 2),
+ ['1'] = (( 1 & 0x1F) << 2), ['S'] = ((28 & 0x1F) << 2),
+ ['2'] = (( 2 & 0x1F) << 2), ['T'] = ((29 & 0x1F) << 2),
+ ['3'] = (( 3 & 0x1F) << 2), ['U'] = ((30 & 0x1F) << 2),
+ ['4'] = (( 4 & 0x1F) << 2), ['V'] = ((31 & 0x1F) << 2),
+ ['5'] = (( 5 & 0x1F) << 2), ['a'] = ((10 & 0x1F) << 2),
+ ['6'] = (( 6 & 0x1F) << 2), ['b'] = ((11 & 0x1F) << 2),
+ ['7'] = (( 7 & 0x1F) << 2), ['c'] = ((12 & 0x1F) << 2),
+ ['8'] = (( 8 & 0x1F) << 2), ['d'] = ((13 & 0x1F) << 2),
+ ['9'] = (( 9 & 0x1F) << 2), ['e'] = ((14 & 0x1F) << 2),
+ ['A'] = ((10 & 0x1F) << 2), ['f'] = ((15 & 0x1F) << 2),
+ ['B'] = ((11 & 0x1F) << 2), ['g'] = ((16 & 0x1F) << 2),
+ ['C'] = ((12 & 0x1F) << 2), ['h'] = ((17 & 0x1F) << 2),
+ ['D'] = ((13 & 0x1F) << 2), ['i'] = ((18 & 0x1F) << 2),
+ ['E'] = ((14 & 0x1F) << 2), ['j'] = ((19 & 0x1F) << 2),
+ ['F'] = ((15 & 0x1F) << 2), ['k'] = ((20 & 0x1F) << 2),
+ ['G'] = ((16 & 0x1F) << 2), ['l'] = ((21 & 0x1F) << 2),
+ ['H'] = ((17 & 0x1F) << 2), ['m'] = ((22 & 0x1F) << 2),
+ ['I'] = ((18 & 0x1F) << 2), ['n'] = ((23 & 0x1F) << 2),
+ ['J'] = ((19 & 0x1F) << 2), ['o'] = ((24 & 0x1F) << 2),
+ ['K'] = ((20 & 0x1F) << 2), ['p'] = ((25 & 0x1F) << 2),
+ ['L'] = ((21 & 0x1F) << 2), ['q'] = ((26 & 0x1F) << 2),
+ ['M'] = ((22 & 0x1F) << 2), ['r'] = ((27 & 0x1F) << 2),
+ ['N'] = ((23 & 0x1F) << 2), ['s'] = ((28 & 0x1F) << 2),
+ ['O'] = ((24 & 0x1F) << 2), ['t'] = ((29 & 0x1F) << 2),
+ ['P'] = ((25 & 0x1F) << 2), ['u'] = ((30 & 0x1F) << 2),
+ ['Q'] = ((26 & 0x1F) << 2), ['v'] = ((31 & 0x1F) << 2),
+};
+
+// 0x18 = 00011000
+const uint8_t seventh_left_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x18) >> 3), ['R'] = ((27 & 0x18) >> 3),
+ ['1'] = (( 1 & 0x18) >> 3), ['S'] = ((28 & 0x18) >> 3),
+ ['2'] = (( 2 & 0x18) >> 3), ['T'] = ((29 & 0x18) >> 3),
+ ['3'] = (( 3 & 0x18) >> 3), ['U'] = ((30 & 0x18) >> 3),
+ ['4'] = (( 4 & 0x18) >> 3), ['V'] = ((31 & 0x18) >> 3),
+ ['5'] = (( 5 & 0x18) >> 3), ['a'] = ((10 & 0x18) >> 3),
+ ['6'] = (( 6 & 0x18) >> 3), ['b'] = ((11 & 0x18) >> 3),
+ ['7'] = (( 7 & 0x18) >> 3), ['c'] = ((12 & 0x18) >> 3),
+ ['8'] = (( 8 & 0x18) >> 3), ['d'] = ((13 & 0x18) >> 3),
+ ['9'] = (( 9 & 0x18) >> 3), ['e'] = ((14 & 0x18) >> 3),
+ ['A'] = ((10 & 0x18) >> 3), ['f'] = ((15 & 0x18) >> 3),
+ ['B'] = ((11 & 0x18) >> 3), ['g'] = ((16 & 0x18) >> 3),
+ ['C'] = ((12 & 0x18) >> 3), ['h'] = ((17 & 0x18) >> 3),
+ ['D'] = ((13 & 0x18) >> 3), ['i'] = ((18 & 0x18) >> 3),
+ ['E'] = ((14 & 0x18) >> 3), ['j'] = ((19 & 0x18) >> 3),
+ ['F'] = ((15 & 0x18) >> 3), ['k'] = ((20 & 0x18) >> 3),
+ ['G'] = ((16 & 0x18) >> 3), ['l'] = ((21 & 0x18) >> 3),
+ ['H'] = ((17 & 0x18) >> 3), ['m'] = ((22 & 0x18) >> 3),
+ ['I'] = ((18 & 0x18) >> 3), ['n'] = ((23 & 0x18) >> 3),
+ ['J'] = ((19 & 0x18) >> 3), ['o'] = ((24 & 0x18) >> 3),
+ ['K'] = ((20 & 0x18) >> 3), ['p'] = ((25 & 0x18) >> 3),
+ ['L'] = ((21 & 0x18) >> 3), ['q'] = ((26 & 0x18) >> 3),
+ ['M'] = ((22 & 0x18) >> 3), ['r'] = ((27 & 0x18) >> 3),
+ ['N'] = ((23 & 0x18) >> 3), ['s'] = ((28 & 0x18) >> 3),
+ ['O'] = ((24 & 0x18) >> 3), ['t'] = ((29 & 0x18) >> 3),
+ ['P'] = ((25 & 0x18) >> 3), ['u'] = ((30 & 0x18) >> 3),
+ ['Q'] = ((26 & 0x18) >> 3), ['v'] = ((31 & 0x18) >> 3),
+};
+
+// 0x07 = 00000111
+const uint8_t seventh_right_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x07) << 5), ['R'] = ((27 & 0x07) << 5),
+ ['1'] = (( 1 & 0x07) << 5), ['S'] = ((28 & 0x07) << 5),
+ ['2'] = (( 2 & 0x07) << 5), ['T'] = ((29 & 0x07) << 5),
+ ['3'] = (( 3 & 0x07) << 5), ['U'] = ((30 & 0x07) << 5),
+ ['4'] = (( 4 & 0x07) << 5), ['V'] = ((31 & 0x07) << 5),
+ ['5'] = (( 5 & 0x07) << 5), ['a'] = ((10 & 0x07) << 5),
+ ['6'] = (( 6 & 0x07) << 5), ['b'] = ((11 & 0x07) << 5),
+ ['7'] = (( 7 & 0x07) << 5), ['c'] = ((12 & 0x07) << 5),
+ ['8'] = (( 8 & 0x07) << 5), ['d'] = ((13 & 0x07) << 5),
+ ['9'] = (( 9 & 0x07) << 5), ['e'] = ((14 & 0x07) << 5),
+ ['A'] = ((10 & 0x07) << 5), ['f'] = ((15 & 0x07) << 5),
+ ['B'] = ((11 & 0x07) << 5), ['g'] = ((16 & 0x07) << 5),
+ ['C'] = ((12 & 0x07) << 5), ['h'] = ((17 & 0x07) << 5),
+ ['D'] = ((13 & 0x07) << 5), ['i'] = ((18 & 0x07) << 5),
+ ['E'] = ((14 & 0x07) << 5), ['j'] = ((19 & 0x07) << 5),
+ ['F'] = ((15 & 0x07) << 5), ['k'] = ((20 & 0x07) << 5),
+ ['G'] = ((16 & 0x07) << 5), ['l'] = ((21 & 0x07) << 5),
+ ['H'] = ((17 & 0x07) << 5), ['m'] = ((22 & 0x07) << 5),
+ ['I'] = ((18 & 0x07) << 5), ['n'] = ((23 & 0x07) << 5),
+ ['J'] = ((19 & 0x07) << 5), ['o'] = ((24 & 0x07) << 5),
+ ['K'] = ((20 & 0x07) << 5), ['p'] = ((25 & 0x07) << 5),
+ ['L'] = ((21 & 0x07) << 5), ['q'] = ((26 & 0x07) << 5),
+ ['M'] = ((22 & 0x07) << 5), ['r'] = ((27 & 0x07) << 5),
+ ['N'] = ((23 & 0x07) << 5), ['s'] = ((28 & 0x07) << 5),
+ ['O'] = ((24 & 0x07) << 5), ['t'] = ((29 & 0x07) << 5),
+ ['P'] = ((25 & 0x07) << 5), ['u'] = ((30 & 0x07) << 5),
+ ['Q'] = ((26 & 0x07) << 5), ['v'] = ((31 & 0x07) << 5),
+};
+
+// 0x1F = 00011111
+const uint8_t eighth_base32hex_to_num[] = {
+ ['0'] = (( 0 & 0x1F) << 0), ['R'] = ((27 & 0x1F) << 0),
+ ['1'] = (( 1 & 0x1F) << 0), ['S'] = ((28 & 0x1F) << 0),
+ ['2'] = (( 2 & 0x1F) << 0), ['T'] = ((29 & 0x1F) << 0),
+ ['3'] = (( 3 & 0x1F) << 0), ['U'] = ((30 & 0x1F) << 0),
+ ['4'] = (( 4 & 0x1F) << 0), ['V'] = ((31 & 0x1F) << 0),
+ ['5'] = (( 5 & 0x1F) << 0), ['a'] = ((10 & 0x1F) << 0),
+ ['6'] = (( 6 & 0x1F) << 0), ['b'] = ((11 & 0x1F) << 0),
+ ['7'] = (( 7 & 0x1F) << 0), ['c'] = ((12 & 0x1F) << 0),
+ ['8'] = (( 8 & 0x1F) << 0), ['d'] = ((13 & 0x1F) << 0),
+ ['9'] = (( 9 & 0x1F) << 0), ['e'] = ((14 & 0x1F) << 0),
+ ['A'] = ((10 & 0x1F) << 0), ['f'] = ((15 & 0x1F) << 0),
+ ['B'] = ((11 & 0x1F) << 0), ['g'] = ((16 & 0x1F) << 0),
+ ['C'] = ((12 & 0x1F) << 0), ['h'] = ((17 & 0x1F) << 0),
+ ['D'] = ((13 & 0x1F) << 0), ['i'] = ((18 & 0x1F) << 0),
+ ['E'] = ((14 & 0x1F) << 0), ['j'] = ((19 & 0x1F) << 0),
+ ['F'] = ((15 & 0x1F) << 0), ['k'] = ((20 & 0x1F) << 0),
+ ['G'] = ((16 & 0x1F) << 0), ['l'] = ((21 & 0x1F) << 0),
+ ['H'] = ((17 & 0x1F) << 0), ['m'] = ((22 & 0x1F) << 0),
+ ['I'] = ((18 & 0x1F) << 0), ['n'] = ((23 & 0x1F) << 0),
+ ['J'] = ((19 & 0x1F) << 0), ['o'] = ((24 & 0x1F) << 0),
+ ['K'] = ((20 & 0x1F) << 0), ['p'] = ((25 & 0x1F) << 0),
+ ['L'] = ((21 & 0x1F) << 0), ['q'] = ((26 & 0x1F) << 0),
+ ['M'] = ((22 & 0x1F) << 0), ['r'] = ((27 & 0x1F) << 0),
+ ['N'] = ((23 & 0x1F) << 0), ['s'] = ((28 & 0x1F) << 0),
+ ['O'] = ((24 & 0x1F) << 0), ['t'] = ((29 & 0x1F) << 0),
+ ['P'] = ((25 & 0x1F) << 0), ['u'] = ((30 & 0x1F) << 0),
+ ['Q'] = ((26 & 0x1F) << 0), ['v'] = ((31 & 0x1F) << 0),
+};
+
+// Without leap day 29. 2.
+static const uint8_t days_in_months[] = {
+ [ 1] = 31, [ 2] = 28, [ 3] = 31, [ 4] = 30, [ 5] = 31, [ 6] = 30,
+ [ 7] = 31, [ 8] = 31, [ 9] = 30, [10] = 31, [11] = 30, [12] = 31,
+};
+
+// Without leap day 29. 2.
+static const uint16_t days_across_months[] = {
+ [ 1] = 0, [ 2] = 31, [ 3] = 59, [ 4] = 90, [ 5] = 120, [ 6] = 151,
+ [ 7] = 181, [ 8] = 212, [ 9] = 243, [10] = 273, [11] = 304, [12] = 334,
+};
+
+// 0 ~ 1970 ... 135 ~ 2105
+static const uint8_t is_leap_year[] = {
+ [ 1] = 0, [ 2] = 1, [ 3] = 0, [ 4] = 0, [ 5] = 0,
+ [ 6] = 1, [ 7] = 0, [ 8] = 0, [ 9] = 0, [ 10] = 1,
+ [ 11] = 0, [ 12] = 0, [ 13] = 0, [ 14] = 1, [ 15] = 0,
+ [ 16] = 0, [ 17] = 0, [ 18] = 1, [ 19] = 0, [ 20] = 0,
+ [ 21] = 0, [ 22] = 1, [ 23] = 0, [ 24] = 0, [ 25] = 0,
+ [ 26] = 1, [ 27] = 0, [ 28] = 0, [ 29] = 0, [ 30] = 1,
+ [ 31] = 0, [ 32] = 0, [ 33] = 0, [ 34] = 1, [ 35] = 0,
+ [ 36] = 0, [ 37] = 0, [ 38] = 1, [ 39] = 0, [ 40] = 0,
+ [ 41] = 0, [ 42] = 1, [ 43] = 0, [ 44] = 0, [ 45] = 0,
+ [ 46] = 1, [ 47] = 0, [ 48] = 0, [ 49] = 0, [ 50] = 1,
+ [ 51] = 0, [ 52] = 0, [ 53] = 0, [ 54] = 1, [ 55] = 0,
+ [ 56] = 0, [ 57] = 0, [ 58] = 1, [ 59] = 0, [ 60] = 0,
+ [ 61] = 0, [ 62] = 1, [ 63] = 0, [ 64] = 0, [ 65] = 0,
+ [ 66] = 1, [ 67] = 0, [ 68] = 0, [ 69] = 0, [ 70] = 1,
+ [ 71] = 0, [ 72] = 0, [ 73] = 0, [ 74] = 1, [ 75] = 0,
+ [ 76] = 0, [ 77] = 0, [ 78] = 1, [ 79] = 0, [ 80] = 0,
+ [ 81] = 0, [ 82] = 1, [ 83] = 0, [ 84] = 0, [ 85] = 0,
+ [ 86] = 1, [ 87] = 0, [ 88] = 0, [ 89] = 0, [ 90] = 1,
+ [ 91] = 0, [ 92] = 0, [ 93] = 0, [ 94] = 1, [ 95] = 0,
+ [ 96] = 0, [ 97] = 0, [ 98] = 1, [ 99] = 0, [100] = 0,
+ [101] = 0, [102] = 1, [103] = 0, [104] = 0, [105] = 0,
+ [106] = 1, [107] = 0, [108] = 0, [109] = 0, [110] = 1,
+ [111] = 0, [112] = 0, [113] = 0, [114] = 1, [115] = 0,
+ [116] = 0, [117] = 0, [118] = 1, [119] = 0, [120] = 0,
+ [121] = 0, [122] = 1, [123] = 0, [124] = 0, [125] = 0,
+ [126] = 1, [127] = 0, [128] = 0, [129] = 0, [130] = 0,
+ [131] = 0, [132] = 0, [133] = 0, [134] = 1, [135] = 0,
+};
+
+// 0 ~ 1970 ... 135 ~ 2105
+static const uint16_t days_across_years[] = {
+ [ 1] = 365, [ 2] = 730, [ 3] = 1096, [ 4] = 1461, [ 5] = 1826,
+ [ 6] = 2191, [ 7] = 2557, [ 8] = 2922, [ 9] = 3287, [ 10] = 3652,
+ [ 11] = 4018, [ 12] = 4383, [ 13] = 4748, [ 14] = 5113, [ 15] = 5479,
+ [ 16] = 5844, [ 17] = 6209, [ 18] = 6574, [ 19] = 6940, [ 20] = 7305,
+ [ 21] = 7670, [ 22] = 8035, [ 23] = 8401, [ 24] = 8766, [ 25] = 9131,
+ [ 26] = 9496, [ 27] = 9862, [ 28] = 10227, [ 29] = 10592, [ 30] = 10957,
+ [ 31] = 11323, [ 32] = 11688, [ 33] = 12053, [ 34] = 12418, [ 35] = 12784,
+ [ 36] = 13149, [ 37] = 13514, [ 38] = 13879, [ 39] = 14245, [ 40] = 14610,
+ [ 41] = 14975, [ 42] = 15340, [ 43] = 15706, [ 44] = 16071, [ 45] = 16436,
+ [ 46] = 16801, [ 47] = 17167, [ 48] = 17532, [ 49] = 17897, [ 50] = 18262,
+ [ 51] = 18628, [ 52] = 18993, [ 53] = 19358, [ 54] = 19723, [ 55] = 20089,
+ [ 56] = 20454, [ 57] = 20819, [ 58] = 21184, [ 59] = 21550, [ 60] = 21915,
+ [ 61] = 22280, [ 62] = 22645, [ 63] = 23011, [ 64] = 23376, [ 65] = 23741,
+ [ 66] = 24106, [ 67] = 24472, [ 68] = 24837, [ 69] = 25202, [ 70] = 25567,
+ [ 71] = 25933, [ 72] = 26298, [ 73] = 26663, [ 74] = 27028, [ 75] = 27394,
+ [ 76] = 27759, [ 77] = 28124, [ 78] = 28489, [ 79] = 28855, [ 80] = 29220,
+ [ 81] = 29585, [ 82] = 29950, [ 83] = 30316, [ 84] = 30681, [ 85] = 31046,
+ [ 86] = 31411, [ 87] = 31777, [ 88] = 32142, [ 89] = 32507, [ 90] = 32872,
+ [ 91] = 33238, [ 92] = 33603, [ 93] = 33968, [ 94] = 34333, [ 95] = 34699,
+ [ 96] = 35064, [ 97] = 35429, [ 98] = 35794, [ 99] = 36160, [100] = 36525,
+ [101] = 36890, [102] = 37255, [103] = 37621, [104] = 37986, [105] = 38351,
+ [106] = 38716, [107] = 39082, [108] = 39447, [109] = 39812, [110] = 40177,
+ [111] = 40543, [112] = 40908, [113] = 41273, [114] = 41638, [115] = 42004,
+ [116] = 42369, [117] = 42734, [118] = 43099, [119] = 43465, [120] = 43830,
+ [121] = 44195, [122] = 44560, [123] = 44926, [124] = 45291, [125] = 45656,
+ [126] = 46021, [127] = 46387, [128] = 46752, [129] = 47117, [130] = 47482,
+ [131] = 47847, [132] = 48212, [133] = 48577, [134] = 48942, [135] = 49308,
+};
+
+int date_to_timestamp(uint8_t *buff, uint32_t *timestamp)
+{
+ uint32_t year, month, day, hour, minute, second;
+ uint32_t leap_day = 0;
+
+ year = 1000 * (buff[ 0] - '0') + 100 * (buff[ 1] - '0') +
+ 10 * (buff[ 2] - '0') + (buff[ 3] - '0');
+ month = 10 * (buff[ 4] - '0') + (buff[ 5] - '0');
+ day = 10 * (buff[ 6] - '0') + (buff[ 7] - '0');
+ hour = 10 * (buff[ 8] - '0') + (buff[ 9] - '0');
+ minute = 10 * (buff[10] - '0') + (buff[11] - '0');
+ second = 10 * (buff[12] - '0') + (buff[13] - '0');
+
+ if (year < 1970 || year > 2105 || month < 1 || month > 12 || day < 1) {
+ return ZSCANNER_EBAD_DATE;
+ } else {
+ year -= 1970;
+ }
+
+ if (is_leap_year[year]) {
+ if (month > 2) {
+ leap_day = 1; // Add one day in case of leap year.
+ } else if (month == 2 &&
+ day > (uint32_t)(days_in_months[month] + 1)) {
+ return ZSCANNER_EBAD_DATE;
+ }
+ } else if (day > days_in_months[month]){
+ return ZSCANNER_EBAD_DATE;
+ }
+
+ if (hour > 23 || minute > 59 || second > 59) {
+ return ZSCANNER_EBAD_TIME;
+ }
+
+ *timestamp = hour * 3600 + minute * 60 + second +
+ (days_across_years[year] +
+ days_across_months[month] +
+ day - 1 + leap_day) * 86400;
+
+ return KNOT_EOK;
+}
+
+void wire_dname_to_str(const uint8_t *data,
+ const uint32_t data_len,
+ char *text)
+{
+ uint32_t i = 0, text_len = 0;
+
+ if (data == NULL || data_len == 0 || text == NULL) {
+ return;
+ }
+
+ uint8_t label_len = data[0];
+
+ // Loop over data characters.
+ for (i = 1; i < data_len; i++) {
+ // Replace label length with dot.
+ if (label_len == 0) {
+ label_len = data[i];
+ text[text_len++] = '.';
+ continue;
+ }
+
+ // Just in case use \123 notation.
+ text[text_len++] = '\\';
+ text[text_len++] = (data[i] / 100) + ASCII_0;
+ text[text_len++] = (data[i] / 10) % 10 + ASCII_0;
+ text[text_len++] = (data[i] ) % 10 + ASCII_0;
+
+ label_len--;
+ }
+
+ // Add trailing dot for root domain.
+ if (data_len == 1 && label_len == 0) {
+ text[text_len++] = '.';
+ }
+
+ // Ending text string.
+ text[text_len] = 0;
+}
+
+uint8_t loc64to8(uint64_t number)
+{
+ uint8_t exponent = 0;
+
+ while (number > 9) {
+ number /= 10;
+ exponent++;
+ }
+ // First 4 bits are mantisa, second 4 bits are exponent.
+ return ((uint8_t)number << 4) + (exponent & 15);
+}
+
+/*!
+ * \brief Returns domain name length in wire-format.
+ *
+ * \param data Data array.
+ * \param data_len Length of data array.
+ *
+ * \retval >0 if success.
+ * \retval 0 if error.
+ */
+static uint32_t get_dname_length(const uint8_t *data,
+ const uint32_t data_len)
+{
+ uint8_t label_len = data[0];
+ uint32_t dname_len = 0;
+
+ while (label_len > 0) {
+ // Label overflow check.
+ if (label_len > MAX_LABEL_LENGTH) {
+ return 0;
+ }
+
+ dname_len += 1 + label_len;
+
+ // Data overflow check.
+ if (dname_len > data_len) {
+ return 0;
+ }
+
+ label_len = data[dname_len];
+ }
+
+ dname_len++; // Last label length byte.
+
+ // Dname overflow check.
+ if (dname_len <= MAX_DNAME_LENGTH) {
+ return dname_len;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ * \brief Returns length of the leading NAPTR block in wire-format.
+ *
+ * \param data Data array.
+ * \param data_len Length of data array.
+ *
+ * \retval >0 if success.
+ * \retval 0 if error.
+ */
+static uint32_t get_naptr_header_length(const uint8_t *data,
+ const uint32_t data_len)
+{
+ uint32_t naptr_len = 0;
+
+ // 2B order + 2B preference.
+ naptr_len += 2 + 2;
+
+ // Flags - text string with forward 1B length.
+ naptr_len += data[naptr_len] + 1;
+
+ // Services - text string with forward 1B length.
+ naptr_len += data[naptr_len] + 1;
+
+ // Regexp - text string with forward 1B length.
+ naptr_len += data[naptr_len] + 1;
+
+ // Data overflow check.
+ if (naptr_len <= data_len) {
+ return naptr_len;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ * \brief Returns block length in wire-format.
+ *
+ * \param data Data array.
+ * \param data_len Length of data array.
+ * \param offset Start of the block in data array.
+ * \param type Record type.
+ *
+ * \retval >=0 if success.
+ * \retval <0 if error.
+ */
+static int32_t get_block_length(const uint8_t *data,
+ const uint32_t data_len,
+ const uint32_t offset,
+ const int type)
+{
+ uint32_t ret;
+
+ switch (type) {
+ case KNOT_RDATA_WF_COMPRESSED_DNAME:
+ case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
+ case KNOT_RDATA_WF_LITERAL_DNAME:
+ ret = get_dname_length(data + offset, data_len - offset);
+
+ if (ret > 0) {
+ return ret;
+ } else {
+ return -1;
+ }
+ case KNOT_RDATA_WF_NAPTR_HEADER:
+ ret = get_naptr_header_length(data + offset, data_len - offset);
+
+ if (ret > 0) {
+ return ret;
+ } else {
+ return -1;
+ }
+ case KNOT_RDATA_WF_REMAINDER:
+ return data_len - offset;
+ default:
+ return 0;
+ }
+}
+
+int find_rdata_blocks(scanner_t *s)
+{
+ int32_t ret;
+ uint32_t position = 0;
+
+ // Initialization of block items.
+ s->r_data_blocks_count = 0;
+ s->r_data_blocks[0] = 0;
+
+ // Getting appropriate descriptor array.
+ const rdata_descriptor_t *descriptor = get_rdata_descriptor(s->r_type);
+ const int *type = descriptor->block_types;
+
+ // Loop over descriptor array.
+ while (*type != KNOT_RDATA_WF_END) {
+ if (*type > KNOT_RDATA_WF_END) {
+ position += *type;
+ } else {
+ ret = get_block_length(s->r_data,
+ s->r_data_length,
+ position,
+ *type);
+ if (ret < 0) {
+ return ZSCANNER_EUNKNOWN_BLOCK;
+ }
+
+ position += ret;
+ }
+ s->r_data_blocks[++(s->r_data_blocks_count)] = position;
+ type++;
+ }
+
+ // Checking processed rdata length.
+ if (s->r_data_blocks[s->r_data_blocks_count] != s->r_data_length) {
+ return ZSCANNER_EBAD_HEX_RDATA;
+ }
+ else {
+ return KNOT_EOK;
+ }
+}
diff --git a/src/zscanner/scanner_functions.h b/src/zscanner/scanner_functions.h
new file mode 100644
index 0000000..5d219d7
--- /dev/null
+++ b/src/zscanner/scanner_functions.h
@@ -0,0 +1,127 @@
+/* Copyright (C) 2011 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 scanner_functions.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Zone scanner auxiliary functions.
+ *
+ * \addtogroup zone_scanner
+ * @{
+ */
+
+#ifndef _ZSCANNER__SCANNER_FUNCTIONS_H_
+#define _ZSCANNER__SCANNER_FUNCTIONS_H_
+
+#include <stdint.h>
+
+#include "zscanner/scanner.h"
+
+/*! \brief Transforms digit char to number. */
+extern const uint8_t digit_to_num[];
+
+/*! \brief Transforms first hex char to the part of the total number. */
+extern const uint8_t first_hex_to_num[];
+/*! \brief Transforms second hex char to the part of the total number. */
+extern const uint8_t second_hex_to_num[];
+
+/*! \brief Transforms first Base64 char. */
+extern const uint8_t first_base64_to_num[];
+/*! \brief Transforms left part of the second Base64 char. */
+extern const uint8_t second_left_base64_to_num[];
+/*! \brief Transforms left part of the second Base64 char. */
+extern const uint8_t second_right_base64_to_num[];
+/*! \brief Transforms left part of the third Base64 char. */
+extern const uint8_t third_left_base64_to_num[];
+/*! \brief Transforms left part of the third Base64 char. */
+extern const uint8_t third_right_base64_to_num[];
+/*! \brief Transforms fourth Base64 char. */
+extern const uint8_t fourth_base64_to_num[];
+
+/*! \brief Transforms first Base32hex char. */
+extern const uint8_t first_base32hex_to_num[];
+/*! \brief Transforms left part of the second Base32hex char. */
+extern const uint8_t second_left_base32hex_to_num[];
+/*! \brief Transforms right part of the second Base32hex char. */
+extern const uint8_t second_right_base32hex_to_num[];
+/*! \brief Transforms third Base32hex char. */
+extern const uint8_t third_base32hex_to_num[];
+/*! \brief Transforms left part of the fourth Base32hex char. */
+extern const uint8_t fourth_left_base32hex_to_num[];
+/*! \brief Transforms right part of the fourth Base32hex char. */
+extern const uint8_t fourth_right_base32hex_to_num[];
+/*! \brief Transforms left part of the fifth Base32hex char. */
+extern const uint8_t fifth_left_base32hex_to_num[];
+/*! \brief Transforms right part of the fifth Base32hex char. */
+extern const uint8_t fifth_right_base32hex_to_num[];
+/*! \brief Transforms sixth Base32hex char. */
+extern const uint8_t sixth_base32hex_to_num[];
+/*! \brief Transforms left part of the seventh Base32hex char. */
+extern const uint8_t seventh_left_base32hex_to_num[];
+/*! \brief Transforms right part of the seventh Base32hex char. */
+extern const uint8_t seventh_right_base32hex_to_num[];
+/*! \brief Transforms eighth Base32hex char. */
+extern const uint8_t eighth_base32hex_to_num[];
+
+/*!
+ * \brief Converts YYYYMMDDHHMMSS time string to unsigned 32-bit timestamp.
+ *
+ * \param buff Buffer containing time string.
+ * \param timestamp Computed timestamp.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval error_code if error.
+ */
+int date_to_timestamp(uint8_t *buff, uint32_t *timestamp);
+
+/*!
+ * \brief Converts wire-format dname to text dname.
+ *
+ * \param data Buffer containg wire-format dname.
+ * \param data_len Length of the buffer.
+ * \param text Text output.
+ */
+void wire_dname_to_str(const uint8_t *data,
+ const uint32_t data_len,
+ char *text);
+
+/*!
+ * \brief Converts unsigned integer to mantisa*10^(exponent).
+ *
+ * Given number is encoded as two 4-bit numbers. First part is mantisa [0-9],
+ * second part is decimal exponent [0-15]. Result is concatenation of these
+ * two blocks.
+ *
+ * \param number Number to convert.
+ *
+ * \retval number encoded number.
+ */
+uint8_t loc64to8(uint64_t number);
+
+/*!
+ * \brief Finds rdata blocks according to rdata descriptors.
+ *
+ * \param s Zone scanner.
+ *
+ * \retval KNOT_EOK if success.
+ * \retval error_code if error.
+ */
+int find_rdata_blocks(scanner_t *s);
+
+#endif // _ZSCANNER__SCANNER_FUNCTIONS_H_
+
+/*! @} */
diff --git a/src/zscanner/test/cases/00_general.in b/src/zscanner/test/cases/00_general.in
new file mode 100644
index 0000000..de9c3f0
--- /dev/null
+++ b/src/zscanner/test/cases/00_general.in
@@ -0,0 +1,24 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+t01 IN 10 NS @ ; All items are mentioned
+ IN 10 NS @ ; Same as above without OWNER
+t02 20 IN NS @ ; Switched CLASS and TTL
+ 20 IN NS @ ; Same as above without OWNER
+t03 30 NS @ ; Missing CLASS
+ 30 NS @ ; Same as above without OWNER
+t04 IN NS @ ; Missing TTL
+ IN NS @ ; Same as above without OWNER
+t05 NS @ ; Missing CLASS and TTL
+ NS @ ; Same as above without OWNER
+
+@ ( ) NS ( ; Multiline 1/5
+ ) () ( ; Multiline 2/5
+
+ @ ; Multiline 4/5
+ ) (
+) ; Multiline 6/6
+
+; KO
+@ NS ((@)) ; Nested parentheses - ERROR = STOP PROCESSING!
diff --git a/src/zscanner/test/cases/00_general.out b/src/zscanner/test/cases/00_general.out
new file mode 100644
index 0000000..c9c6a43
--- /dev/null
+++ b/src/zscanner/test/cases/00_general.out
@@ -0,0 +1,68 @@
+OWNER=0374303100
+CLASS=0001
+RRTTL=0000000A
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303100
+CLASS=0001
+RRTTL=0000000A
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303200
+CLASS=0001
+RRTTL=00000014
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303200
+CLASS=0001
+RRTTL=00000014
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303300
+CLASS=0001
+RRTTL=0000001E
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303300
+CLASS=0001
+RRTTL=0000001E
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303500
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0374303500
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+ERROR=ZSCANNER_ELEFT_PARENTHESIS
+------
diff --git a/src/zscanner/test/cases/01_owner.in b/src/zscanner/test/cases/01_owner.in
new file mode 100644
index 0000000..2cb148e
--- /dev/null
+++ b/src/zscanner/test/cases/01_owner.in
@@ -0,0 +1,34 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+. NS @ ; The simplest owner
+tld. NS @ ; FQD tld owner
+tld NS @ ; Relative form
+ NS @ ; The previous owner
+*. NS @ ; FQD with asterisk
+* NS @ ; Alone asterisk
+*.* NS @ ; More asterisks
+@ NS @ ; Use origin
+0123456789 NS @ ; Digits
+_a_.-b-c-./d/. NS @ ; Allowed characters '_' '-' '/' anywhere
+ABCDEFGHIJKLMNOPQRSTUVWXYZ NS @ ; All upper-case letters
+abcdefghijklmnopqrstuvwxyz NS @ ; All lower-case letters
+\000\0320\ \\\"\.\@\*.tld. NS @ ; Label with special chars
+b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. NS @ ; IPv6 reverse
+12345678901234567890123456789012345678901234567890123456789012\051.tld. NS @ ; Label of maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901. NS @ ; Domain name of maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901 NS @ ; Domain name of maximal length (after appending origin)
+
+; KO
+& NS @ ; Bad (unslashed) character
+a*a NS @ ; * char can substitute whole label only
+ NS @ ; Bad previous
+.a NS @ ; Leading dot
+@@ NS @ ; Double @@
+.. NS @ ; Missing label between dots
+\1 NS @ ; Slash notation requires 3 digits
+\12 NS @ ; Slash notation requires 3 digits
+12345678901234567890123456789012345678901234567890123456789012\0514.tld. NS @ ; Label exceeded maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012. NS @ ; Domain name exceeded maximal length
+123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012 NS @ ; Domain name exceeded maximal length (after appending origin)
diff --git a/src/zscanner/test/cases/01_owner.out b/src/zscanner/test/cases/01_owner.out
new file mode 100644
index 0000000..d68d468
--- /dev/null
+++ b/src/zscanner/test/cases/01_owner.out
@@ -0,0 +1,124 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=012A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=012A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=012A012A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0A3031323334353637383900
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=035F615F052D622D632D032F642F00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=1A4142434445464748494A4B4C4D4E4F505152535455565758595A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=1A6162636465666768696A6B6C6D6E6F707172737475767778797A00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=09002030205C222E402A03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_OWNER
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_PREVIOUS_OWNER
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ELABEL_OVERFLOW
+------
+WARNG=ZSCANNER_EDNAME_OVERFLOW
+------
+WARNG=ZSCANNER_EDNAME_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/02_class.in b/src/zscanner/test/cases/02_class.in
new file mode 100644
index 0000000..c4347e7
--- /dev/null
+++ b/src/zscanner/test/cases/02_class.in
@@ -0,0 +1,10 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ IN NS @ ; The only accepted class IN
+@ in NS @ ; Class in lower-case
+
+; KO
+@ CH NS @ ; Unsupported class
+@ CLASS1 NS @ ; Unsupported notation
diff --git a/src/zscanner/test/cases/02_class.out b/src/zscanner/test/cases/02_class.out
new file mode 100644
index 0000000..6002cc3
--- /dev/null
+++ b/src/zscanner/test/cases/02_class.out
@@ -0,0 +1,16 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZSCANNER_EUNSUPPORTED_TYPE
+------
+WARNG=ZSCANNER_EUNSUPPORTED_TYPE
+------
diff --git a/src/zscanner/test/cases/03_rrttl.in b/src/zscanner/test/cases/03_rrttl.in
new file mode 100644
index 0000000..7c57d73
--- /dev/null
+++ b/src/zscanner/test/cases/03_rrttl.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ 0 NS @ ; Minimal ttl
+@ 3600 NS @ ; Inner value
+@ 4294967295 NS @ ; Maximal ttl
+@ 1S NS @ ; 1 second (upper-case)
+@ 1s NS @ ; 1 second (lower-case)
+@ 1M NS @ ; 1 minute (upper-case)
+@ 1m NS @ ; 1 minute (lower-case)
+@ 1H NS @ ; 1 hour (upper-case)
+@ 1h NS @ ; 1 hour (lower-case)
+@ 1D NS @ ; 1 day (upper-case)
+@ 1d NS @ ; 1 day (lower-case)
+@ 1W NS @ ; 1 week (upper-case)
+@ 1w NS @ ; 1 week (lower-case)
+@ 1w1d1h1m1s NS @ ; More time units
+@ 1s1m1m NS @ ; Same time units, non decreasing order
+
+; KO
+@ -1 NS @ ; Negative ttl
+@ 4294967296 NS @ ; 32bit overflow
+@ 100000000W NS @ ; 32bit overflow
+@ 4294967295s1w NS @ ; 32bit overflow
+@ 1x NS @ ; Unknown time unit
diff --git a/src/zscanner/test/cases/03_rrttl.out b/src/zscanner/test/cases/03_rrttl.out
new file mode 100644
index 0000000..bdc0b6e
--- /dev/null
+++ b/src/zscanner/test/cases/03_rrttl.out
@@ -0,0 +1,100 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000000
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=FFFFFFFF
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=000A9A4D
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000079
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_TIME_UNIT
+------
diff --git a/src/zscanner/test/cases/04-0_ORIGIN.in b/src/zscanner/test/cases/04-0_ORIGIN.in
new file mode 100644
index 0000000..4d65ec4
--- /dev/null
+++ b/src/zscanner/test/cases/04-0_ORIGIN.in
@@ -0,0 +1,29 @@
+$TTL 1
+
+; OK
+$ORIGIN . ; Root domain
+@ NS @ ; Use origin
+a. NS @ ; Absolute dname
+a NS @ ; Relative dname
+$ORIGIN tld. ; 1. level domain
+@ NS @ ; Use origin
+a. NS @ ; Absolute dname
+a NS @ ; Relative dname
+$ORIGIN second.tld. ; 2. level domain
+@ NS @ ; Use origin
+a. NS @ ; Absolute dname
+a NS @ ; Relative dname
+$ORIGIN \0320\ \\\"\.\@\*.tld. ; Label with special chars
+@ NS @ ; Use origin
+$ORIGIN b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. ; IPv6 reverse
+@ NS @ ; Use origin
+$ORIGIN 12345678901234567890123456789012345678901234567890123456789012\051.tld. ; Label of maximal length
+@ NS @ ; Use origin
+$ORIGIN 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901. ; Domain name of maximal length
+@ NS @ ; Use origin
+$origin . ; Lower-case
+@ NS @ ; Use origin
+
+; KO
+$ORIGIN ; Empty input
+. NS . ; Is OK, but shouldn't be processed due to previous error stop!
diff --git a/src/zscanner/test/cases/04-0_ORIGIN.out b/src/zscanner/test/cases/04-0_ORIGIN.out
new file mode 100644
index 0000000..e2135d3
--- /dev/null
+++ b/src/zscanner/test/cases/04-0_ORIGIN.out
@@ -0,0 +1,86 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016103746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=067365636F6E6403746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=067365636F6E6403746C6400
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=067365636F6E6403746C6400
+------
+OWNER=0161067365636F6E6403746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=067365636F6E6403746C6400
+------
+OWNER=082030205C222E402A03746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+------
+OWNER=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+------
+OWNER=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+ERROR=ZSCANNER_EBAD_ORIGIN
+------
diff --git a/src/zscanner/test/cases/04-1_ORIGIN.in b/src/zscanner/test/cases/04-1_ORIGIN.in
new file mode 100644
index 0000000..871c064
--- /dev/null
+++ b/src/zscanner/test/cases/04-1_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN tld ; Not FQD
diff --git a/src/zscanner/test/cases/04-1_ORIGIN.out b/src/zscanner/test/cases/04-1_ORIGIN.out
new file mode 100644
index 0000000..43d27c3
--- /dev/null
+++ b/src/zscanner/test/cases/04-1_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_ORIGIN
+------
diff --git a/src/zscanner/test/cases/04-2_ORIGIN.in b/src/zscanner/test/cases/04-2_ORIGIN.in
new file mode 100644
index 0000000..8dd2e20
--- /dev/null
+++ b/src/zscanner/test/cases/04-2_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN % ; Bad (unslashed) character
diff --git a/src/zscanner/test/cases/04-2_ORIGIN.out b/src/zscanner/test/cases/04-2_ORIGIN.out
new file mode 100644
index 0000000..43d27c3
--- /dev/null
+++ b/src/zscanner/test/cases/04-2_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_ORIGIN
+------
diff --git a/src/zscanner/test/cases/04-3_ORIGIN.in b/src/zscanner/test/cases/04-3_ORIGIN.in
new file mode 100644
index 0000000..26d1872
--- /dev/null
+++ b/src/zscanner/test/cases/04-3_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN .. ; Missing label between dots
diff --git a/src/zscanner/test/cases/04-3_ORIGIN.out b/src/zscanner/test/cases/04-3_ORIGIN.out
new file mode 100644
index 0000000..16950a8
--- /dev/null
+++ b/src/zscanner/test/cases/04-3_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_REST
+------
diff --git a/src/zscanner/test/cases/04-4_ORIGIN.in b/src/zscanner/test/cases/04-4_ORIGIN.in
new file mode 100644
index 0000000..0be4721
--- /dev/null
+++ b/src/zscanner/test/cases/04-4_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN \1 ; Slash notation requires 3 digits
diff --git a/src/zscanner/test/cases/04-4_ORIGIN.out b/src/zscanner/test/cases/04-4_ORIGIN.out
new file mode 100644
index 0000000..f30b929
--- /dev/null
+++ b/src/zscanner/test/cases/04-4_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/04-5_ORIGIN.in b/src/zscanner/test/cases/04-5_ORIGIN.in
new file mode 100644
index 0000000..170d465
--- /dev/null
+++ b/src/zscanner/test/cases/04-5_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN \12 ; Slash notation requires 3 digits
diff --git a/src/zscanner/test/cases/04-5_ORIGIN.out b/src/zscanner/test/cases/04-5_ORIGIN.out
new file mode 100644
index 0000000..f30b929
--- /dev/null
+++ b/src/zscanner/test/cases/04-5_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/04-6_ORIGIN.in b/src/zscanner/test/cases/04-6_ORIGIN.in
new file mode 100644
index 0000000..db9652d
--- /dev/null
+++ b/src/zscanner/test/cases/04-6_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN .tld ; Leading dot
diff --git a/src/zscanner/test/cases/04-6_ORIGIN.out b/src/zscanner/test/cases/04-6_ORIGIN.out
new file mode 100644
index 0000000..16950a8
--- /dev/null
+++ b/src/zscanner/test/cases/04-6_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_REST
+------
diff --git a/src/zscanner/test/cases/04-7_ORIGIN.in b/src/zscanner/test/cases/04-7_ORIGIN.in
new file mode 100644
index 0000000..556646c
--- /dev/null
+++ b/src/zscanner/test/cases/04-7_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN tld. x ; Unexpected item
diff --git a/src/zscanner/test/cases/04-7_ORIGIN.out b/src/zscanner/test/cases/04-7_ORIGIN.out
new file mode 100644
index 0000000..16950a8
--- /dev/null
+++ b/src/zscanner/test/cases/04-7_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_REST
+------
diff --git a/src/zscanner/test/cases/04-8_ORIGIN.in b/src/zscanner/test/cases/04-8_ORIGIN.in
new file mode 100644
index 0000000..445cbec
--- /dev/null
+++ b/src/zscanner/test/cases/04-8_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN 12345678901234567890123456789012345678901234567890123456789012\0514.tld. ; Label exceeded maximal length
diff --git a/src/zscanner/test/cases/04-8_ORIGIN.out b/src/zscanner/test/cases/04-8_ORIGIN.out
new file mode 100644
index 0000000..ee4139a
--- /dev/null
+++ b/src/zscanner/test/cases/04-8_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_ELABEL_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/04-9_ORIGIN.in b/src/zscanner/test/cases/04-9_ORIGIN.in
new file mode 100644
index 0000000..e0a4b95
--- /dev/null
+++ b/src/zscanner/test/cases/04-9_ORIGIN.in
@@ -0,0 +1,4 @@
+$TTL 1
+
+; KO
+$ORIGIN 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012. ; Domain name exceeded maximal length
diff --git a/src/zscanner/test/cases/04-9_ORIGIN.out b/src/zscanner/test/cases/04-9_ORIGIN.out
new file mode 100644
index 0000000..2ed0a4c
--- /dev/null
+++ b/src/zscanner/test/cases/04-9_ORIGIN.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EDNAME_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/05-0_TTL.in b/src/zscanner/test/cases/05-0_TTL.in
new file mode 100644
index 0000000..baa8f38
--- /dev/null
+++ b/src/zscanner/test/cases/05-0_TTL.in
@@ -0,0 +1,36 @@
+$ORIGIN .
+
+; OK
+$TTL 0 ; Minimal ttl
+@ NS @ ; Use ttl
+$TTL 3600 ; Inner value
+@ NS @ ; Use ttl
+$TTL 4294967295 ; Maximal ttl
+@ NS @ ; Use ttl
+$TTL 1S ; 1 second (upper-case)
+@ NS @ ; Use ttl
+$TTL 1s ; 1 second (lower-case)
+@ NS @ ; Use ttl
+$TTL 1M ; 1 minute (upper-case)
+@ NS @ ; Use ttl
+$TTL 1m ; 1 minute (lower-case)
+@ NS @ ; Use ttl
+$TTL 1H ; 1 hour (upper-case)
+@ NS @ ; Use ttl
+$TTL 1h ; 1 hour (lower-case)
+@ NS @ ; Use ttl
+$TTL 1D ; 1 day (upper-case)
+@ NS @ ; Use ttl
+$TTL 1d ; 1 day (lower-case)
+@ NS @ ; Use ttl
+$TTL 1W ; 1 week (upper-case)
+@ NS @ ; Use ttl
+$TTL 1w ; 1 week (lower-case)
+@ NS @ ; Use ttl
+$TTL 1w1d1h1m1s ; More time units
+@ NS @ ; Use ttl
+$TTL 1s1m1m ; Same time units, non decreasing order
+@ NS @ ; Use ttl
+
+; KO
+$TTL -1 ; Negative ttl
diff --git a/src/zscanner/test/cases/05-0_TTL.out b/src/zscanner/test/cases/05-0_TTL.out
new file mode 100644
index 0000000..5e87bb0
--- /dev/null
+++ b/src/zscanner/test/cases/05-0_TTL.out
@@ -0,0 +1,92 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000000
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=FFFFFFFF
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=0000003C
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00015180
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00093A80
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=000A9A4D
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000079
+RTYPE=0002
+RDATA=00
+------
+ERROR=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/05-1_TTL.in b/src/zscanner/test/cases/05-1_TTL.in
new file mode 100644
index 0000000..519fe79
--- /dev/null
+++ b/src/zscanner/test/cases/05-1_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 4294967296 ; 32bit overflow
diff --git a/src/zscanner/test/cases/05-1_TTL.out b/src/zscanner/test/cases/05-1_TTL.out
new file mode 100644
index 0000000..bbdc638
--- /dev/null
+++ b/src/zscanner/test/cases/05-1_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_ENUMBER32_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/05-2_TTL.in b/src/zscanner/test/cases/05-2_TTL.in
new file mode 100644
index 0000000..ed112da
--- /dev/null
+++ b/src/zscanner/test/cases/05-2_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 100000000W ; 32bit overflow
diff --git a/src/zscanner/test/cases/05-2_TTL.out b/src/zscanner/test/cases/05-2_TTL.out
new file mode 100644
index 0000000..bbdc638
--- /dev/null
+++ b/src/zscanner/test/cases/05-2_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_ENUMBER32_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/05-3_TTL.in b/src/zscanner/test/cases/05-3_TTL.in
new file mode 100644
index 0000000..d96c9ba
--- /dev/null
+++ b/src/zscanner/test/cases/05-3_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 4294967295s1w ; 32bit overflow
diff --git a/src/zscanner/test/cases/05-3_TTL.out b/src/zscanner/test/cases/05-3_TTL.out
new file mode 100644
index 0000000..bbdc638
--- /dev/null
+++ b/src/zscanner/test/cases/05-3_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_ENUMBER32_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/05-4_TTL.in b/src/zscanner/test/cases/05-4_TTL.in
new file mode 100644
index 0000000..efaf4d0
--- /dev/null
+++ b/src/zscanner/test/cases/05-4_TTL.in
@@ -0,0 +1,4 @@
+$ORIGIN .
+
+; KO
+$TTL 1x ; Unknown time unit
diff --git a/src/zscanner/test/cases/05-4_TTL.out b/src/zscanner/test/cases/05-4_TTL.out
new file mode 100644
index 0000000..d0a0c65
--- /dev/null
+++ b/src/zscanner/test/cases/05-4_TTL.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_TIME_UNIT
+------
diff --git a/src/zscanner/test/cases/06-0_INCLUDE.in b/src/zscanner/test/cases/06-0_INCLUDE.in
new file mode 100644
index 0000000..65ed38c
--- /dev/null
+++ b/src/zscanner/test/cases/06-0_INCLUDE.in
@@ -0,0 +1,29 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+0. NS @
+
+$INCLUDE ./includes/include1 ; Relative path without origin
+1. NS @
+
+$INCLUDE "./includes/include2" . ; Quoted filename and the simplest origin
+2. NS @
+
+$INCLUDE ./includes/include\050 tld. ; Simple origin
+3. NS @
+
+$INCLUDE \./includes/include2 _a_.-b-c-./d/. ; Slashed character in file name, allowed characters in origin
+4. NS @
+
+$INCLUDE ./includes/include2 \0320\ \\\"\.\@\*.tld. ; Origin with special chars
+5. NS @
+
+$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/includes/include2 ; Absolute path without origin
+6. NS @
+
+$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/includes/include2 tld. ; Absolute path with origin
+7. NS @
+
+; KO
+$INCLUDE ; Empty parameters
diff --git a/src/zscanner/test/cases/06-0_INCLUDE.inin b/src/zscanner/test/cases/06-0_INCLUDE.inin
new file mode 100644
index 0000000..032bf4d
--- /dev/null
+++ b/src/zscanner/test/cases/06-0_INCLUDE.inin
@@ -0,0 +1,29 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+0. NS @
+
+$INCLUDE ./includes/include1 ; Relative path without origin
+1. NS @
+
+$INCLUDE "./includes/include2" . ; Quoted filename and the simplest origin
+2. NS @
+
+$INCLUDE ./includes/include\050 tld. ; Simple origin
+3. NS @
+
+$INCLUDE \./includes/include2 _a_.-b-c-./d/. ; Slashed character in file name, allowed characters in origin
+4. NS @
+
+$INCLUDE ./includes/include2 \0320\ \\\"\.\@\*.tld. ; Origin with special chars
+5. NS @
+
+$INCLUDE @abs_builddir@/includes/include2 ; Absolute path without origin
+6. NS @
+
+$INCLUDE @abs_builddir@/includes/include2 tld. ; Absolute path with origin
+7. NS @
+
+; KO
+$INCLUDE ; Empty parameters
diff --git a/src/zscanner/test/cases/06-0_INCLUDE.out b/src/zscanner/test/cases/06-0_INCLUDE.out
new file mode 100644
index 0000000..db179aa
--- /dev/null
+++ b/src/zscanner/test/cases/06-0_INCLUDE.out
@@ -0,0 +1,140 @@
+OWNER=013000
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016105746C64316100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=016105746C64316200
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=05746C64316200
+------
+OWNER=013100
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016200
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013200
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016203746C6400
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013300
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0162035F615F052D622D632D032F642F00
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=035F615F052D622D632D032F642F00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=0162082030205C222E402A03746C6400
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013500
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016200
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013600
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=016203746C6400
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
+OWNER=013700
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+ERROR=ZSCANNER_EBAD_INCLUDE_FILENAME
+------
diff --git a/src/zscanner/test/cases/06-1_INCLUDE.in b/src/zscanner/test/cases/06-1_INCLUDE.in
new file mode 100644
index 0000000..0eb3b64
--- /dev/null
+++ b/src/zscanner/test/cases/06-1_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include1 a ; Origin is not FQD
diff --git a/src/zscanner/test/cases/06-1_INCLUDE.out b/src/zscanner/test/cases/06-1_INCLUDE.out
new file mode 100644
index 0000000..25883e7
--- /dev/null
+++ b/src/zscanner/test/cases/06-1_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_INCLUDE_ORIGIN
+------
diff --git a/src/zscanner/test/cases/06-2_INCLUDE.in b/src/zscanner/test/cases/06-2_INCLUDE.in
new file mode 100644
index 0000000..21bcf05
--- /dev/null
+++ b/src/zscanner/test/cases/06-2_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include1 % ; Bad origin
diff --git a/src/zscanner/test/cases/06-2_INCLUDE.out b/src/zscanner/test/cases/06-2_INCLUDE.out
new file mode 100644
index 0000000..25883e7
--- /dev/null
+++ b/src/zscanner/test/cases/06-2_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EBAD_INCLUDE_ORIGIN
+------
diff --git a/src/zscanner/test/cases/06-3_INCLUDE.in b/src/zscanner/test/cases/06-3_INCLUDE.in
new file mode 100644
index 0000000..963e44d
--- /dev/null
+++ b/src/zscanner/test/cases/06-3_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/ ; Given file is a directory
diff --git a/src/zscanner/test/cases/06-3_INCLUDE.inin b/src/zscanner/test/cases/06-3_INCLUDE.inin
new file mode 100644
index 0000000..02be7f8
--- /dev/null
+++ b/src/zscanner/test/cases/06-3_INCLUDE.inin
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE @abs_builddir@/ ; Given file is a directory
diff --git a/src/zscanner/test/cases/06-3_INCLUDE.out b/src/zscanner/test/cases/06-3_INCLUDE.out
new file mode 100644
index 0000000..6a45d67
--- /dev/null
+++ b/src/zscanner/test/cases/06-3_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EUNPROCESSED_INCLUDE
+------
diff --git a/src/zscanner/test/cases/06-4_INCLUDE.in b/src/zscanner/test/cases/06-4_INCLUDE.in
new file mode 100644
index 0000000..438933a
--- /dev/null
+++ b/src/zscanner/test/cases/06-4_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE /home/ondrej/Projects/knot/build/src/zscanner/test/cases/zscanner_tests/file-doesnt-exist ; File doesn't exist
diff --git a/src/zscanner/test/cases/06-4_INCLUDE.inin b/src/zscanner/test/cases/06-4_INCLUDE.inin
new file mode 100644
index 0000000..b1c6575
--- /dev/null
+++ b/src/zscanner/test/cases/06-4_INCLUDE.inin
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE @abs_builddir@/zscanner_tests/file-doesnt-exist ; File doesn't exist
diff --git a/src/zscanner/test/cases/06-4_INCLUDE.out b/src/zscanner/test/cases/06-4_INCLUDE.out
new file mode 100644
index 0000000..2d4fff2
--- /dev/null
+++ b/src/zscanner/test/cases/06-4_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EUNOPENED_INCLUDE
+------
diff --git a/src/zscanner/test/cases/06-5_INCLUDE.in b/src/zscanner/test/cases/06-5_INCLUDE.in
new file mode 100644
index 0000000..1d65812
--- /dev/null
+++ b/src/zscanner/test/cases/06-5_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include3 ; Blank include file
diff --git a/src/zscanner/test/cases/06-5_INCLUDE.out b/src/zscanner/test/cases/06-5_INCLUDE.out
new file mode 100644
index 0000000..6a45d67
--- /dev/null
+++ b/src/zscanner/test/cases/06-5_INCLUDE.out
@@ -0,0 +1,2 @@
+ERROR=ZSCANNER_EUNPROCESSED_INCLUDE
+------
diff --git a/src/zscanner/test/cases/06-6_INCLUDE.in b/src/zscanner/test/cases/06-6_INCLUDE.in
new file mode 100644
index 0000000..cbfda64
--- /dev/null
+++ b/src/zscanner/test/cases/06-6_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include4 ; Include file contains warning
diff --git a/src/zscanner/test/cases/06-6_INCLUDE.out b/src/zscanner/test/cases/06-6_INCLUDE.out
new file mode 100644
index 0000000..80f23ed
--- /dev/null
+++ b/src/zscanner/test/cases/06-6_INCLUDE.out
@@ -0,0 +1,4 @@
+WARNG=ZSCANNER_EBAD_RDATA
+------
+ERROR=ZSCANNER_EUNPROCESSED_INCLUDE
+------
diff --git a/src/zscanner/test/cases/06-7_INCLUDE.in b/src/zscanner/test/cases/06-7_INCLUDE.in
new file mode 100644
index 0000000..24deef7
--- /dev/null
+++ b/src/zscanner/test/cases/06-7_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include5 ; Include file contains error
diff --git a/src/zscanner/test/cases/06-7_INCLUDE.out b/src/zscanner/test/cases/06-7_INCLUDE.out
new file mode 100644
index 0000000..c94b02f
--- /dev/null
+++ b/src/zscanner/test/cases/06-7_INCLUDE.out
@@ -0,0 +1,4 @@
+ERROR=ZSCANNER_EBAD_NUMBER
+------
+ERROR=ZSCANNER_EUNPROCESSED_INCLUDE
+------
diff --git a/src/zscanner/test/cases/06-8_INCLUDE.in b/src/zscanner/test/cases/06-8_INCLUDE.in
new file mode 100644
index 0000000..c856668
--- /dev/null
+++ b/src/zscanner/test/cases/06-8_INCLUDE.in
@@ -0,0 +1,5 @@
+$ORIGIN .
+$TTL 1
+
+; KO
+$INCLUDE ./includes/include6 ; Include file contains include
diff --git a/src/zscanner/test/cases/06-8_INCLUDE.out b/src/zscanner/test/cases/06-8_INCLUDE.out
new file mode 100644
index 0000000..4581388
--- /dev/null
+++ b/src/zscanner/test/cases/06-8_INCLUDE.out
@@ -0,0 +1,12 @@
+OWNER=016200
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=00
+------
+OWNER=016205746C64316100
+CLASS=0001
+RRTTL=00000E10
+RTYPE=0002
+RDATA=05746C64316100
+------
diff --git a/src/zscanner/test/cases/10_A.in b/src/zscanner/test/cases/10_A.in
new file mode 100644
index 0000000..69ae11d
--- /dev/null
+++ b/src/zscanner/test/cases/10_A.in
@@ -0,0 +1,22 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ A 0.0.0.0 ; Minimal ipv4 address
+@ A 255.255.255.255 ; Maximal ipv4 address
+@ A \# 4 00000000 ; Hexadecimal rdata
+@ TYPE1 \# 4 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE1 0.0.0.0 ; TYPE
+@ a 0.0.0.0 ; Type in lower-case
+
+; KO
+@ A
+@ A ; Empty rdata
+@ A \# 0 ; Hex empty rdata
+@ A \# ; Missing hex length
+@ A 0.0.0.256 ; 8bit overflow
+@ A 0.0.0 ; Short address
+@ A 0.0.0.A ; Bad character
+@ A 0.0.0.0 1.1.1.1 ; Unexpected item
+@ A \# 5 0000000000 ; Too long rdata
+@ A \# 5 00000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/10_A.out b/src/zscanner/test/cases/10_A.out
new file mode 100644
index 0000000..c36823c
--- /dev/null
+++ b/src/zscanner/test/cases/10_A.out
@@ -0,0 +1,56 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+WARNG=ZSCANNER_EBAD_ADDRESS_CHAR
+------
+WARNG=ZSCANNER_EBAD_ADDRESS_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_IPV4
+------
+WARNG=ZSCANNER_EBAD_IPV4
+------
+WARNG=ZSCANNER_EBAD_ADDRESS_CHAR
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/11_AAAA.in b/src/zscanner/test/cases/11_AAAA.in
new file mode 100644
index 0000000..c43d375
--- /dev/null
+++ b/src/zscanner/test/cases/11_AAAA.in
@@ -0,0 +1,24 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ AAAA 0:0:0:0:0:0:0:0 ; Minimal ipv6 address
+@ AAAA FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF ; Maximal ipv6 address
+@ AAAA \# 16 00000000 00000000 00000000 00000000 ; Hexadecimal rdata
+@ TYPE28 \# 16 00000000 00000000 00000000 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE28 0:0:0:0:0:0:0:0 ; TYPE
+@ AAAA 0::1.2.3.4 ; ipv6 address based on ipv4 address
+@ AAAA :: ; Double colon
+@ aaAA :: ; Type in lower-case
+
+; KO
+@ AAAA
+@ AAAA ; Empty rdata
+@ AAAA \# 0 ; Hex empty rdata
+@ AAAA \# ; Missing hex length
+@ AAAA 0::FFFFF ; 16bit overflow
+@ AAAA 0:0:0:0:0:0:0 ; Short address
+@ AAAA 0:0:0:0:0:0:0:X ; Bad character
+@ AAAA :: :: ; Unexpected item
+@ AAAA \# 17 00000000 00000000 00000000 00000000 00 ; Too long rdata
+@ AAAA \# 17 00000000 00000000 00000000 00000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/11_AAAA.out b/src/zscanner/test/cases/11_AAAA.out
new file mode 100644
index 0000000..c4006bf
--- /dev/null
+++ b/src/zscanner/test/cases/11_AAAA.out
@@ -0,0 +1,68 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000001020304
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001C
+RDATA=00000000000000000000000000000000
+------
+WARNG=ZSCANNER_EBAD_ADDRESS_CHAR
+------
+WARNG=ZSCANNER_EBAD_ADDRESS_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_IPV6
+------
+WARNG=ZSCANNER_EBAD_IPV6
+------
+WARNG=ZSCANNER_EBAD_ADDRESS_CHAR
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/12_TXT.in b/src/zscanner/test/cases/12_TXT.in
new file mode 100644
index 0000000..36519ff
--- /dev/null
+++ b/src/zscanner/test/cases/12_TXT.in
@@ -0,0 +1,39 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ TXT "" ; Blank string
+@ TXT a ; One char string
+@ TXT \ ; One space char
+@ TXT "\ " ; One space char in quotes
+@ TXT \021 ; One unprintable char
+@ TXT "\\ \"" ; Special chars
+@ TXT "" "test1" "\255" test2 ; Array of text strings
+@ TXT "" "" "" ; Array of blank strings
+@ TXT first \# "\#" ; Array with special string
+@ TXT \0320\ \\\"\.\@\*.tld. ; Special domain as a string
+@ TXT " !\"#$%&'()*+,-./0123456789:;<=>?@" ; First part of all printables
+@ TXT "ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" ; Second part of all printables
+@ TXT "abcdefghijklmnopqrstuvwxyz{|}~" ; Third part of all printables
+@ TXT \# 1 00 ; Hexadecimal rdata
+@ TYPE16 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE16 "" ; TYPE
+@ TXT ( ; Special multi-line string
+"first
+second"
+third ; Second string
+)
+@ TXT "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\053" ; Text string of maximal length (255 chars)
+@ txt "" ; Type in lower-case
+
+; KO
+@ TXT
+@ TXT ; Empty rdata
+@ TXT \# 0 ; Hex empty rdata
+@ TXT \# ; Missing hex length
+@ TXT \# second ; Hex notation with second text string
+@ TXT \01 ; Missing digit in decimal notation
+@ TXT \256 ; 8bit overflow in decimal notation
+@ TXT \# 2 "" ; Bad length
+@ TXT """ ; '"' char without forward slash
+@ TXT "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\0536" ; Maximal length overflow
diff --git a/src/zscanner/test/cases/12_TXT.out b/src/zscanner/test/cases/12_TXT.out
new file mode 100644
index 0000000..ba573ed
--- /dev/null
+++ b/src/zscanner/test/cases/12_TXT.out
@@ -0,0 +1,134 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0161
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0115
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=035C2022
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0005746573743101FF057465737432
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=05666972737401230123
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0D2030205C222E402A2E746C642E
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=21202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F40
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=204142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F60
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=1E6162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=0C66697273740A7365636F6E64057468697264
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=FF6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E3132333435
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0010
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_TEXT
+------
+WARNG=ZSCANNER_EITEM_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/13_SPF.in b/src/zscanner/test/cases/13_SPF.in
new file mode 100644
index 0000000..0ad6c84
--- /dev/null
+++ b/src/zscanner/test/cases/13_SPF.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The SPF is the same as the TXT, so there are the differences and basics only.
+
+; OK
+@ SPF "" "test1" "\255" test2 ; Array of text strings
+@ SPF \# 1 00 ; Hexadecimal rdata
+@ TYPE99 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE99 "" ; TYPE
+@ spf "" ; Type in lower-case
+
+; KO
+@ SPF
diff --git a/src/zscanner/test/cases/13_SPF.out b/src/zscanner/test/cases/13_SPF.out
new file mode 100644
index 0000000..273e92e
--- /dev/null
+++ b/src/zscanner/test/cases/13_SPF.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=0005746573743101FF057465737432
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0063
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
diff --git a/src/zscanner/test/cases/14_NS.in b/src/zscanner/test/cases/14_NS.in
new file mode 100644
index 0000000..fe51ef2
--- /dev/null
+++ b/src/zscanner/test/cases/14_NS.in
@@ -0,0 +1,41 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NS . ; The simplest owner
+@ NS tld. ; FQD tld owner
+@ NS tld ; Relative form
+@ NS *. ; FQD with asterisk
+@ NS * ; Alone asterisk
+@ NS *.* ; More asterisks
+@ NS @ ; Use origin
+@ NS 0123456789 ; Digits
+@ NS _a_.-b-c-./d/. ; Allowed characters '_' '-' '/' anywhere
+@ NS ABCDEFGHIJKLMNOPQRSTUVWXYZ ; All upper-case letters
+@ NS abcdefghijklmnopqrstuvwxyz ; All lower-case letters
+@ NS \0320\ \\\"\.\@\*.tld. ; Label with special chars
+@ NS b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. ; IPv6 reverse
+@ NS 123456789012345678901234567890123456789012345678901234567890123.tld. ; Label of maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901. ; Domain name of maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.1234567890123456789012345678901234567890123456789012345678901 ; Domain name of maximal length (after appending origin)
+@ TYPE2 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE2 @ ; TYPE
+@ ns @ ; Type in lower-case
+
+; KO
+@ NS
+@ NS ; Empty rdata
+@ NS \# 0 ; Hex empty rdata
+@ NS \# ; Missing hex length
+@ NS & ; Bad (unslashed) character
+@ NS a*a ; * char can substitute whole label only
+@ NS @@ ; Double @@
+@ NS .. ; Missing label between dots
+@ NS \1 ; Slash notation requires 3 digits
+@ NS \12 ; Slash notation requires 3 digits
+@ NS 1234567890123456789012345678901234567890123456789012345678901234.tld. ; Label exceeded maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012. ; Domain name exceeded maximal length
+@ NS 123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.123456789012345678901234567890123456789012345678901234567890123.12345678901234567890123456789012345678901234567890123456789012 ; Domain name exceeded maximal length (after appending origin)
+@ NS . x ; Unexpected item
+@ NS \# 2 0001 ; Too long rdata
+@ NS \# 2 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/14_NS.out b/src/zscanner/test/cases/14_NS.out
new file mode 100644
index 0000000..08c0104
--- /dev/null
+++ b/src/zscanner/test/cases/14_NS.out
@@ -0,0 +1,146 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=012A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=012A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=012A012A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=0A3031323334353637383900
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=035F615F052D622D632D032F642F00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=1A4142434445464748494A4B4C4D4E4F505152535455565758595A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=1A6162636465666768696A6B6C6D6E6F707172737475767778797A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=0162016101390138013701360135013001300130013001300130013001300130013001300130013001300130013001300138016201640130013101300130013203697036046172706100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F31323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323303746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=3F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333F3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333D3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0002
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ELABEL_OVERFLOW
+------
+WARNG=ZSCANNER_EDNAME_OVERFLOW
+------
+WARNG=ZSCANNER_EDNAME_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/15_CNAME.in b/src/zscanner/test/cases/15_CNAME.in
new file mode 100644
index 0000000..806b8f9
--- /dev/null
+++ b/src/zscanner/test/cases/15_CNAME.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The CNAME is the same as the NS, so there are the differences and basics only.
+
+; OK
+@ CNAME test.example.com ; Relative dname
+@ CNAME \# 1 00 ; Hexadecimal rdata
+@ TYPE5 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE5 @ ; TYPE
+@ cname @ ; Type in lower-case
+
+; KO
+@ CNAME
diff --git a/src/zscanner/test/cases/15_CNAME.out b/src/zscanner/test/cases/15_CNAME.out
new file mode 100644
index 0000000..a541126
--- /dev/null
+++ b/src/zscanner/test/cases/15_CNAME.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=0474657374076578616D706C6503636F6D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0005
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
diff --git a/src/zscanner/test/cases/16_PTR.in b/src/zscanner/test/cases/16_PTR.in
new file mode 100644
index 0000000..3694e7d
--- /dev/null
+++ b/src/zscanner/test/cases/16_PTR.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The PTR is the same as the NS, so there are the differences and basics only.
+
+; OK
+@ PTR test.example.com ; Relative dname
+@ PTR \# 1 00 ; Hexadecimal rdata
+@ TYPE12 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE12 @ ; TYPE
+@ ptr @ ; Type in lower-case
+
+; KO
+@ PTR
diff --git a/src/zscanner/test/cases/16_PTR.out b/src/zscanner/test/cases/16_PTR.out
new file mode 100644
index 0000000..d983296
--- /dev/null
+++ b/src/zscanner/test/cases/16_PTR.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=0474657374076578616D706C6503636F6D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000C
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
diff --git a/src/zscanner/test/cases/17_DNAME.in b/src/zscanner/test/cases/17_DNAME.in
new file mode 100644
index 0000000..5e9ba71
--- /dev/null
+++ b/src/zscanner/test/cases/17_DNAME.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The DNAME is the same as the NS, so there are the differences and basics only.
+
+; OK
+@ DNAME test.example.com ; Relative dname
+@ DNAME \# 1 00 ; Hexadecimal rdata
+@ TYPE39 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE39 @ ; TYPE
+@ dname @ ; Type in lower-case
+
+; KO
+@ DNAME
diff --git a/src/zscanner/test/cases/17_DNAME.out b/src/zscanner/test/cases/17_DNAME.out
new file mode 100644
index 0000000..ee67972
--- /dev/null
+++ b/src/zscanner/test/cases/17_DNAME.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=0474657374076578616D706C6503636F6D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0027
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
diff --git a/src/zscanner/test/cases/18_MX.in b/src/zscanner/test/cases/18_MX.in
new file mode 100644
index 0000000..52bf995
--- /dev/null
+++ b/src/zscanner/test/cases/18_MX.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; For more tests on dname see NS test (same processing)
+
+; OK
+@ MX 0 @ ; Minimal priority
+@ MX 65535 @ ; Maximal priority
+@ MX 1 mail ; Relative dname
+@ MX 1 mail.tld. ; Absolute dname
+@ MX \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE15 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE15 1 @ ; TYPE
+@ mx 1 @ ; Type in lower-case
+
+; KO
+@ MX
+@ MX ; Empty rdata
+@ MX \# 0 ; Hex empty rdata
+@ MX \# ; Missing hex length
+@ MX -1 @ ; Negative number
+@ MX 65536 @ ; 16bit overflow
+@ MX 1 $ ; Bad dname
+@ MX 0 @ x ; Unexpected item
+@ MX \# 4 0001 0001 ; Too long rdata
+@ MX \# 4 0001 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/18_MX.out b/src/zscanner/test/cases/18_MX.out
new file mode 100644
index 0000000..50b1b70
--- /dev/null
+++ b/src/zscanner/test/cases/18_MX.out
@@ -0,0 +1,68 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=FFFF 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001 046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001 046D61696C03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000F
+RDATA=0001 00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/19_AFSDB.in b/src/zscanner/test/cases/19_AFSDB.in
new file mode 100644
index 0000000..be569e4
--- /dev/null
+++ b/src/zscanner/test/cases/19_AFSDB.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The AFSDB is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ AFSDB 1 mail ; Relative dname
+@ AFSDB \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE18 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE18 1 @ ; TYPE
+@ afsdb 1 @ ; Type in lower-case
+
+; KO
+@ AFSDB
diff --git a/src/zscanner/test/cases/19_AFSDB.out b/src/zscanner/test/cases/19_AFSDB.out
new file mode 100644
index 0000000..957abc7
--- /dev/null
+++ b/src/zscanner/test/cases/19_AFSDB.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=0001 046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0012
+RDATA=0001 00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/20_RT.in b/src/zscanner/test/cases/20_RT.in
new file mode 100644
index 0000000..3bc774d
--- /dev/null
+++ b/src/zscanner/test/cases/20_RT.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The RT is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ RT 1 mail ; Relative dname
+@ RT \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE21 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE21 1 @ ; TYPE
+@ rt 1 @ ; Type in lower-case
+
+; KO
+@ RT
diff --git a/src/zscanner/test/cases/20_RT.out b/src/zscanner/test/cases/20_RT.out
new file mode 100644
index 0000000..490ab2a
--- /dev/null
+++ b/src/zscanner/test/cases/20_RT.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=0001 046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0015
+RDATA=0001 00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/21_KX.in b/src/zscanner/test/cases/21_KX.in
new file mode 100644
index 0000000..529480d
--- /dev/null
+++ b/src/zscanner/test/cases/21_KX.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The KX is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ KX 1 mail ; Relative dname
+@ KX \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE36 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE36 1 @ ; TYPE
+@ kx 1 @ ; Type in lower-case
+
+; KO
+@ KX
diff --git a/src/zscanner/test/cases/21_KX.out b/src/zscanner/test/cases/21_KX.out
new file mode 100644
index 0000000..1c5f323
--- /dev/null
+++ b/src/zscanner/test/cases/21_KX.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=0001 046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0024
+RDATA=0001 00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/22_HINFO.in b/src/zscanner/test/cases/22_HINFO.in
new file mode 100644
index 0000000..8939e2d
--- /dev/null
+++ b/src/zscanner/test/cases/22_HINFO.in
@@ -0,0 +1,29 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ HINFO "" "" ; Blank string
+@ HINFO a b ; One char string
+@ HINFO \ \ ; One space char
+@ HINFO "\ " "\ " ; One space char in quotes
+@ HINFO \021 \022 ; One unprintable char
+@ HINFO "\\ \"" "\\ \"" ; Special chars
+@ HINFO first \# ; Array with special string
+@ HINFO \# 2 00 00 ; Hexadecimal rdata
+@ TYPE13 \# 2 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE13 "" "" ; TYPE
+@ HINFO "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\053" "" ; Text string of maximal length (255 chars)
+@ hinfo "" "" ; Type in lower-case
+
+; KO
+@ HINFO
+@ HINFO ; Empty rdata
+@ HINFO \# 0 ; Hex empty rdata
+@ HINFO \# ; Missing hex length
+@ HINFO \# second ; Hex notation with second text string
+@ HINFO \01 "" ; Missing digit in decimal notation
+@ HINFO \256 "" ; 8bit overflow in decimal notation
+@ HINFO \# 3 0000 ; Bad rdata length
+@ HINFO """ "" ; '"' char without forward slash
+@ HINFO "" "" "" ; Unexpected item
+@ HINFO "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMN1234\0536" "" ; Maximal length overflow
diff --git a/src/zscanner/test/cases/22_HINFO.out b/src/zscanner/test/cases/22_HINFO.out
new file mode 100644
index 0000000..66863ef
--- /dev/null
+++ b/src/zscanner/test/cases/22_HINFO.out
@@ -0,0 +1,94 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01610162
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01200120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01200120
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=01150116
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=035C2022035C2022
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0566697273740123
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=FF6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E6162636465666768696A6B6C6D6E6F707172737475767778797A313233343536373839304142434445464748494A4B4C4D4E313233343500
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000D
+RDATA=0000
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_TEXT
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EITEM_OVERFLOW
+------
diff --git a/src/zscanner/test/cases/23_MINFO.in b/src/zscanner/test/cases/23_MINFO.in
new file mode 100644
index 0000000..4f00765
--- /dev/null
+++ b/src/zscanner/test/cases/23_MINFO.in
@@ -0,0 +1,21 @@
+$ORIGIN .
+$TTL 1
+
+; For more tests on dname see NS test (same processing)
+
+; OK
+@ MINFO . . ; The simplest dnames
+@ MINFO @ @ ; Use origin
+@ MINFO mail mail.tld. ; Relative and absolute dnames
+@ MINFO \# 2 00 00 ; Hexadecimal rdata
+@ TYPE14 \# 2 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE14 @ @ ; TYPE
+@ minfo @ @ ; Type in lower-case
+
+; KO
+@ MINFO
+@ MINFO ; Empty rdata
+@ MINFO \# 0 ; Hex empty rdata
+@ MINFO \# ; Missing hex length
+@ MINFO \# 3 00 0001 ; Too long rdata
+@ MINFO \# 3 00 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/23_MINFO.out b/src/zscanner/test/cases/23_MINFO.out
new file mode 100644
index 0000000..026a7d2
--- /dev/null
+++ b/src/zscanner/test/cases/23_MINFO.out
@@ -0,0 +1,54 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=046D61696C00 046D61696C03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=000E
+RDATA=00 00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/24_RP.in b/src/zscanner/test/cases/24_RP.in
new file mode 100644
index 0000000..a70d792
--- /dev/null
+++ b/src/zscanner/test/cases/24_RP.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The RP is the same as the MINFO, so there are the differences and basics only.
+
+; OK
+@ RP mail mail.tld. ; Relative and absolute dnames
+@ RP \# 2 00 00 ; Hexadecimal rdata
+@ TYPE17 \# 2 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE17 @ @ ; TYPE
+@ rp @ @ ; Type in lower-case
+
+; KO
+@ RP
diff --git a/src/zscanner/test/cases/24_RP.out b/src/zscanner/test/cases/24_RP.out
new file mode 100644
index 0000000..0565c7d
--- /dev/null
+++ b/src/zscanner/test/cases/24_RP.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=046D61696C00 046D61696C03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0011
+RDATA=00 00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
diff --git a/src/zscanner/test/cases/25_SOA.in b/src/zscanner/test/cases/25_SOA.in
new file mode 100644
index 0000000..197cb20
--- /dev/null
+++ b/src/zscanner/test/cases/25_SOA.in
@@ -0,0 +1,36 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ SOA @ @ 0 0 0 0 0 ; The simplest variant
+@ SOA tld. tld 0 0 0 0 0 ; Absolute and relative dnames.
+@ SOA @ @ 4294967295 0 0 0 0 ; Maximal serial
+@ SOA @ @ 0 4294967295 4294967295 4294967295 4294967295 ; Maximal times
+@ SOA @ @ 0 1d 1h 1m 1s ; Time units
+@ TYPE6 \# 22 00 00 0000000000000000000000000000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE6 @ @ 0 0 0 0 0 ; TYPE
+@ SOA ns.tld. first\.second.tld. ( ; Multiline record
+ 2007120710
+ 1w2d3h4m5s
+ 2h
+ 3m
+ 4s
+)
+@ soa @ @ 0 0 0 0 0 ; Type in lower-case
+
+; KO
+@ SOA
+@ SOA ; Empty rdata
+@ SOA \# 0 ; Hex empty rdata
+@ SOA \# ; Missing hex length
+@ SOA @ @ 1h 0 0 0 0 ; Bad number
+@ SOA @ @ 4294967296 0 0 0 0 ; Serial overflow
+@ SOA @ @ 0 4294967296 0 0 0 ; Refresh overflow
+@ SOA @ @ 0 0 4294967296 0 0 ; Retry overflow
+@ SOA @ @ 0 0 0 4294967296 0 ; Expire overflow
+@ SOA @ @ 0 0 0 0 4294967296 ; Minimum overflow
+@ SOA @ @ 0 0 0 0 0 x ; Unexpected item
+@ SOA \# 23 0001 00 0000000000000000000000000000000000000000 ; Too long rdata (mname)
+@ SOA \# 23 00 0001 0000000000000000000000000000000000000000 ; Too long rdata (rname)
+@ SOA \# 23 00 00 000000000000000000000000000000000000000000 ; Too long rdata
+@ SOA \# 23 00 00 0000000000000000000000000000000000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/25_SOA.out b/src/zscanner/test/cases/25_SOA.out
new file mode 100644
index 0000000..0833c68
--- /dev/null
+++ b/src/zscanner/test/cases/25_SOA.out
@@ -0,0 +1,84 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00 00 0000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=03746C6400 03746C6400 0000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00 00 FFFFFFFF00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00 00 00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00 00 000000000001518000000E100000003C00000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00 00 0000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00 00 0000000000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=026E7303746C6400 0C66697273742E7365636F6E6403746C6400 77A23B46000C08A500001C20000000B400000004
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0006
+RDATA=00 00 0000000000000000000000000000000000000000
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/26_SRV.in b/src/zscanner/test/cases/26_SRV.in
new file mode 100644
index 0000000..43abb3f
--- /dev/null
+++ b/src/zscanner/test/cases/26_SRV.in
@@ -0,0 +1,28 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ SRV 0 0 0 @ ; The simplest variant
+_ldap._tcp.test.tld. SRV 0 0 0 @ ; Underscores in owner
+@ SRV 65535 65535 65535 @ ; Maximal numbers
+@ SRV 0 0 0 \0320\ \\\"\.\@\*.tld. ; Dname with specials
+@ TYPE33 \# 7 000000000000 00 ; TYPE + Hexadecimal rdata
+@ TYPE33 0 0 0 @ ; TYPE
+@ srv 0 0 0 @ ; Type in lower-case
+
+; KO
+@ SRV
+@ SRV ; Empty rdata
+@ SRV \# 0 ; Hex empty rdata
+@ SRV \# ; Missing hex length
+@ SRV 1h 0 0 @ ; Bad priority
+@ SRV 0 1h 0 @ ; Bad weight
+@ SRV 0 0 1h @ ; Bad port
+@ SRV 0 0 0 % ; Bad target
+@ SRV 65536 0 0 @ ; Priority overflow
+@ SRV 0 65536 0 @ ; Weight overflow
+@ SRV 0 0 65536 @ ; Port overflow
+@ SRV 0 0 0 @ x ; Unexpected item
+@ SRV 0 0 0 ; Missing item
+@ SRV \# 8 000000000000 00 00 ; Too long rdata
+@ SRV \# 8 000000000000 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/26_SRV.out b/src/zscanner/test/cases/26_SRV.out
new file mode 100644
index 0000000..fa63eb0
--- /dev/null
+++ b/src/zscanner/test/cases/26_SRV.out
@@ -0,0 +1,72 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=000000000000 00
+------
+OWNER=055F6C646170045F746370047465737403746C6400
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=000000000000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=FFFFFFFFFFFF 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=000000000000 082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=000000000000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=000000000000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0021
+RDATA=000000000000 00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/27_NAPTR.in b/src/zscanner/test/cases/27_NAPTR.in
new file mode 100644
index 0000000..0f8a132
--- /dev/null
+++ b/src/zscanner/test/cases/27_NAPTR.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NAPTR 0 0 "" "" "" @ ; The simplest variant
+@ NAPTR 65535 65535 "" "" "" @ ; Maximal numbers
+@ NAPTR 65535 65535 "" "" "!^urn:cid:.+@([^\.]+\.)(.*)$!\\2!i" @ ; Regexp example
+@ NAPTR 0 0 "" "" "" \0320\ \\\"\.\@\*.tld. ; Dname with specials
+@ TYPE35 \# 8 00000000000000 00 ; TYPE + Hexadecimal rdata
+@ TYPE35 0 0 "" "" "" @ ; TYPE
+@ naptr 0 0 "" "" "" @ ; Type in lower-case
+
+; KO
+@ NAPTR
+@ NAPTR ; Empty rdata
+@ NAPTR \# 0 ; Hex empty rdata
+@ NAPTR \# ; Missing hex length
+@ NAPTR 65536 0 "" "" "" @ ; Order overflow
+@ NAPTR 0 65536 "" "" "" @ ; Preference overflow
+@ NAPTR 0 0 "" "" "" @ x ; Unexpected item
+@ NAPTR 0 0 "" "" "" ; Missing item
+@ NAPTR \# 9 00000000000000 00 00 ; Too long rdata
+@ NAPTR \# 9 00000000000000 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/27_NAPTR.out b/src/zscanner/test/cases/27_NAPTR.out
new file mode 100644
index 0000000..42d99d0
--- /dev/null
+++ b/src/zscanner/test/cases/27_NAPTR.out
@@ -0,0 +1,62 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=00000000000000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=FFFFFFFF000000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=FFFFFFFF00001F215E75726E3A6369643A2E2B40285B5E2E5D2B2E29282E2A2924215C322169 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=00000000000000 082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=00000000000000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=00000000000000 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0023
+RDATA=00000000000000 00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/28_TYPE.in b/src/zscanner/test/cases/28_TYPE.in
new file mode 100644
index 0000000..f8189e8
--- /dev/null
+++ b/src/zscanner/test/cases/28_TYPE.in
@@ -0,0 +1,27 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ TYPE0 \# 0 ; Minimal type number
+@ TYPE65535 \# 0 ; Maximal type number
+@ TYPE55555 \# 0 ; Without hex rdata
+@ TYPE55555 \# 1 00 ; Without hex rdata
+@ TYPE1 \# 4 00000000 ; Known type
+@ TYPE1 0.0.0.0 ; Known type in text format
+@ TYPE55555 ( ; Multiline begin
+ \#
+ 5
+ 0102 03
+ 04 05
+ ) ; Multiline end
+@ type55555 \# 0 ; Type in lower-case
+
+; KO
+@ TYPE55555
+@ TYPE55555 ; Without text rdata
+@ TYPE65536 ; Type number overflow
+@ TYPE65535x ; Bad type
+@ TYPE55555 \# ; Missing hex length
+@ TYPE55555 \# 1 0000 ; Too long rdata
+@ TYPE55555 \# 2 00 ; Bad rdata length
+@ TYPE55555 \# 1 00 x ; Unexpected data
diff --git a/src/zscanner/test/cases/28_TYPE.out b/src/zscanner/test/cases/28_TYPE.out
new file mode 100644
index 0000000..8f6e10e
--- /dev/null
+++ b/src/zscanner/test/cases/28_TYPE.out
@@ -0,0 +1,64 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0000
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=FFFF
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0001
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=0102030405
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=D903
+RDATA=
+------
+WARNG=ZSCANNER_ECANNOT_TEXT_DATA
+------
+WARNG=ZSCANNER_ECANNOT_TEXT_DATA
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
diff --git a/src/zscanner/test/cases/29_CERT.in b/src/zscanner/test/cases/29_CERT.in
new file mode 100644
index 0000000..c08c3f7
--- /dev/null
+++ b/src/zscanner/test/cases/29_CERT.in
@@ -0,0 +1,59 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ CERT 0 0 0 AA== ; The simplest variant
+@ CERT 65535 65535 255 AA== ; Maximal numbers
+@ CERT PKIX 0 0 AA== ; Certificate type mnemo
+@ CERT SPKI 0 0 AA== ; Certificate type mnemo
+@ CERT PGP 0 0 AA== ; Certificate type mnemo
+@ CERT IPKIX 0 0 AA== ; Certificate type mnemo
+@ CERT ISPKI 0 0 AA== ; Certificate type mnemo
+@ CERT IPGP 0 0 AA== ; Certificate type mnemo
+@ CERT ACPKIX 0 0 AA== ; Certificate type mnemo
+@ CERT IACPKIX 0 0 AA== ; Certificate type mnemo
+@ CERT URI 0 0 AA== ; Certificate type mnemo
+@ CERT OID 0 0 AA== ; Certificate type mnemo
+@ CERT 0 0 RSAMD5 AA== ; Algorithm mnemo
+@ CERT 0 0 DH AA== ; Algorithm mnemo
+@ CERT 0 0 DSA AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA1 AA== ; Algorithm mnemo
+@ CERT 0 0 DSA-NSEC3-SHA1 AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA1-NSEC3-SHA1 AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA256 AA== ; Algorithm mnemo
+@ CERT 0 0 RSASHA512 AA== ; Algorithm mnemo
+@ CERT 0 0 ECC-GOST AA== ; Algorithm mnemo
+@ CERT 0 0 ECDSAP256SHA256 AA== ; Algorithm mnemo
+@ CERT 0 0 ECDSAP384SHA384 AA== ; Algorithm mnemo
+@ CERT 0 0 INDIRECT AA== ; Algorithm mnemo
+@ CERT 0 0 PRIVATEDNS AA== ; Algorithm mnemo
+@ CERT 0 0 PRIVATEOID AA== ; Algorithm mnemo
+@ CERT 0 0 0 Zm8= ; One char padding
+@ CERT 0 0 0 Zm9v ; Without padding
+@ CERT 0 0 0 Zm9vYg== ; Two base64 blocks
+@ CERT 0 0 0 Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE37 \# 6 000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE37 0 0 0 AA== ; TYPE
+@ cert 0 0 0 AA== ; Type in lower-case
+
+; KO
+@ CERT
+@ CERT ; Empty rdata
+@ CERT \# 0 ; Hex empty rdata
+@ CERT \# ; Missing hex length
+@ CERT 65536 0 0 AA== ; Type overflow
+@ CERT X 0 0 AA== ; Bad type mnemonic
+@ CERT 0 65536 0 AA== ; Key tag overflow
+@ CERT 0 0 256 AA== ; Algorithm overflow
+@ CERT 0 0 0 A ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 AB ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 ABC ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 AA == ; Continuous block length must be multiple of 4
+@ CERT 0 0 0 A=== ; Bad padding
+@ CERT 0 0 0 = ; Bad padding
+@ CERT 0 0 0 == ; Bad padding
+@ CERT 0 0 0 === ; Bad padding
+@ CERT 0 0 0 ==== ; Bad padding
+@ CERT 0 0 0 ; Missing item
+@ CERT \# 6 00000000000000 ; Too long rdata
+@ CERT \# 7 000000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/29_CERT.out b/src/zscanner/test/cases/29_CERT.out
new file mode 100644
index 0000000..5352d09
--- /dev/null
+++ b/src/zscanner/test/cases/29_CERT.out
@@ -0,0 +1,238 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=FFFFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000100000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000200000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000300000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000400000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000500000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000600000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000700000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000800000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00FD00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00FE00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000200
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000300
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000500
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000600
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000700
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000800
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000A00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000D00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000E00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00000000FC00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00000000FD00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=00000000FE00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=0000000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0025
+RDATA=000000000000
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_CERT_TYPE
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/30_KEY.in b/src/zscanner/test/cases/30_KEY.in
new file mode 100644
index 0000000..392257f
--- /dev/null
+++ b/src/zscanner/test/cases/30_KEY.in
@@ -0,0 +1,34 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ KEY 0 0 0 AA== ; The simplest variant
+@ KEY 65535 255 255 AA== ; Maximal numbers
+@ KEY 0 0 0 Zm8= ; One char padding
+@ KEY 0 0 0 Zm9v ; Without padding
+@ KEY 0 0 0 Zm9vYg== ; Two base64 blocks
+@ KEY 0 0 0 Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE25 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE25 0 0 0 AA== ; TYPE
+@ key 0 0 0 AA== ; Type in lower-case
+
+; KO
+@ KEY
+@ KEY ; Empty rdata
+@ KEY \# 0 ; Hex empty rdata
+@ KEY \# ; Missing hex length
+@ KEY 65536 0 0 AA== ; Type overflow
+@ KEY 0 256 0 AA== ; Key tag overflow
+@ KEY 0 0 256 AA== ; Algorithm overflow
+@ KEY 0 0 0 A ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 AB ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 ABC ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 AA == ; Continuous block length must be multiple of 4
+@ KEY 0 0 0 A=== ; Bad padding
+@ KEY 0 0 0 = ; Bad padding
+@ KEY 0 0 0 == ; Bad padding
+@ KEY 0 0 0 === ; Bad padding
+@ KEY 0 0 0 ==== ; Bad padding
+@ KEY 0 0 0 ; Missing item
+@ KEY \# 5 000000000000 ; Too long rdata
+@ KEY \# 6 0000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/30_KEY.out b/src/zscanner/test/cases/30_KEY.out
new file mode 100644
index 0000000..aa721d2
--- /dev/null
+++ b/src/zscanner/test/cases/30_KEY.out
@@ -0,0 +1,92 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=00000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0019
+RDATA=0000000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/31_DNSKEY.in b/src/zscanner/test/cases/31_DNSKEY.in
new file mode 100644
index 0000000..0f99937
--- /dev/null
+++ b/src/zscanner/test/cases/31_DNSKEY.in
@@ -0,0 +1,35 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ DNSKEY 0 0 0 AA== ; The simplest variant
+@ DNSKEY 65535 255 255 AA== ; Maximal numbers
+@ DNSKEY 0 0 RSAMD5 AA== ; Algorithm mnemonic
+@ DNSKEY 0 0 0 Zm8= ; One char padding
+@ DNSKEY 0 0 0 Zm9v ; Without padding
+@ DNSKEY 0 0 0 Zm9vYg== ; Two base64 blocks
+@ DNSKEY 0 0 0 Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE48 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE48 0 0 0 AA== ; TYPE
+@ dnskey 0 0 0 AA== ; Type in lower-case
+
+; KO
+@ DNSKEY
+@ DNSKEY ; Empty rdata
+@ DNSKEY \# 0 ; Hex empty rdata
+@ DNSKEY \# ; Missing hex length
+@ DNSKEY 65536 0 0 AA== ; Type overflow
+@ DNSKEY 0 256 0 AA== ; Key tag overflow
+@ DNSKEY 0 0 256 AA== ; Algorithm overflow
+@ DNSKEY 0 0 0 A ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 AB ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 ABC ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 AA == ; Continuous block length must be multiple of 4
+@ DNSKEY 0 0 0 A=== ; Bad padding
+@ DNSKEY 0 0 0 = ; Bad padding
+@ DNSKEY 0 0 0 == ; Bad padding
+@ DNSKEY 0 0 0 === ; Bad padding
+@ DNSKEY 0 0 0 ==== ; Bad padding
+@ DNSKEY 0 0 0 ; Missing item
+@ DNSKEY \# 5 000000000000 ; Too long rdata
+@ DNSKEY \# 6 0000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/31_DNSKEY.out b/src/zscanner/test/cases/31_DNSKEY.out
new file mode 100644
index 0000000..f72ec07
--- /dev/null
+++ b/src/zscanner/test/cases/31_DNSKEY.out
@@ -0,0 +1,98 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=00000000666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0030
+RDATA=0000000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/32_APL.in b/src/zscanner/test/cases/32_APL.in
new file mode 100644
index 0000000..56f2c23
--- /dev/null
+++ b/src/zscanner/test/cases/32_APL.in
@@ -0,0 +1,30 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ APL ; The simplest variant - blank list
+@ APL 1:0.0.0.0/0 ; Minimal ipv4 prefix length
+@ APL 1:255.255.255.255/32 ; Maximal ipv4 prefix length
+@ APL 1:255.255.255.255/30 ; Prefix length isn't multiple of 8
+@ APL 2:0::0/0 ; Minimal ipv6 prefix length
+@ APL 2:0::0/128 ; Maximal ipv6 prefix length
+@ APL 2:FFFF:FFFF:FFFF::/2 ; Trailing zeroes test
+@ APL !1:0.0.0.0/0 ; Negation flag
+@ APL 1:0.0.0.0/0 1:255.255.255.255/32 ; More APLs
+@ TYPE42 \# 4 00010000 ; TYPE + Hexadecimal rdata
+@ TYPE42 1:0.0.0.0/0 ; TYPE
+@ APL \# 0 ; Zero length rdata
+@ apl 1:0.0.0.0/0 ; Type in lower-case
+
+; KO
+@ APL 0:0.0.0.0/32 ; Bad address family
+@ APL x:0.0.0.0/32 ; Bad address family
+@ APL !x:0.0.0.0/32 ; Bad address family
+@ APL 1:0.0.0.0/33 ; Prefix length is too long
+@ APL 2:0::0/129 ; Prefix length is too long
+@ APL 2::/0 ; Bad ipv6 address
+@ APL 2:0::0/x ; Bad prefix length
+@ APL 1:0.0.0.0/ ; Missing prefix length
+@ APL \# ; Missing hex length
+@ APL \# 4 0001000000 ; Too long rdata
+@ APL \# 5 00000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/32_APL.out b/src/zscanner/test/cases/32_APL.out
new file mode 100644
index 0000000..8e7ae85
--- /dev/null
+++ b/src/zscanner/test/cases/32_APL.out
@@ -0,0 +1,100 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00012004FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00011E04FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00020000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00028000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00020206FFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010080
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=0001000000012004FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002A
+RDATA=00010000
+------
+WARNG=ZSCANNER_EBAD_APL
+------
+WARNG=ZSCANNER_EBAD_APL
+------
+WARNG=ZSCANNER_EBAD_APL
+------
+WARNG=ZSCANNER_EBAD_APL
+------
+WARNG=ZSCANNER_EBAD_APL
+------
+WARNG=ZSCANNER_EBAD_IPV6
+------
+WARNG=ZSCANNER_EBAD_APL
+------
+WARNG=ZSCANNER_EBAD_APL
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/33_DS.in b/src/zscanner/test/cases/33_DS.in
new file mode 100644
index 0000000..8a71195
--- /dev/null
+++ b/src/zscanner/test/cases/33_DS.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ DS 0 0 0 00 ; The simplest variant
+@ DS 65535 255 255 00 ; Maximal numbers
+@ DS 0 RSAMD5 0 00 ; Algorithm mnemonic
+@ DS 0 0 0 01 02 0304 ; Hex block with blank spaces between them
+@ TYPE43 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE43 0 0 0 00 ; TYPE
+@ ds 0 0 0 00 ; Type in lower-case
+
+; KO
+@ DS
+@ DS ; Empty rdata
+@ DS \# 0 ; Hex empty rdata
+@ DS \# ; Missing hex length
+@ DS 65536 0 0 00 ; Key tag overflow
+@ DS 0 256 0 00 ; Algorithm overflow
+@ DS 0 0 256 00 ; Digest type overflow
+@ DS 0 0 0 0 ; Continuous block length must be multiple of 2
+@ DS 0 0 0 00 0 ; Continuous block length must be multiple of 2
+@ DS 0 0 0 XX ; Bad hex character
+@ DS 0 0 0 ; Missing item
+@ DS \# 5 000000000000 ; Too long rdata
+@ DS \# 6 0000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/33_DS.out b/src/zscanner/test/cases/33_DS.out
new file mode 100644
index 0000000..b727d1c
--- /dev/null
+++ b/src/zscanner/test/cases/33_DS.out
@@ -0,0 +1,68 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000010000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000001020304
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002B
+RDATA=0000000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/34_SSHFP.in b/src/zscanner/test/cases/34_SSHFP.in
new file mode 100644
index 0000000..b8b502d
--- /dev/null
+++ b/src/zscanner/test/cases/34_SSHFP.in
@@ -0,0 +1,24 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ SSHFP 0 0 00 ; The simplest variant
+@ SSHFP 255 255 00 ; Maximal numbers
+@ SSHFP 0 0 01 02 0304 ; Hex block with blank spaces between them
+@ TYPE44 \# 3 000000 ; TYPE + Hexadecimal rdata
+@ TYPE44 0 0 00 ; TYPE
+@ sshfp 0 0 00 ; Type in lower-case
+
+; KO
+@ SSHFP
+@ SSHFP ; Empty rdata
+@ SSHFP \# 0 ; Hex empty rdata
+@ SSHFP \# ; Missing hex length
+@ SSHFP 256 0 00 ; Algorithm overflow
+@ SSHFP 0 256 00 ; Fp type overflow
+@ SSHFP 0 0 0 ; Continuous block length must be multiple of 2
+@ SSHFP 0 0 00 0 ; Continuous block length must be multiple of 2
+@ SSHFP 0 0 XX ; Bad hex character
+@ SSHFP 0 0 ; Missing item
+@ SSHFP \# 3 00000000 ; Too long rdata
+@ SSHFP \# 4 000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/34_SSHFP.out b/src/zscanner/test/cases/34_SSHFP.out
new file mode 100644
index 0000000..787074b
--- /dev/null
+++ b/src/zscanner/test/cases/34_SSHFP.out
@@ -0,0 +1,60 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=FFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000001020304
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002C
+RDATA=000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/35_IPSECKEY.in b/src/zscanner/test/cases/35_IPSECKEY.in
new file mode 100644
index 0000000..c0e06f8
--- /dev/null
+++ b/src/zscanner/test/cases/35_IPSECKEY.in
@@ -0,0 +1,32 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ IPSECKEY 0 0 0 . ; The simplest variant - no gw, no key
+@ IPSECKEY 255 3 255 . AA== ; Maximal numbers
+@ IPSECKEY 0 1 0 0.0.0.0 ; IPv4 address
+@ IPSECKEY 0 2 0 :: ; IPv6 address
+@ IPSECKEY 0 3 0 \0320\ \\\"\.\@\*.tld. ; Special chars in domain name
+@ IPSECKEY 0 0 1 . Zm8= ; One char padding
+@ IPSECKEY 0 0 1 . Zm9v ; Without padding
+@ IPSECKEY 0 0 1 . Zm9vYg== ; Two base64 blocks
+@ IPSECKEY 0 0 1 . Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE45 \# 3 000000 ; TYPE + Hexadecimal rdata
+@ TYPE45 0 0 1 . AA== ; TYPE
+@ ipseckey 0 0 1 . AA== ; Type in lower-case
+
+; KO
+@ IPSECKEY
+@ IPSECKEY ; Empty rdata
+@ IPSECKEY \# 0 ; Hex empty rdata
+@ IPSECKEY \# ; Missing hex length
+@ IPSECKEY 256 0 0 . ; Precedence overflow
+@ IPSECKEY 0 4 0 . ; Unknown gateway
+@ IPSECKEY 0 0 256 . AA== ; Algorithm overflow
+@ IPSECKEY 0 0 0 . AA== ; If alg is 0 then key shouldn't be given
+@ IPSECKEY 0 0 0 a% ; Bad domain name char
+@ IPSECKEY 0 0 1 . A ; Continuous block length must be multiple of 4
+@ IPSECKEY 0 0 1 . = ; Bad padding
+@ IPSECKEY 0 0 ; Missing item
+@ IPSECKEY \# 3 00000000 ; Too long rdata
+@ IPSECKEY \# 4 000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/35_IPSECKEY.out b/src/zscanner/test/cases/35_IPSECKEY.out
new file mode 100644
index 0000000..6865bc7
--- /dev/null
+++ b/src/zscanner/test/cases/35_IPSECKEY.out
@@ -0,0 +1,100 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=FF03FF0000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00010000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00020000000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000300082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000001666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002D
+RDATA=00000100
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_GATEWAY
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_GATEWAY_KEY
+------
+WARNG=ZSCANNER_EBAD_GATEWAY
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_GATEWAY_KEY
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/36_RRSIG.in b/src/zscanner/test/cases/36_RRSIG.in
new file mode 100644
index 0000000..700c152
--- /dev/null
+++ b/src/zscanner/test/cases/36_RRSIG.in
@@ -0,0 +1,48 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ RRSIG TYPE0 0 0 0 0 0 0 . AA== ; The simplest variant
+@ RRSIG A 2 3 4 5 6 7 \008. CQ== ; Human visual test - block numbering
+@ RRSIG TYPE65535 255 255 4294967295 4294967295 4294967295 65535 . AA== ; Maximal numbers
+@ RRSIG TYPE0 RSAMD5 0 0 0 0 0 . AA== ; Algorithm mnemonic
+@ RRSIG A 0 0 0 19700101000000 0 0 . AA== ; Minimal date format
+@ RRSIG A 0 0 0 0 21051231235959 0 . AA== ; Maximal date format (zscanner limit)
+@ RRSIG TYPE0 0 0 0 0 0 0 \0320\ \\\"\.\@\*.tld. AA== ; Special chars in domain name
+@ RRSIG A 0 0 0 0 0 0 . Zm8= ; One char padding
+@ RRSIG A 0 0 0 0 0 0 . Zm9v ; Without padding
+@ RRSIG A 0 0 0 0 0 0 . Zm9vYg== ; Two base64 blocks
+@ RRSIG A 0 0 0 0 0 0 . Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE46 \# 20 000100000000000000000000000000000000 00 00 ; TYPE + Hexadecimal rdata
+@ TYPE46 A 0 0 0 0 0 0 . AA== ; TYPE
+@ rrsig A 0 0 0 0 0 0 . AA== ; Type in lower-case
+
+; KO
+@ RRSIG
+@ RRSIG ; Empty rdata
+@ RRSIG \# 0 ; Hex empty rdata
+@ RRSIG \# ; Missing hex length
+@ RRSIG X 0 0 0 0 0 0 . AA== ; Unknown type
+@ RRSIG TYPE65536 0 0 0 0 0 0 . AA== ; Type overflow
+@ RRSIG A 256 0 0 0 0 0 . AA== ; Algorithm overflow
+@ RRSIG A 0 256 0 0 0 0 . AA== ; Labels overflow
+@ RRSIG A 0 0 4294967296 0 0 0 . AA== ; TTL overflow
+@ RRSIG A 0 0 0 9294967296 0 0 . AA== ; Sig. exp. overflow
+@ RRSIG A 0 0 0 0 4294967296 0 . AA== ; Sig. inc. overflow
+@ RRSIG A 0 0 0 0 0 65536 . AA== ; Key tag overflow
+@ RRSIG A 0 0 0 0 21060101000000 0 . AA== ; Date overflow
+@ RRSIG A 0 0 0 0 2106010100000x 0 . AA== ; Bad timestamp char
+@ RRSIG A 0 0 0 0 210601010000000 0 . AA== ; Bad timestamp length
+@ RRSIG A 0 0 0 0 0 0 a% AA== ; Bad domain char
+@ RRSIG A 0 0 0 0 0 0 . A ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . AB ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . ABC ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . AA == ; Continuous block length must be multiple of 4
+@ RRSIG A 0 0 0 0 0 0 . A=== ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . = ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . == ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . === ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . ==== ; Bad padding
+@ RRSIG A 0 0 0 0 0 0 . ; Missing item
+@ RRSIG \# 20 000100000000000000000000000000000000 00 0000 ; Too long rdata
+@ RRSIG \# 21 000100000000000000000000000000000000 00 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/36_RRSIG.out b/src/zscanner/test/cases/36_RRSIG.out
new file mode 100644
index 0000000..f624432
--- /dev/null
+++ b/src/zscanner/test/cases/36_RRSIG.out
@@ -0,0 +1,140 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000000000000000000000000000000000000 00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000102030000000400000005000000060007 010800 09
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000001000000000000000000000000000000 00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000FFCEDD7F0000 00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000000000000000000000000000000000000 082030205C222E402A03746C6400 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002E
+RDATA=000100000000000000000000000000000000 00 00
+------
+WARNG=ZSCANNER_EUNSUPPORTED_TYPE
+------
+WARNG=ZSCANNER_EUNSUPPORTED_TYPE
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EUNSUPPORTED_TYPE
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER32_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_DATE
+------
+WARNG=ZSCANNER_EBAD_TIMESTAMP_CHAR
+------
+WARNG=ZSCANNER_EBAD_TIMESTAMP_LENGTH
+------
+WARNG=ZSCANNER_EBAD_DNAME_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/37_NSEC.in b/src/zscanner/test/cases/37_NSEC.in
new file mode 100644
index 0000000..e424816
--- /dev/null
+++ b/src/zscanner/test/cases/37_NSEC.in
@@ -0,0 +1,23 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NSEC . ; The simplest variant - without bitmap
+@ NSEC \0320\ \\\"\.\@\*.tld. ; Special chars in domain name
+@ NSEC . TYPE0 ; Minimal type number
+@ NSEC . TYPE65535 ; Maximal type number
+@ NSEC . TYPE0 A NS ; First bitmap window
+@ NSEC . TYPE0 TYPE256 TYPE512 TYPE32768 ; First, second, third and 128. bitmap window
+@ TYPE47 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE47 . ; TYPE
+@ nsec . ; Type in lower-case
+
+; KO
+@ NSEC
+@ NSEC ; Empty rdata
+@ NSEC \# 0 ; Hex empty rdata
+@ NSEC \# ; Missing hex length
+@ NSEC . TYPE65536 ; Type number overflow
+@ NSEC . X ; Unknown type
+@ NSEC \# 1 0000 ; Too long rdata
+@ NSEC \# 2 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/37_NSEC.out b/src/zscanner/test/cases/37_NSEC.out
new file mode 100644
index 0000000..b6e57a4
--- /dev/null
+++ b/src/zscanner/test/cases/37_NSEC.out
@@ -0,0 +1,70 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=082030205C222E402A03746C6400
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00 000180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00 FF200000000000000000000000000000000000000000000000000000000000000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00 0001E0
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00 000180010180020180800180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=002F
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_BITMAP
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/38_DHCID.in b/src/zscanner/test/cases/38_DHCID.in
new file mode 100644
index 0000000..30f5c00
--- /dev/null
+++ b/src/zscanner/test/cases/38_DHCID.in
@@ -0,0 +1,29 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ DHCID AA== ; The simplest variant
+@ DHCID Zm8= ; One char padding
+@ DHCID Zm9v ; Without padding
+@ DHCID Zm9vYg== ; Two base64 blocks
+@ DHCID Zm9v YmE= ; Two base64 blocks with blank space between them
+@ TYPE49 \# 1 00 ; TYPE + Hexadecimal rdata
+@ TYPE49 AA== ; TYPE
+@ dhcid AA== ; Type in lower-case
+
+; KO
+@ DHCID
+@ DHCID ; Empty rdata
+@ DHCID \# 0 ; Hex empty rdata
+@ DHCID \# ; Missing hex length
+@ DHCID A ; Continuous block length must be multiple of 4
+@ DHCID AB ; Continuous block length must be multiple of 4
+@ DHCID ABC ; Continuous block length must be multiple of 4
+@ DHCID AA == ; Continuous block length must be multiple of 4
+@ DHCID A=== ; Bad padding
+@ DHCID = ; Bad padding
+@ DHCID == ; Bad padding
+@ DHCID === ; Bad padding
+@ DHCID ==== ; Bad padding
+@ DHCID \# 1 0000 ; Too long rdata
+@ DHCID \# 2 00 ; Bad rdata length
diff --git a/src/zscanner/test/cases/38_DHCID.out b/src/zscanner/test/cases/38_DHCID.out
new file mode 100644
index 0000000..41774e3
--- /dev/null
+++ b/src/zscanner/test/cases/38_DHCID.out
@@ -0,0 +1,78 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0031
+RDATA=00
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE64_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/39_NSEC3.in b/src/zscanner/test/cases/39_NSEC3.in
new file mode 100644
index 0000000..ba8bdcb
--- /dev/null
+++ b/src/zscanner/test/cases/39_NSEC3.in
@@ -0,0 +1,49 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NSEC3 0 0 0 - 00====== ; The simplest variant - without bitmap
+@ NSEC3 255 255 65535 - 00====== ; Maximal numbers
+@ NSEC3 0 0 0 00FF 00====== ; Hex string
+@ NSEC3 0 0 0 - 00====== ; Eight char padding
+@ NSEC3 0 0 0 - CPNG==== ; Four char padding
+@ NSEC3 0 0 0 - CPNMU=== ; Three char padding
+@ NSEC3 0 0 0 - CPNMUOG= ; One char padding
+@ NSEC3 0 0 0 - CPNMUOJ1 ; Without padding
+@ NSEC3 0 0 0 - CPNMUOJ1E8====== ; Two base32hex blocks
+@ NSEC3 0 0 0 - 00====== TYPE0 ; Minimal type number
+@ NSEC3 0 0 0 - 00====== TYPE65535 ; Maximal type number
+@ NSEC3 0 0 0 - 00====== TYPE0 A NS ; First bitmap window
+@ NSEC3 0 0 0 - 00====== TYPE0 TYPE256 TYPE512 TYPE32768 ; First, second, third and 128. bitmap window
+@ TYPE50 \# 7 00000000000100 ; TYPE + Hexadecimal rdata
+@ TYPE50 0 0 0 - 00====== ; TYPE
+@ nsec3 0 0 0 - 00====== ; Type in lower-case
+
+; KO
+@ NSEC3
+@ NSEC3 ; Empty rdata
+@ NSEC3 \# 0 ; Hex empty rdata
+@ NSEC3 \# ; Missing hex length
+@ NSEC3 256 0 0 - 00====== ; Algorithm overflow
+@ NSEC3 0 256 0 - 00====== ; Flags overflow
+@ NSEC3 0 0 65536 - 00====== ; Iterations overflow
+@ NSEC3 0 0 0 0 00====== ; Hex block must be multiple of 2
+@ NSEC3 0 0 0 0X 00====== ; Bad hex char
+@ NSEC3 0 0 0 00 FF 00====== ; Hex string with blank space inside
+@ NSEC3 0 0 0 - 1 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 12 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 123 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 1234 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 12345 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 123456 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 1234567 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - 123456 78 ; Continuous block length must be multiple of 8
+@ NSEC3 0 0 0 - ======== ; Bad padding
+@ NSEC3 0 0 0 - 1======= ; Bad padding
+@ NSEC3 0 0 0 - 123===== ; Bad padding
+@ NSEC3 0 0 0 - 123456== ; Bad padding
+@ NSEC3 0 0 0 - CPNMUOJ1 E8====== ; Two base32hex blocks with blank space between them
+@ NSEC3 0 0 0 - 00====== TYPE65536 ; Type number overflow
+@ NSEC3 0 0 0 - 00====== X ; Unknown type
+@ NSEC3 \# 7 0000000000010000 ; Too long rdata
+@ NSEC3 \# 8 00000000000100 ; Bad rdata length
diff --git a/src/zscanner/test/cases/39_NSEC3.out b/src/zscanner/test/cases/39_NSEC3.out
new file mode 100644
index 0000000..ef533f5
--- /dev/null
+++ b/src/zscanner/test/cases/39_NSEC3.out
@@ -0,0 +1,150 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=FFFFFFFF000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000200FF0100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000002666F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000003666F6F
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000004666F6F62
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000005666F6F6261
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000006666F6F626172
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100000180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100FF200000000000000000000000000000000000000000000000000000000000000001
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=000000000001000001E0
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100000180010180020180800180
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0032
+RDATA=00000000000100
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BASE32HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_BITMAP
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_BITMAP
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/40_NSEC3PARAM.in b/src/zscanner/test/cases/40_NSEC3PARAM.in
new file mode 100644
index 0000000..b397591
--- /dev/null
+++ b/src/zscanner/test/cases/40_NSEC3PARAM.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ NSEC3PARAM 0 0 0 - ; The simplest variant
+@ NSEC3PARAM 255 255 65535 - ; Maximal numbers
+@ NSEC3PARAM 0 0 0 0102FF ; Hex string
+@ TYPE51 \# 5 0000000000 ; TYPE + Hexadecimal rdata
+@ TYPE51 0 0 0 - ; TYPE
+@ nsec3param 0 0 0 - ; Type in lower-case
+
+; KO
+@ NSEC3PARAM
+@ NSEC3PARAM ; Empty rdata
+@ NSEC3PARAM \# 0 ; Hex empty rdata
+@ NSEC3PARAM \# ; Missing hex length
+@ NSEC3PARAM 256 0 0 00 ; Algorithm overflow
+@ NSEC3PARAM 0 256 0 00 ; Flags overflow
+@ NSEC3PARAM 0 0 65536 00 ; Iterations overflow
+@ NSEC3PARAM 0 0 0 0 ; Hex block length must be multiple of 2
+@ NSEC3PARAM 0 0 0 0x ; Bad hex char
+@ NSEC3PARAM 0 0 0 00 00 ; Hex block must not contain blank spaces
+@ NSEC3PARAM 0 0 0 00 x ; Unexpected item
+@ NSEC3PARAM 0 0 0 ; Missing item
+@ NSEC3PARAM \# 5 000000000000 ; Too long rdata
+@ NSEC3PARAM \# 6 0000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/40_NSEC3PARAM.out b/src/zscanner/test/cases/40_NSEC3PARAM.out
new file mode 100644
index 0000000..85f9f74
--- /dev/null
+++ b/src/zscanner/test/cases/40_NSEC3PARAM.out
@@ -0,0 +1,64 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=FFFFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=00000000030102FF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0033
+RDATA=0000000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/41_TLSA.in b/src/zscanner/test/cases/41_TLSA.in
new file mode 100644
index 0000000..d28f426
--- /dev/null
+++ b/src/zscanner/test/cases/41_TLSA.in
@@ -0,0 +1,24 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ TLSA 0 0 0 00 ; The simplest variant
+@ TLSA 255 255 255 00 ; Maximal numbers
+@ TLSA 0 0 0 0102 00 FF ; Hex string with blank spaces inside
+@ TYPE52 \# 4 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE52 0 0 0 00 ; TYPE
+@ tlsa 0 0 0 00 ; Type in lower-case
+
+; KO
+@ TLSA
+@ TLSA ; Empty rdata
+@ TLSA \# 0 ; Hex empty rdata
+@ TLSA \# ; Missing hex length
+@ TLSA 256 0 0 00 ; Algorithm overflow
+@ TLSA 0 256 0 00 ; Flags overflow
+@ TLSA 0 0 256 00 ; Iterations overflow
+@ TLSA 0 0 0 0 ; Hex block length must be multiple of 2
+@ TLSA 0 0 0 0x ; Bad hex char
+@ TLSA 0 0 0 ; Missing item
+@ TLSA \# 4 0000000000 ; Too long rdata
+@ TLSA \# 5 00000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/41_TLSA.out b/src/zscanner/test/cases/41_TLSA.out
new file mode 100644
index 0000000..ebe5eaa
--- /dev/null
+++ b/src/zscanner/test/cases/41_TLSA.out
@@ -0,0 +1,60 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=FFFFFF00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=000000010200FF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0034
+RDATA=00000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_ENUMBER8_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/42_LOC.in b/src/zscanner/test/cases/42_LOC.in
new file mode 100644
index 0000000..11a87c4
--- /dev/null
+++ b/src/zscanner/test/cases/42_LOC.in
@@ -0,0 +1,67 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ LOC 1 N 1 E 0 ; The simplest case
+@ LOC 0 1 N 1 E 0 ; Combination of parameters
+@ LOC 0 0 1 N 1 E 0 ; Combination of parameters
+@ LOC 1 N 0 1 E 0 ; Combination of parameters
+@ LOC 1 N 0 0 1 E 0 ; Combination of parameters
+@ LOC 1 N 0 0 1 E 0m ; Combination of parameters
+@ LOC 1 N 1 E 0 1 ; Combination of parameters
+@ LOC 1 N 1 E 0 1m ; Combination of parameters
+@ LOC 1 N 1 E 0 0 1 ; Combination of parameters
+@ LOC 1 N 1 E 0 0 1m ; Combination of parameters
+@ LOC 1 N 1 E 0 0 0 1 ; Combination of parameters
+@ LOC 1 N 1 E 0 0 0 1m ; Combination of parameters
+@ LOC 0 0 0 N 0 0 0 E -100000.00 0 0 0 ; Minimal values
+@ LOC 90 59 59.999 S 180 59 59.999 W 42849672.95m 90000000.00m 90000000.00m 90000000.00m ; Maximal values
+@ LOC 0 S 0 0 0.001 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 0.01 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 0.1 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 1.0 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 0 10 W 0 ; Float dd.ddd test
+@ LOC 0 S 0 W 0 0.01 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 0.10 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 1.0 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 10 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 100 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 1000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 10000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 100000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 1000000 ; Number to [mantisa,exponent] test
+@ LOC 0 S 0 W 0 10000000 ; Number to [mantisa,exponent] test
+@ LOC \# 16 00 00 00 00 00000000 00000000 00000000 ; Hexadecimal rdata
+@ TYPE29 \# 16 00 00 00 00 00000000 00000000 00000000 ; TYPE + Hexadecimal rdata
+@ TYPE29 0 N 0 E 0 ; TYPE
+@ loc 0 N 0 E 0 ; Type in lower-case
+
+; KO
+@ LOC
+@ LOC ; Empty rdata
+@ LOC \# 0 ; Hex empty rdata
+@ LOC \# ; Missing hex length
+@ LOC 91 0 0 N 0 0 0 E 0 0 0 0 ; Degree overflow
+@ LOC 0 60 0 N 0 0 0 E 0 0 0 0 ; Minute overflow
+@ LOC 0 0 60 0 N 0 0 0 E 0 0 0 0 ; Second overflow
+@ LOC 0 0 0 N 181 0 0 E 0 0 0 0 ; Degree overflow
+@ LOC 0 0 0 N 0 60 0 E 0 0 0 0 ; Minute overflow
+@ LOC 0 0 0 N 0 0 60 E 0 0 0 0 ; Second overflow
+@ LOC 0 0 0 N 0 0 0 E 42849672.96 0 0 0 ; Altitude overflow
+@ LOC 0 0 0 N 0 0 0 E 42849673 0 0 0 ; Altitude overflow
+@ LOC 0 0 0 N 0 0 0 E -100000.01 0 0 0 ; Altitude underflow
+@ LOC 0 0 0 N 0 0 0 E -100001 0 0 0 ; Altitude underflow
+@ LOC 0 0 0 N 0 0 0 E 0 90000000.01 0 0 ; Size overflow
+@ LOC 0 0 0 N 0 0 0 E 0 90000001 0 0 ; Size overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 90000000.01 0 ; HP overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 90000001 0 ; HP overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 0 90000000.01 ; VP overflow
+@ LOC 0 0 0 N 0 0 0 E 0 0 0 90000001 ; VP overflow
+@ LOC 1 1 E 0 ; Missing N or S
+@ LOC 1 x 1 E 0 ; Bad letter
+@ LOC 1 N 1 0 ; Missing E or W
+@ LOC 1 N 1 x 0 ; Bad letter
+@ LOC 1 N 1 E ; Missing altitude
+@ LOC 0 0 0 N 0 0 0 E 0 0 0 0 x ; Unexpected item
+@ LOC \# 17 00 00 00 00 00000000 00000000 00000000 00 ; Too long rdata
+@ LOC \# 17 00 00 00 00 00000000 00000000 00000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/42_LOC.out b/src/zscanner/test/cases/42_LOC.out
new file mode 100644
index 0000000..9c6580c
--- /dev/null
+++ b/src/zscanner/test/cases/42_LOC.out
@@ -0,0 +1,254 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138000EA608036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800003E88036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808000EA6000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE80800003E800989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE80800003E800989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=001216138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000012138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000012138036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000000128036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=000000128036EE808036EE8000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00000000800000008000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=009999996C79388159295F81FFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFFFF00989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFFF600989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFF9C00989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFFC1800989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000007FFFD8F000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00101613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00111613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00131613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00141613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00151613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00161613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00171613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00181613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00191613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00000000000000000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000008000000000989680
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=001D
+RDATA=00121613800000008000000000989680
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_LOC_DATA
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/43_EUI48.in b/src/zscanner/test/cases/43_EUI48.in
new file mode 100644
index 0000000..2da448f
--- /dev/null
+++ b/src/zscanner/test/cases/43_EUI48.in
@@ -0,0 +1,25 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ EUI48 00-00-00-00-00-00 ; The simplest case
+@ EUI48 FF-FF-FF-FF-FF-FF ; The maximal case
+@ EUI48 aa-bb-cc-dd-ee-ff ; Lower-case
+@ EUI48 \# 6 000000000000 ; Hexadecimal rdata
+@ TYPE108 \# 6 000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE108 00-00-00-00-00-00 ; TYPE
+@ eui48 00-00-00-00-00-00 ; Type in lower-case
+
+; KO
+@ EUI48
+@ EUI48 ; Empty rdata
+@ EUI48 \# 0 ; Hex empty rdata
+@ EUI48 \# ; Missing hex length
+@ EUI48 00-00-00-00-00 ; Too few hex pairs
+@ EUI48 00-00-00-00-00-00-00 ; Too many hex pairs
+@ EUI48 00-00-00-00-00-0 ; Missing char in a hex pair
+@ EUI48 00:00-00-00-00-00 ; Bad separator
+@ EUI48 00-00-00-x0-00-00 ; Bad character
+@ EUI48 00-00-00-00-00-00 x ; Unexpected item
+@ EUI48 \# 7 000000000000 00 ; Too long rdata
+@ EUI48 \# 7 000000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/43_EUI48.out b/src/zscanner/test/cases/43_EUI48.out
new file mode 100644
index 0000000..29f6bdb
--- /dev/null
+++ b/src/zscanner/test/cases/43_EUI48.out
@@ -0,0 +1,66 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=FFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=AABBCCDDEEFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006C
+RDATA=000000000000
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_EUI_LENGTH
+------
+WARNG=ZSCANNER_EBAD_EUI_LENGTH
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_CHAR_DASH
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/44_EUI64.in b/src/zscanner/test/cases/44_EUI64.in
new file mode 100644
index 0000000..1c70757
--- /dev/null
+++ b/src/zscanner/test/cases/44_EUI64.in
@@ -0,0 +1,25 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ EUI64 00-00-00-00-00-00-00-00 ; The simplest case
+@ EUI64 FF-FF-FF-FF-FF-FF-FF-FF ; The maximal case
+@ EUI64 aa-bb-cc-dd-ee-ff-01-02 ; Lower-case
+@ EUI64 \# 8 0000000000000000 ; Hexadecimal rdata
+@ TYPE109 \# 8 0000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE109 00-00-00-00-00-00-00-00 ; TYPE
+@ eui64 00-00-00-00-00-00-00-00 ; Type in lower-case
+
+; KO
+@ EUI64
+@ EUI64 ; Empty rdata
+@ EUI64 \# 0 ; Hex empty rdata
+@ EUI64 \# ; Missing hex length
+@ EUI64 00-00-00-00-00-00-00 ; Too few hex pairs
+@ EUI64 00-00-00-00-00-00-00-00-00 ; Too many hex pairs
+@ EUI64 00-00-00-00-00-00-00-0 ; Missing char in a hex pair
+@ EUI64 00:00-00-00-00-00-00-00 ; Bad separator
+@ EUI64 00-00-00-x0-00-00-00-00 ; Bad character
+@ EUI64 00-00-00-00-00-00-00-00 x ; Unexpected item
+@ EUI64 \# 9 0000000000000000 00 ; Too long rdata
+@ EUI64 \# 9 0000000000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/44_EUI64.out b/src/zscanner/test/cases/44_EUI64.out
new file mode 100644
index 0000000..745ba09
--- /dev/null
+++ b/src/zscanner/test/cases/44_EUI64.out
@@ -0,0 +1,66 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=FFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=AABBCCDDEEFF0102
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006D
+RDATA=0000000000000000
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_EUI_LENGTH
+------
+WARNG=ZSCANNER_EBAD_EUI_LENGTH
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_CHAR_DASH
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/45_NID.in b/src/zscanner/test/cases/45_NID.in
new file mode 100644
index 0000000..a85f9c3
--- /dev/null
+++ b/src/zscanner/test/cases/45_NID.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The NID is the same as the L64, so there are the differences and basics only.
+
+; OK
+@ NID 0 0000:0000:0000:0000 ; The simplest case
+@ NID \# 10 00000000000000000000 ; Hexadecimal rdata
+@ TYPE104 \# 10 00000000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE104 0 0000:0000:0000:0000 ; TYPE
+@ nid 0 0000:0000:0000:0000 ; Type in lower-case
+
+; KO
+@ NID
diff --git a/src/zscanner/test/cases/45_NID.out b/src/zscanner/test/cases/45_NID.out
new file mode 100644
index 0000000..e3da3ed
--- /dev/null
+++ b/src/zscanner/test/cases/45_NID.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0068
+RDATA=00000000000000000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/46_L32.in b/src/zscanner/test/cases/46_L32.in
new file mode 100644
index 0000000..1340573
--- /dev/null
+++ b/src/zscanner/test/cases/46_L32.in
@@ -0,0 +1,25 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ L32 0 0.0.0.0 ; The simplest case
+@ L32 65535 255.255.255.255 ; The maximal case
+@ L32 \# 6 000000000000 ; Hexadecimal rdata
+@ TYPE105 \# 6 000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE105 0 0.0.0.0 ; TYPE
+@ l32 0 0.0.0.0 ; Type in lower-case
+
+; KO
+@ L32
+@ L32 ; Empty rdata
+@ L32 \# 0 ; Hex empty rdata
+@ L32 \# ; Missing hex length
+@ L32 65536 0.0.0.0 ; Too big preference
+
+@ L32 0 0.0.0.256 ; 8-bit overflow
+@ L32 0 0.0.0 ; Short address
+@ L32 0 0.0.0.0.0 ; Long address
+@ L32 0 0.0.0.x ; Bad character
+@ L32 0 0.0.0.0 x ; Unexpected item
+@ L32 \# 7 000000000000 00 ; Too long rdata
+@ L32 \# 7 000000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/46_L32.out b/src/zscanner/test/cases/46_L32.out
new file mode 100644
index 0000000..9509b57
--- /dev/null
+++ b/src/zscanner/test/cases/46_L32.out
@@ -0,0 +1,60 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=FFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=0069
+RDATA=000000000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_IPV4
+------
+WARNG=ZSCANNER_EBAD_IPV4
+------
+WARNG=ZSCANNER_EBAD_IPV4
+------
+WARNG=ZSCANNER_EBAD_ADDRESS_CHAR
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/47_L64.in b/src/zscanner/test/cases/47_L64.in
new file mode 100644
index 0000000..7d1020a
--- /dev/null
+++ b/src/zscanner/test/cases/47_L64.in
@@ -0,0 +1,26 @@
+$ORIGIN .
+$TTL 1
+
+; OK
+@ L64 0 0000:0000:0000:0000 ; The simplest case
+@ L64 65535 FFFF:FFFF:FFFF:FFFF ; The maximal case
+@ L64 0 abcd:ef00:0000:0000 ; Lower-case
+@ L64 \# 10 00000000000000000000 ; Hexadecimal rdata
+@ TYPE106 \# 10 00000000000000000000 ; TYPE + Hexadecimal rdata
+@ TYPE106 0 0000:0000:0000:0000 ; TYPE
+@ l64 0 0000:0000:0000:0000 ; Type in lower-case
+
+; KO
+@ L64
+@ L64 ; Empty rdata
+@ L64 \# 0 ; Hex empty rdata
+@ L64 \# ; Missing hex length
+@ L64 65536 ; Too big preference
+@ L64 0 0000:0000:0000 ; Missing label
+@ L64 0 0000:0000:0000:0000:0000 ; Too many labels
+@ L64 0 0000:0000:0000:000 ; Missing hex character
+@ L64 0 0000:0000:0000-0000 ; Bad separator
+@ L64 0 0000:0000:0000:x000 ; Bad hex character
+@ L64 0 0000:0000:0000:0000 x ; Unexpected item
+@ L64 \# 11 00000000000000000000 00 ; Too long rdata
+@ L64 \# 11 00000000000000000000 ; Bad rdata length
diff --git a/src/zscanner/test/cases/47_L64.out b/src/zscanner/test/cases/47_L64.out
new file mode 100644
index 0000000..9184048
--- /dev/null
+++ b/src/zscanner/test/cases/47_L64.out
@@ -0,0 +1,68 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=FFFFFFFFFFFFFFFFFFFF
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=0000ABCDEF0000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006A
+RDATA=00000000000000000000
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
+WARNG=ZSCANNER_ENUMBER16_OVERFLOW
+------
+WARNG=ZSCANNER_EBAD_L64_LENGTH
+------
+WARNG=ZSCANNER_EBAD_L64_LENGTH
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_CHAR_COLON
+------
+WARNG=ZSCANNER_EBAD_HEX_CHAR
+------
+WARNG=ZSCANNER_EBAD_REST
+------
+WARNG=ZSCANNER_EBAD_HEX_RDATA
+------
+WARNG=ZSCANNER_EBAD_RDATA_LENGTH
+------
diff --git a/src/zscanner/test/cases/48_LP.in b/src/zscanner/test/cases/48_LP.in
new file mode 100644
index 0000000..bc537d0
--- /dev/null
+++ b/src/zscanner/test/cases/48_LP.in
@@ -0,0 +1,14 @@
+$ORIGIN .
+$TTL 1
+
+; The LP is the same as the MX, so there are the differences and basics only.
+
+; OK
+@ LP 1 mail ; Relative dname
+@ LP \# 3 0001 00 ; Hexadecimal rdata
+@ TYPE107 \# 3 0001 00 ; TYPE + Hexadecimal rdata
+@ TYPE107 1 @ ; TYPE
+@ lp 1 @ ; Type in lower-case
+
+; KO
+@ LP
diff --git a/src/zscanner/test/cases/48_LP.out b/src/zscanner/test/cases/48_LP.out
new file mode 100644
index 0000000..79ff530
--- /dev/null
+++ b/src/zscanner/test/cases/48_LP.out
@@ -0,0 +1,32 @@
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=0001 046D61696C00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=0001 00
+------
+OWNER=00
+CLASS=0001
+RRTTL=00000001
+RTYPE=006B
+RDATA=0001 00
+------
+WARNG=ZSCANNER_EBAD_NUMBER
+------
diff --git a/src/zscanner/test/cases/includes/include1 b/src/zscanner/test/cases/includes/include1
new file mode 100644
index 0000000..9de1859
--- /dev/null
+++ b/src/zscanner/test/cases/includes/include1
@@ -0,0 +1,9 @@
+$TTL 1
+
+a NS @
+
+$ORIGIN tld1a.
+a NS @
+
+$ORIGIN tld1b.
+a NS @
diff --git a/src/zscanner/test/cases/includes/include2 b/src/zscanner/test/cases/includes/include2
new file mode 100644
index 0000000..1e14e96
--- /dev/null
+++ b/src/zscanner/test/cases/includes/include2
@@ -0,0 +1,6 @@
+$TTL 1H
+
+b NS @
+
+$ORIGIN tld1a.
+b NS @
diff --git a/src/zscanner/test/cases/includes/include3 b/src/zscanner/test/cases/includes/include3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/zscanner/test/cases/includes/include3
diff --git a/src/zscanner/test/cases/includes/include4 b/src/zscanner/test/cases/includes/include4
new file mode 100644
index 0000000..7e8d5e2
--- /dev/null
+++ b/src/zscanner/test/cases/includes/include4
@@ -0,0 +1 @@
+a NS ; Missing data
diff --git a/src/zscanner/test/cases/includes/include5 b/src/zscanner/test/cases/includes/include5
new file mode 100644
index 0000000..ac98e01
--- /dev/null
+++ b/src/zscanner/test/cases/includes/include5
@@ -0,0 +1 @@
+$TTL x ; Bad number
diff --git a/src/zscanner/test/cases/includes/include6 b/src/zscanner/test/cases/includes/include6
new file mode 100644
index 0000000..b5e8cb8
--- /dev/null
+++ b/src/zscanner/test/cases/includes/include6
@@ -0,0 +1 @@
+$INCLUDE include2 ; Include in include
diff --git a/src/zscanner/test/processing.c b/src/zscanner/test/processing.c
new file mode 100644
index 0000000..b9319d5
--- /dev/null
+++ b/src/zscanner/test/processing.c
@@ -0,0 +1,212 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "zscanner/scanner_functions.h"
+
+#include <inttypes.h> // PRIu64
+#include <stdio.h> // printf
+
+#include "common/errcode.h" // knot_strerror
+#include "common/descriptor.h" // knot_rrtype_to_string
+#include "zscanner/scanner.h" // scanner_t
+
+#define ERROR_CODE_TO_STRING(code) [code - ZSCANNER_UNCOVERED_STATE] = #code
+const char *error_names[] = {
+ ERROR_CODE_TO_STRING(ZSCANNER_UNCOVERED_STATE),
+ ERROR_CODE_TO_STRING(ZSCANNER_ELEFT_PARENTHESIS),
+ ERROR_CODE_TO_STRING(ZSCANNER_ERIGHT_PARENTHESIS),
+ ERROR_CODE_TO_STRING(ZSCANNER_EUNSUPPORTED_TYPE),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_PREVIOUS_OWNER),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_DNAME_CHAR),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_OWNER),
+ ERROR_CODE_TO_STRING(ZSCANNER_ELABEL_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_EDNAME_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_NUMBER),
+ ERROR_CODE_TO_STRING(ZSCANNER_ENUMBER64_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_ENUMBER32_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_ENUMBER16_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_ENUMBER8_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_EFLOAT_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_ERDATA_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_EITEM_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_ADDRESS_CHAR),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_IPV4),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_IPV6),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_GATEWAY),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_GATEWAY_KEY),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_APL),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_RDATA),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_HEX_RDATA),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_HEX_CHAR),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_BASE64_CHAR),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_BASE32HEX_CHAR),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_REST),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TIMESTAMP_CHAR),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TIMESTAMP_LENGTH),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TIMESTAMP),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_DATE),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TIME),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TIME_UNIT),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_BITMAP),
+ ERROR_CODE_TO_STRING(ZSCANNER_ETEXT_OVERFLOW),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TEXT_CHAR),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TEXT),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_DIRECTIVE),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_TTL),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_ORIGIN),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_INCLUDE_FILENAME),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_INCLUDE_ORIGIN),
+ ERROR_CODE_TO_STRING(ZSCANNER_EUNPROCESSED_INCLUDE),
+ ERROR_CODE_TO_STRING(ZSCANNER_EUNOPENED_INCLUDE),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_RDATA_LENGTH),
+ ERROR_CODE_TO_STRING(ZSCANNER_ECANNOT_TEXT_DATA),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_LOC_DATA),
+ ERROR_CODE_TO_STRING(ZSCANNER_EUNKNOWN_BLOCK),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_ALGORITHM),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_CERT_TYPE),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_EUI_LENGTH),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_L64_LENGTH),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_CHAR_COLON),
+ ERROR_CODE_TO_STRING(ZSCANNER_EBAD_CHAR_DASH),
+};
+#define ERROR_CODE_NAME(code) error_names[code - ZSCANNER_UNCOVERED_STATE]
+
+const char *separator = "------\n";
+
+static void print_wire_dname(const uint8_t *dname, uint32_t dname_length)
+{
+ uint32_t label_length = 0, i = 0;
+
+ for (i = 0; i < dname_length; i++) {
+ if (label_length == 0) {
+ label_length = dname[i];
+ printf("(%u)", label_length);
+ continue;
+ }
+ printf("%c", (char)dname[i]);
+ label_length--;
+ }
+}
+
+void empty_process(const scanner_t *s)
+{
+ (void)s;
+}
+
+void debug_process_error(const scanner_t *s)
+{
+ if (s->stop == true) {
+ printf("LINE(%03"PRIu64") ERROR(%s) FILE(%s) NEAR(%s)\n",
+ s->line_counter,
+ knot_strerror(s->error_code),
+ s->file_name,
+ s->buffer);
+ } else {
+ printf("LINE(%03"PRIu64") WARNING(%s) FILE(%s) NEAR(%s)\n",
+ s->line_counter,
+ knot_strerror(s->error_code),
+ s->file_name,
+ s->buffer);
+ }
+ fflush(stdout);
+}
+
+void debug_process_record(const scanner_t *s)
+{
+ uint32_t block, block_length, i;
+
+ char rclass[32];
+ char rtype[32];
+
+ if (knot_rrclass_to_string(s->r_class, rclass, sizeof(rclass)) > 0 &&
+ knot_rrtype_to_string(s->r_type, rtype, sizeof(rtype)) > 0) {
+ printf("LINE(%03"PRIu64") %s %u %*s ",
+ s->line_counter, rclass, s->r_ttl, 5, rtype);
+ } else {
+ printf("LINE(%03"PRIu64") %u %u %*u ",
+ s->line_counter, s->r_class, s->r_ttl, 5, s->r_type);
+ }
+
+ print_wire_dname(s->r_owner, s->r_owner_length);
+
+ printf(" #%u/%uB:", s->r_data_blocks_count, s->r_data_length);
+
+ for (block = 1; block <= s->r_data_blocks_count; block++) {
+ block_length =
+ s->r_data_blocks[block] - s->r_data_blocks[block - 1];
+ printf(" (%u)", block_length);
+
+ for (i = s->r_data_blocks[block - 1];
+ i < s->r_data_blocks[block];
+ i++) {
+ printf("%02X", (s->r_data)[i]);
+ }
+ }
+ printf("\n");
+ fflush(stdout);
+}
+
+void test_process_error(const scanner_t *s)
+{
+ if (s->stop == true) {
+ printf("ERROR=%s\n%s", ERROR_CODE_NAME(s->error_code), separator);
+ } else {
+ printf("WARNG=%s\n%s", ERROR_CODE_NAME(s->error_code), separator);
+ }
+ fflush(stdout);
+}
+
+void test_process_record(const scanner_t *s)
+{
+ uint32_t block, i;
+
+ printf("OWNER=");
+ for (i = 0; i < s->r_owner_length; i++) {
+ printf("%02X", s->r_owner[i]);
+ }
+ printf("\n");
+ printf("CLASS=%04X\n", s->r_class);
+ printf("RRTTL=%08X\n", s->r_ttl);
+ printf("RTYPE=%04X\n", s->r_type);
+ printf("RDATA=");
+ for (block = 1; block <= s->r_data_blocks_count; block++) {
+ if (block > 1) {
+ printf(" ");
+ }
+
+ for (i = s->r_data_blocks[block - 1];
+ i < s->r_data_blocks[block];
+ i++) {
+ printf("%02X", (s->r_data)[i]);
+ }
+ }
+ printf("\n%s", separator);
+ fflush(stdout);
+}
+
+void dump_rdata(const scanner_t *s)
+{
+ uint32_t block, i;
+
+ for (block = 1; block <= s->r_data_blocks_count; block++) {
+ for (i = s->r_data_blocks[block - 1];
+ i < s->r_data_blocks[block];
+ i++) {
+ printf("%c", (s->r_data)[i]);
+ }
+ }
+}
diff --git a/src/knot/zone/zone-dump-text.h b/src/zscanner/test/processing.h
index 3d26742..26db215 100644
--- a/src/knot/zone/zone-dump-text.h
+++ b/src/zscanner/test/processing.h
@@ -14,33 +14,33 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
- * \file zone-dump-text.h
+ * \file processing.h
*
- * \author Jan Kadlec <jan.kadlec@nic.cz>
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
*
- * \brief Functions for dumping zone to text file.
+ * \brief Zone scanner test functions.
*
- * \addtogroup zone-load-dump
+ * \addtogroup zone_scanner_test
* @{
*/
-#ifndef _KNOT_ZONE_DUMP_TEXT_H_
-#define _KNOT_ZONE_DUMP_TEXT_H_
+#ifndef _ZSCANNER__TEST_FUNCTIONS_H_
+#define _ZSCANNER__TEST_FUNCTIONS_H_
-#include "libknot/util/descriptor.h"
-#include "libknot/zone/zone.h"
+#include "zscanner/scanner.h"
-/*!
- * \brief Dumps given zone to text (BIND-like) file.
- *
- * \param zone Zone to be saved.
- * \param File file to write to.
- *
- * \retval KNOT_EOK on success.
- * \retval KNOT_EINVAL if the specified file is not valid for writing.
- */
-int zone_dump_text(knot_zone_contents_t *zone, FILE *f);
+void empty_process(const scanner_t *scanner);
+
+void debug_process_error(const scanner_t *scanner);
+
+void debug_process_record(const scanner_t *scanner);
+
+void test_process_error(const scanner_t *scanner);
+
+void test_process_record(const scanner_t *scanner);
+
+void dump_rdata(const scanner_t *scanner);
-#endif // _KNOT_ZONE_DUMP_TEXT_H_
+#endif // _ZSCANNER__TEST_FUNCTIONS_H_
/*! @} */
diff --git a/src/zscanner/test/run_tests.sh b/src/zscanner/test/run_tests.sh
new file mode 100644
index 0000000..2bbdad8
--- /dev/null
+++ b/src/zscanner/test/run_tests.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+TESTS_DIR="/home/ondrej/Projects/knot/build/../src/zscanner/test/cases"
+OUTS_DIR="/home/ondrej/Projects/knot/build/src/zscanner/test/.out"
+TEST_BIN="./../zscanner-tool -m 2"
+
+# Delete temporary output directory at exit.
+trap "chmod -R u+rw ${OUTS_DIR} && rm -rf ${OUTS_DIR}" EXIT
+
+# If an argument -> verbose mode (stores result in /tmp).
+if [ $# -eq 0 ]; then
+ RESULT_DIR=`mktemp -d /tmp/zscanner_test.XXXX`
+ echo "ZSCANNER TEST ${RESULT_DIR}"
+fi
+
+# Create output directory.
+mkdir -p "${OUTS_DIR}"
+
+# Run zscanner on all test zone files.
+for file in $(find "${TESTS_DIR}" -name "*.in" | sort -n); do
+ fileout="$(basename "${file}" .in).out"
+
+ # Run zscanner.
+ ${TEST_BIN} . "${file}" > "${OUTS_DIR}/${fileout}"
+
+ # Compare result with the reference one.
+ cmp -s "${OUTS_DIR}/${fileout}" "${TESTS_DIR}/${fileout}"
+
+ RET=$?
+
+ # Check for differences.
+ if [ $RET -ne 0 ]; then
+ # If verbose print diff.
+ if [ $# -eq 0 ]; then
+ echo "\n=== ${fileout} DIFF ======================"
+ diff "${OUTS_DIR}/${fileout}" "${TESTS_DIR}/${fileout}"
+ fi
+ fi
+done
+
+# Store test result.
+if [ $# -eq 0 ]; then
+ cp -a "${OUTS_DIR}/." "${RESULT_DIR}/"
+ echo "\nFINISHED ${RESULT_DIR}"
+fi
diff --git a/src/zscanner/test/run_tests.sh.in b/src/zscanner/test/run_tests.sh.in
new file mode 100644
index 0000000..fc00c57
--- /dev/null
+++ b/src/zscanner/test/run_tests.sh.in
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+TESTS_DIR="@abs_srcdir@/cases"
+OUTS_DIR="@abs_builddir@/.out"
+TEST_BIN="@builddir@/../zscanner-tool -m 2"
+
+# Delete temporary output directory at exit.
+trap "chmod -R u+rw ${OUTS_DIR} && rm -rf ${OUTS_DIR}" EXIT
+
+# If an argument -> verbose mode (stores result in /tmp).
+if [ $# -eq 0 ]; then
+ RESULT_DIR=`mktemp -d /tmp/zscanner_test.XXXX`
+ echo "ZSCANNER TEST ${RESULT_DIR}"
+fi
+
+# Create output directory.
+mkdir -p "${OUTS_DIR}"
+
+# Run zscanner on all test zone files.
+for file in $(find "${TESTS_DIR}" -name "*.in" | sort -n); do
+ fileout="$(basename "${file}" .in).out"
+
+ # Run zscanner.
+ ${TEST_BIN} . "${file}" > "${OUTS_DIR}/${fileout}"
+
+ # Compare result with the reference one.
+ cmp -s "${OUTS_DIR}/${fileout}" "${TESTS_DIR}/${fileout}"
+
+ RET=$?
+
+ # Check for differences.
+ if [ $RET -ne 0 ]; then
+ # If verbose print diff.
+ if [ $# -eq 0 ]; then
+ echo "\n=== ${fileout} DIFF ======================"
+ diff "${OUTS_DIR}/${fileout}" "${TESTS_DIR}/${fileout}"
+ fi
+ fi
+done
+
+# Store test result.
+if [ $# -eq 0 ]; then
+ cp -a "${OUTS_DIR}/." "${RESULT_DIR}/"
+ echo "\nFINISHED ${RESULT_DIR}"
+fi
diff --git a/src/zscanner/test/tests.c b/src/zscanner/test/tests.c
new file mode 100644
index 0000000..fdd87cc
--- /dev/null
+++ b/src/zscanner/test/tests.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2011 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 <config.h>
+#include "zscanner/test/tests.h"
+
+#include <inttypes.h> // PRIu64
+#include <stdio.h> // printf
+#include <time.h> // mktime
+#include <stdlib.h> // printf
+#include "../scanner_functions.h" // date_to_timestamp
+
+int test__date_to_timestamp()
+{
+ time_t ref_timestamp, max_timestamp;
+ uint32_t test_timestamp;
+ uint8_t buffer[16];
+ uint64_t val1, val2; // For time_t type unification.
+ struct tm tm;
+
+ // Set UTC for strftime.
+ putenv("TZ=UTC");
+ tzset();
+
+ // Get maximal allowed timestamp.
+ strptime("21051231235959", "%Y%m%d%H%M%S", &tm);
+ max_timestamp = mktime(&tm);
+
+ // Testing loop over whole input interval.
+ for (ref_timestamp = 0;
+ ref_timestamp < max_timestamp;
+ ref_timestamp += 30) {
+ // Get reference (correct) timestamp.
+ strftime((char*)buffer, sizeof(buffer), "%Y%m%d%H%M%S",
+ gmtime(&ref_timestamp));
+
+ // Get testing timestamp.
+ date_to_timestamp(buffer, &test_timestamp);
+
+ // Some continuous loging.
+ if (ref_timestamp % 10000000 == 0) {
+ val1 = ref_timestamp;
+ printf("%s = %"PRIu64"\n", buffer, val1);
+ }
+
+ // Comparing results.
+ if (ref_timestamp != test_timestamp) {
+ val1 = ref_timestamp;
+
+ if (ref_timestamp > test_timestamp) {
+ val2 = ref_timestamp - test_timestamp;
+ printf("%s = %"PRIu64", in - out = %"PRIu64"\n",
+ buffer, val1, val2);
+ } else {
+ val2 = test_timestamp - ref_timestamp;
+ printf("%s = %"PRIu64", out - in = %"PRIu64"\n",
+ buffer, val1, val2);
+ }
+
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/tests/libknot/libknot/cuckoo_tests.h b/src/zscanner/test/tests.h
index b6b0db8..ab5f426 100644
--- a/src/tests/libknot/libknot/cuckoo_tests.h
+++ b/src/zscanner/test/tests.h
@@ -13,13 +13,22 @@
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 tests.h
+ *
+ * \author Daniel Salzman <daniel.salzman@nic.cz>
+ *
+ * \brief Zone scanner test functions.
+ *
+ * \addtogroup zone_scanner_test
+ * @{
+ */
-#ifndef _KNOTD_CUCKOO_TESTS_H_
-#define _KNOTD_CUCKOO_TESTS_H_
+#ifndef _ZSCANNER__TESTS_H_
+#define _ZSCANNER__TESTS_H_
-#include "common/libtap/tap_unit.h"
+int test__date_to_timestamp();
-/* Unit API. */
-unit_api cuckoo_tests_api;
+#endif // _ZSCANNER__TESTS_H_
-#endif /* _KNOTD_CUCKOO_TESTS_H_ */
+/*! @} */
diff --git a/src/zscanner/test/zscanner-tool.c b/src/zscanner/test/zscanner-tool.c
new file mode 100644
index 0000000..c6a728d
--- /dev/null
+++ b/src/zscanner/test/zscanner-tool.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2011 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 <config.h>
+#include <inttypes.h> // PRIu64
+#include <stdio.h> // printf
+#include <stdlib.h> // atoi
+#include <getopt.h> // getopt
+
+#include "common/errcode.h" // knot_strerror
+#include "zscanner/file_loader.h" // file_loader
+#include "zscanner/test/processing.h" // processing functions
+#include "zscanner/test/tests.h" // test functions
+
+#define DEFAULT_MODE 1
+
+void help(void)
+{
+ printf("\nZone scanner testing tool.\n"
+ "Usage: zscanner-tool [parameters] origin zonefile\n"
+ "\n"
+ "Parameters:\n"
+ " -m [0,1,2] Processing mode.\n"
+ " 0 Empty output.\n"
+ " 1 Debug output (DEFAULT).\n"
+ " 2 Test output.\n"
+ " -t Launch unit tests.\n"
+ " -h Print this help.\n");
+}
+
+int main(int argc, char *argv[])
+{
+ // Parsed command line arguments.
+ int c = 0, li = 0;
+ int ret, mode = DEFAULT_MODE, test = 0;
+ file_loader_t *fl;
+ const char *origin;
+ const char *zone_file;
+
+ // Command line long options.
+ struct option opts[] = {
+ {"mode", required_argument, 0, 'm'},
+ {"test", no_argument, 0, 't'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ // Command line options processing.
+ while ((c = getopt_long(argc, argv, "m:th", opts, &li)) != -1) {
+ switch (c) {
+ case 'm':
+ mode = atoi(optarg);
+ break;
+ case 't':
+ test = 1;
+ break;
+ case 'h': // Fall through.
+ default:
+ help();
+ return EXIT_FAILURE;
+ }
+ }
+
+ if (test == 1) {
+ test__date_to_timestamp();
+ } else {
+ // Check if there are 2 remaining non-options.
+ if (argc - optind != 2) {
+ help();
+ return EXIT_FAILURE;
+ }
+
+ zone_file = argv[optind];
+ origin = argv[optind + 1];
+
+ // Create appropriate file loader.
+ switch (mode) {
+ case 0:
+ fl = file_loader_create(origin,
+ zone_file,
+ DEFAULT_CLASS,
+ DEFAULT_TTL,
+ &empty_process,
+ &empty_process,
+ NULL);
+ break;
+ case 1:
+ fl = file_loader_create(origin,
+ zone_file,
+ DEFAULT_CLASS,
+ DEFAULT_TTL,
+ &debug_process_record,
+ &debug_process_error,
+ NULL);
+ break;
+ case 2:
+ fl = file_loader_create(origin,
+ zone_file,
+ DEFAULT_CLASS,
+ DEFAULT_TTL,
+ &test_process_record,
+ &test_process_error,
+ NULL);
+ break;
+ default:
+ printf("Bad mode number!\n");
+ help();
+ return EXIT_FAILURE;
+ }
+
+ // Check file loader.
+ if (fl != NULL) {
+ ret = file_loader_process(fl);
+
+ switch (ret) {
+ case KNOT_EOK:
+ if (mode == DEFAULT_MODE) {
+ printf("Zone file has been processed "
+ "successfully\n");
+ }
+ file_loader_free(fl);
+ break;
+
+ case FLOADER_ESCANNER:
+ if (mode == DEFAULT_MODE) {
+ printf("Zone processing has stopped with "
+ "%"PRIu64" warnings/errors!\n",
+ fl->scanner->error_counter);
+ }
+ file_loader_free(fl);
+ return EXIT_FAILURE;
+
+ default:
+ if (mode == DEFAULT_MODE) {
+ printf("%s\n", knot_strerror(ret));
+ }
+ file_loader_free(fl);
+ return EXIT_FAILURE;
+ }
+ } else {
+ printf("File open error!\n");
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/tests/Makefile b/tests/Makefile
deleted file mode 100644
index bd3e9aa..0000000
--- a/tests/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-BASE = ../src
-CFLAGS += -std=gnu99 -g -I.. -I$(BASE) -I$(BASE)/libknot -I/usr/local/include
-
-chkjournal: chkjournal.c $(BASE)/libknotd.la
- libtool --mode=link $(CC) $(CFLAGS) chkjournal.c $(BASE)/libknotd.la -o chkjournal
-chkjournal-i386:
- @echo "!!! Make sure knot is compiled with -fpack-struct=4"
- @grep -q -- "-fpack-struct=4" $(BASE)/Makefile || exit 1
- libtool --mode=link $(CC) $(CFLAGS) -fpack-struct=4 chkjournal.c $(BASE)/libknotd.la -o chkjournal-i386
-chkjournal-amd64:
- @echo "!!! Make sure knot is compiled with -fpack-struct=8"
- @grep -q -- "-fpack-struct=8" $(BASE)/Makefile || exit 1
- libtool --mode=link $(CC) $(CFLAGS) -fpack-struct=8 chkjournal.c $(BASE)/libknotd.la -o chkjournal-amd64
-clean:
- rm chkjournal chkjournal-i386 chkjournal-amd64
-
diff --git a/tests/chkjournal.c b/tests/chkjournal.c
deleted file mode 100644
index b429a87..0000000
--- a/tests/chkjournal.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/* Copyright (C) 2011 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/>.
-
- Usage: chkjournal --help
-
- How to make:
- (for this computer): make chkjournal
- (for 32bit journals): make chkjournal-i386
- (for 64bit journal): make chkjournal-amd64
-
- !!! For specific versions, make sure the libknotd.la is compiled
- with -fpack-struct=4 for 32bit or -fpack-struct=8 for 64bit chkjournal.
- f.e.:
- $ cd <knot_root>
- $ CFLAGS="-fpack-struct=4" ./configure
- $ make clean && make -j8
- $ cd tests
- $ make chkjournal-i386
- */
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <getopt.h>
-#include <assert.h>
-#include <sys/stat.h>
-
-#ifndef KNOT_RRSET_DEBUG
-#define KNOT_RRSET_DEBUG 1
-#endif
-
-//#define KNOT_RDATA_DEBUG 1
-#include "src/common/log.h"
-#include "src/common/crc.h"
-#include "src/common/errcode.h"
-#include "src/knot/server/journal.h"
-#include "src/knot/server/zones.h"
-#include "src/libknot/updates/changesets.h"
-#include "src/libknot/util/debug.h"
-#include "src/libknot/util/debug.c"
-#include "config.h"
-
-/* Alignment. */
-static size_t ALIGNMENT = 1;
-static inline size_t a(size_t s) {
- return s + s % ALIGNMENT;
-}
-static size_t PADDING = 4;
-
-/*! \brief Return 'serial_from' part of the key. */
-static inline uint32_t ixfrdb_key_from(uint64_t k)
-{
- /* 64 32 0
- * key = [TO | FROM]
- * Need: Least significant 32 bits.
- */
- return (uint32_t)(k & ((uint64_t)0x00000000ffffffff));
-}
-
-/*----------------------------------------------------------------------------*/
-
-/*! \brief Return 'serial_to' part of the key. */
-static inline uint32_t ixfrdb_key_to(uint64_t k)
-{
- /* 64 32 0
- * key = [TO | FROM]
- * Need: Most significant 32 bits.
- */
- return (uint32_t)(k >> (uint64_t)32);
-}
-
-/*----------------------------------------------------------------------------*/
-
-#define MAGIC_LENGTH 7
-
-enum {
- SHOW = 0,
- UPDATE,
- FIXCRC,
- DUMP,
- XDUMP
-};
-
-void help(int argc, char **argv)
-{
- printf("Usage: chkjournal [parameters] <journal_file>\n");
- printf("Parameters:\n"
- " -p, --padding=N Padding after each node.\n"
- " -a, --align=N Expect journal structures aligned to N bytes.\n"
- " -f, --fixcrc Recompute CRC32.\n"
- " -u, --update Update version to latest.\n"
- " -x, --xdump=id Dump changeset (hexdump).\n"
- " -d, --dump=id Dump changeset (parsed).\n"
- " -h, --help Print help and usage.\n"
- );
-}
-
-/* Show. */
-int walkf(journal_t *j, journal_node_t *n) {
- printf("entry '%zu' flags=0x%hu fpos=%u len=%u\n", n->id, n->flags, n->pos, n->len);
- return 0;
-}
-
-int show(const char *fname)
-{
- /* Open journal. */
- journal_t *j = journal_open(fname, -1, 0, 0);
- if (j == NULL) {
- fprintf(stderr, "error: couldn't open journal '%s'\n", fname);
- return 1;
- }
-
- printf("journal: %s max_nodes=%hu queue=%u..%u\n",
- fname, j->max_nodes, j->qtail, j->qhead);
- journal_walk(j, walkf);
- journal_close(j);
- return 0;
-}
-
-/* Fix CRC. */
-int fixcrc(const char *fname)
-{
- int fd = open(fname, O_RDONLY);
- if (fd < 0) {
- return 1;
- }
-
- int ret = 1;
- if (journal_update_crc(fd) == 0) {
- ret = 0;
- }
-
- close(fd);
- return ret;
-}
-
-/* Fix file positions. */
-static int FPOSDELTA = 0;
-int walkfix(journal_t *j, journal_node_t *n) {
- n->pos += FPOSDELTA;
- journal_update(j, n);
- return 0;
-}
-
-int fixfpos(const char *fname, int delta)
-{
- /* Open journal. */
- journal_t *j = journal_open(fname, -1, 0, 0);
- if (j == NULL) {
- fprintf(stderr, "error: couldn't open journal '%s'\n", fname);
- return 1;
- }
- FPOSDELTA = delta;
- journal_walk(j, walkfix);
- journal_close(j);
- return 0;
-}
-
-/* Update journal file. */
-int update(const char *fname)
-{
- int fd = open(fname, O_RDONLY);
- if (fd < 0) {
- return 1;
- }
-
- /* Check source magic bytes. */
- int rb = 0;
- int ret = 0;
- char buf[4096];
- char mbytes[MAGIC_LENGTH] = {};
- read(fd, mbytes, MAGIC_LENGTH);
- if (memcmp(mbytes, "knot100", MAGIC_LENGTH) == 0) {
- /* 100 -> 101 +crc after MB. */
- char *nfname = malloc(strlen(fname) + 4 + 1);
- assert(nfname != NULL);
- strncpy(nfname, fname, strlen(fname));
- strncat(nfname, ".new", 4);
- int nfd = open(nfname, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
- const char nmbytes[] = "knot101";
- if (nfd >= 0) {
- /* Extend header. */
- write(nfd, nmbytes, MAGIC_LENGTH);
- write(nfd, buf, sizeof(crc_t));
- read(fd, buf, sizeof(uint16_t) * 3);
- write(nfd, buf, sizeof(uint16_t) * 3);
-
- /* Copy nodes. */
- uint16_t ncount = *((uint16_t*)buf) + 1;
- printf("Will update %hu nodes.\n", ncount - 1);
- for (uint16_t i = 0; i < ncount; ++i) {
- /* Copy id+flags. */
- read(fd, buf, a(sizeof(uint64_t)+sizeof(uint16_t)));
- write(nfd, buf, a(sizeof(uint64_t)+sizeof(uint16_t)));
- read(fd, buf, a(2*sizeof(uint32_t)));
- *((uint32_t*)buf) += sizeof(crc_t);
- write(nfd, buf, a(2*sizeof(uint32_t)));
- /* Copy padding. */
- read(fd, buf, PADDING);
- write(nfd, buf, PADDING);
- }
-
- /* Copy remaining. */
- while((rb = read(fd, buf, sizeof(buf))) > 0) {
- if (write(nfd, buf, rb) != rb) {
- ret = 1;
- break;
- }
- }
- /* Update CRC. */
- if (ret == 0) {
- journal_update_crc(nfd);
- }
- }
-
- /* Replace if success. */
- close(nfd);
- close(fd);
- if (ret == 0) {
- remove(fname);
- rename(nfname, fname);
- printf("Converted journal v1.0.0 -> v1.0.1\n");
- }
- free(nfname);
- } else if (memcmp(mbytes, "knot101", MAGIC_LENGTH) == 0) {
- /* 101 -> 102, transactions, +uint16 'next' in jnode */
- char *nfname = malloc(strlen(fname) + 4 + 1);
- assert(nfname != NULL);
- strncpy(nfname, fname, strlen(fname));
- strncat(nfname, ".new", 4);
- int nfd = open(nfname, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
- size_t hs102 = (MAGIC_LENGTH + sizeof(crc_t) + sizeof(uint16_t) * 3);
- const char nmbytes[] = "knot102";
-
- if (nfd >= 0) {
- /* Copy header. */
- lseek(fd, 0, SEEK_SET);
- read(fd, buf, hs102);
- write(nfd, buf, hs102);
- lseek(nfd, 0, SEEK_SET);
- write(nfd, nmbytes, MAGIC_LENGTH);
-
- /* Read node count. */
- lseek(fd, MAGIC_LENGTH + sizeof(crc_t), SEEK_SET);
- uint16_t ncount = 0;
- read(fd, &ncount, sizeof(uint16_t));
- printf("Will update %hu nodes.\n", ncount);
- ncount += 1; /* Free segment. */
- lseek(fd, hs102, SEEK_SET);
- lseek(nfd, hs102, SEEK_SET);
-
- /* Extend nodes. */
- /*! \todo Calculate offset from difference of struct size. */
- for (uint16_t i = 0; i < ncount; ++i) {
- /* Copy id+flags. */
- read(fd, buf, a(sizeof(uint64_t)+sizeof(uint16_t)));
- write(nfd, buf, sizeof(uint64_t)+sizeof(uint16_t));
- /* Append 'next'. */
- memset(buf, 0, sizeof(uint16_t));
- write(nfd, buf, sizeof(uint16_t));
-
- /* Copy rest. */
- read(fd, buf, a(2*sizeof(uint32_t)));
- //*((uint32_t*)buf) += offs;
- write(nfd, buf, a(2*sizeof(uint32_t)));
- /* Copy padding. */
- read(fd, buf, PADDING);
- write(nfd, buf, PADDING);
- }
-
- /* Copy remaining. */
- while((rb = read(fd, buf, sizeof(buf))) > 0) {
- if (write(nfd, buf, rb) != rb) {
- ret = 1;
- break;
- }
- }
- /* Update CRC. */
- if (ret == 0) {
- journal_update_crc(nfd);
- }
- }
-
- /* Replace if success. */
- close(nfd);
- close(fd);
- if (ret == 0) {
- remove(fname);
- rename(nfname, fname);
- printf("Converted journal v1.0.1-> v1.0.2\n");
- }
- free(nfname);
- } else if (memcmp(mbytes, "knot102", MAGIC_LENGTH) == 0) {
- /* Update magic bytes. */
- const char nmbytes[] = "knot104";
- int nfd = open(fname, O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
- lseek(nfd, 0, SEEK_SET);
- write(nfd, nmbytes, MAGIC_LENGTH);
- journal_update_crc(nfd);
- close(nfd);
- printf("Converted journal v1.0.2-> v.1.0.4\n");
- } else if (memcmp(mbytes, "knot104", MAGIC_LENGTH) == 0) {
- /* Update magic bytes and add 4bytes to each journal node. */
- const char nmbytes[] = "knot105";
- int nfd = open(fname, O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
- lseek(nfd, 0, SEEK_SET);
- write(nfd, nmbytes, MAGIC_LENGTH);
- journal_update_crc(nfd);
- close(nfd);
-
- /* Fix crc. */
- fixcrc(fname);
-
- /* Open as source journal. */
- journal_t *src = journal_open(fname, 0, 0, 0);
- assert(src != NULL);
-
- /* Recreate as new journal. */
- char *nfname = malloc(strlen(fname) + 4 + 1);
- assert(nfname != NULL);
- strncpy(nfname, fname, strlen(fname));
- strncat(nfname, ".new", 4);
- journal_create(nfname, src->max_nodes);
- journal_t *dst = journal_open(nfname, 0, 0, 0);
- assert(dst != NULL);
-
- /* Convert journal entries, adding dummy flags. */
- uint32_t flags = 1;
- size_t i = src->qhead;
- for(; i != src->qtail; i = (i + 1) % src->max_nodes) {
- journal_node_t *n = src->nodes + i;
- char *ibuf = malloc(n->len + sizeof(uint32_t));
- memset(ibuf, &flags, sizeof(uint32_t));
- journal_read(src, n->id, NULL, ibuf + sizeof(uint32_t));
- journal_write(dst, n->id, ibuf, n->len + sizeof(uint32_t));
- free(ibuf);
- }
- journal_close(src);
- journal_close(dst);
-
- /* Switch journals. */
- remove(fname);
- rename(nfname, fname);
- free(nfname);
- printf("Converted journal v1.0.4-> v.1.0.5\n");
- } else {
- close(fd);
- }
-
-
- return ret;
-}
-
-/* Hexdump. */
-int xdump(const char *fname, uint64_t id)
-{
- /* Open journal. */
- journal_t *j = journal_open(fname, -1, 0, 0);
- if (j == NULL) {
- fprintf(stderr, "error: couldn't open journal '%s'\n", fname);
- return 1;
- }
-
- int ret = 1;
- journal_node_t *n = NULL;
- journal_fetch(j, id, NULL, &n);
- if (n != NULL) {
- char *buf = malloc(n->len);
- assert(buf != NULL);
- journal_read(j, id, NULL, buf);
- size_t rf = 0;
- while(rf < n->len) {
- if (rf % 16 == 0) printf("\n%08lx |", (unsigned long)rf);
- printf(" %02x", (unsigned)buf[rf] & 0xffU);
- ++rf;
- }
- printf("\n");
- printf("-- index %llu fpos=%u length=%u\n",
- (unsigned long long)id, n->pos, n->len);
- free(buf);
- ret = 0;
- }
-
- journal_close(j);
- return ret;
-}
-
-/* Hexdump. */
-int dump(const char *fname, uint64_t id)
-{
- /* Open journal. */
- journal_t *j = journal_open(fname, -1, 0, 0);
- if (j == NULL) {
- fprintf(stderr, "error: couldn't open journal '%s'\n", fname);
- return 1;
- }
-
- journal_node_t *n = NULL;
- journal_fetch(j, id, NULL, &n);
- if (n == NULL) {
- journal_close(j);
- return 1;
- }
-
- /* Reserve and read changeset. */
- knot_changesets_t* chsets = malloc(sizeof(knot_changesets_t));
- assert(chsets != NULL);
- memset(chsets, 0, sizeof(knot_changesets_t));
- chsets->count = 1;
- knot_changesets_check_size(chsets);
- assert(chsets->sets != NULL);
- knot_changeset_t *chs = chsets->sets;
- memset(chs, 0, sizeof(knot_changeset_t));
- chs->serial_from = ixfrdb_key_from(n->id);
- chs->serial_to = ixfrdb_key_to(n->id);
- chs->data = malloc(n->len);
- assert(chs->data != NULL);
- journal_read(j, n->id, NULL, chs->data);
- chs->size = chs->allocated = n->len;
-
- /* Unpack */
- int ks = zones_changesets_from_binary(chsets);
- printf("=== index %llu fpos=%u length=%u\n",
- (unsigned long long)id, n->pos, n->len);
-
- /* TODO: dump wireformat? */
- printf("--- %zu records\n", chs->remove_count);
- for (unsigned i = 0; i < chs->remove_count; ++i) {
- knot_rrset_dump(chs->remove[i], 1);
- }
- printf("+++ %zu records\n", chs->add_count);
- for (unsigned i = 0; i < chs->add_count; ++i) {
- knot_rrset_dump(chs->add[i], 1);
- }
- printf("=== index %llu fpos=%u length=%u\n",
- (unsigned long long)id, n->pos, n->len);
-
- /* Close. */
- //knot_free_changesets(&chsets);
- journal_close(j);
- return 0;
-}
-
-int main(int argc, char *argv[])
-{
- /* Long options. */
- struct option opts[] = {
- {"padding",required_argument, 0, 'p'},
- {"align", required_argument, 0, 'a'},
- {"fixcrc", no_argument, 0, 'f'},
- {"update", no_argument, 0, 'u'},
- {"dump", required_argument, 0, 'd'},
- {"xdump", required_argument, 0, 'x'},
- {"help", no_argument, 0, 'h'},
- {0, 0, 0, 0}
- };
-
- int c = 0, li = 0;
- int action = SHOW;
- uint64_t dump_id = 0;
- while ((c = getopt_long(argc, argv, "p:a:fuhd:x:", opts, &li)) != -1) {
- switch (c)
- {
- case 'p':
- PADDING = strtoull(optarg, NULL, 10);
- break;
- case 'a':
- ALIGNMENT = strtoull(optarg, NULL, 10);
- break;
- case 'f':
- action = FIXCRC;
- break;
- case 'u':
- action = UPDATE;
- break;
- case 'd':
- action = DUMP;
- dump_id = strtoull(optarg, NULL, 10);
- break;
- case 'x':
- action = XDUMP;
- dump_id = strtoull(optarg, NULL, 10);
- break;
- case 'h':
- case '?':
- default:
- help(argc, argv);
- return 1;
- }
- }
-
- /* Check if there's at least one remaining non-option. */
- if (argc - optind < 1) {
- help(argc, argv);
- return 1;
- }
- const char *fname = argv[optind];
-
- /* Init log. */
- log_init();
- log_levels_set(LOGT_SYSLOG, LOG_ANY, 0);
- log_levels_set(LOGT_STDERR, LOG_ANY, 0);
- log_levels_set(LOGT_STDOUT, LOG_ANY, ~0);
-
- /* Execute operation. */
- int ret = 0;
- switch(action) {
- case SHOW:
- ret = show(fname);
- break;
- case UPDATE:
- ret = update(fname);
- break;
- case FIXCRC:
- ret = fixcrc(fname);
- break;
- case DUMP:
- ret = dump(fname, dump_id);
- break;
- case XDUMP:
- ret = xdump(fname, dump_id);
- break;
- default:
- fprintf(stderr, "Unsupported operation.\n");
- break;
- }
-
- return ret;
-}
diff --git a/tests/querytcp.c b/tests/querytcp.c
deleted file mode 100644
index 7e1418f..0000000
--- a/tests/querytcp.c
+++ /dev/null
@@ -1,797 +0,0 @@
-/*
-TCP query version of queryperf
-querytcp.c
- fujiwara@jprs.co.jp
- 2009.08.12
- version 0.4
-
-queryperf for tcp query
-
-This program measures DNS server performance of TCP query.
-
-o Running environment:
- Development environment:
- Linux
- FreeBSD
- MacOS X 10.3.4
-
-o How to make:
- Linux: gcc -D_LINUX -Wall -O2 -g -lm -o querytcp querytcp.c
- FreeBSD: gcc -Wall -O2 -g -lm -o querytcp querytcp.c
- MacOS X: gcc -Wall -O2 -g -lm -lresolv -o querytcp querytcp.c
-
-o changes
-
- 2010/6/7: Linux compatibility
- 2009/8/12: Remove use of res_mkquery
-*/
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <netdb.h>
-#include <errno.h>
-#include <math.h>
-#include <err.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <arpa/nameser.h>
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <fcntl.h>
-#include <math.h>
-#ifndef NO_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifdef __APPLE__
-#include <nameser8_compat.h>
-#endif
-
-#ifndef ns_t_soa
-#define ns_t_soa T_SOA
-#endif
-#ifndef ns_t_ns
-#define ns_t_ns T_NS
-#endif
-#ifndef ns_c_in
-#define ns_c_in C_IN
-#endif
-
-#ifdef NOINET6
-#undef AF_INET6
-#endif
-
-#define Global
-
-#ifndef PACKETSZ
-#define PACKETSZ 512
-#endif
-
-/* debug.c */
-void hexdump(char *title, unsigned char *memory, int len)
-{
- printf("[ %s ", title);
- while (len-- > 0)
- printf("%02x ", *memory++);
- printf("]\n");
-}
-
-#define Xmalloc(size) Xrealloc(NULL, size)
-
-void *Xrealloc(void *p, int size)
-{
- int sz;
-
- sz = (size > 0) ? size : -size;
- if (p == NULL) {
- p = malloc(sz);
- } else {
- p = realloc(p, sz);
- }
- if (p == NULL) {
- char buf[100];
- snprintf(buf, sizeof buf, "size=%d", size);
- perror(buf);
- exit(1);
- }
- if (size < 0)
- memset(p, 0, sz);
- return p;
-}
-
-/* strlcpy() emulation for Linux. */
-#ifdef _LINUX
-static inline size_t strlcpy(char *destination, const char *source, size_t size)
-{
- if(strncpy(destination, source, size) == NULL)
- return 0;
-
- return size;
-}
-#endif
-
-/*
- NULL ... returns NULL
- */
-char *Xstrdup(char *p)
-{
- char *q;
- int len;
-
- if (p == NULL)
- return NULL;
- len = strlen(p) + 1;
- q = Xmalloc(len);
- strlcpy(q, p, len);
- return q;
-}
-
-
-typedef int64_t timediff_t;
-
-/* packet buffer */
-static struct timeval current;
-static struct timeval start, send_finished;;
-static fd_set fdset0r, fdset0w;
-static int nfds;
-static struct sockaddr_storage remote;
-static int remote_len = 0;
-static int finished = 0;
-static timediff_t Timeout = 10*1000000LL;
-unsigned short counter = 0;
-
-#define UpdateCurrentTime gettimeofday(&current, NULL)
-
-#define RECVBUFSIZ 65537
-#define SENDBUFSIZ 512
-
-struct dnsheader {
- unsigned short id; // 2
- unsigned char flag1, flag2; // 2
- unsigned short qdcount, ancount, nscount, arcount; // 8
-};
-
-/*
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
- |QR| Opcode |AA|TC|RD|RA| Z | RCODE |
- +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-*/
-
-struct queries {
- struct tcpdns {
- unsigned short len;
- union {
- struct dnsheader h;
- unsigned char dnsdata[SENDBUFSIZ];
- } u;
- } send;
- unsigned char recvbuf[RECVBUFSIZ];
- int sendlen;
- int sent_flag:1;
- int tcpstate:2;
- int fd;
- int rpos;
- int wpos;
- int no;
- struct timeval sent; /* long tv_sec, long tv_usec */
-};
-
-struct queries *Queries;
-
-#define NQUERY 100
-
-#define TCP_NONE 0
-#define TCP_WRITABLE 1
-#define TCP_READABLE 2
-
-/* input */
-char *ServerName = "127.0.0.1";
-char *ServerPort = "53";
-int family = PF_UNSPEC;
-char *datafile = NULL;
-int TimeLimit = 20;
-int EDNS0 = 0;
-int DNSSEC = 0;
-int recursion = 0;
-FILE *fp = NULL;
-int datafileloop = 0;
-int verbose = 0;
-int nQueries = 120;
-int printrcode = 0;
-char *rcodestr[]= {
- "NOERROR", "FormatError", "ServerFailure", "NameError",
- "NotImplemented", "Reused", "RCODE06", "RCODE07",
- "RCODE08", "RCODE09", "RCODE10", "RCODE11",
- "RCODE12", "RCODE13", "RCODE14", "RCODE15",
-};
-
-timediff_t timediff(struct timeval *a, struct timeval *b) /* u sec */
-{
- return (a->tv_sec - b->tv_sec) * 1000000 + (a->tv_usec - b->tv_usec);
-}
-
-#define TIMEOUTERROR -10000
-#define ERROROFFSET -20000
-#define ERRZEROREAD -30000
-
-uint64_t countrcode[16];
-uint64_t response_size_sum = 0;
-uint64_t response_size_sum2 = 0;
-uint64_t countanswers = 0;
-uint64_t countqueries = 0;
-uint64_t countzeroread = 0;
-uint64_t counttimeout = 0;
-uint64_t counterror = 0;
-
-int response_size_min = 0;
-int response_size_max = 0;
-
-
-
-void register_response(struct queries *q, int timeout, char *note)
-{
- u_char *p;
- int size;
- int rcode;
- int id;
-
- id = ntohs(q->send.u.h.id);
- if (note == NULL)
- note = "";
- countqueries++;
- if (timeout >= 0) {
- p = q->recvbuf;
- NS_GET16(size, p);
- response_size_sum += size;
- response_size_sum2 += size * size;
- if (response_size_min == 0 || response_size_min > size)
- response_size_min = size;
- if (response_size_max == 0 || response_size_max < size)
- response_size_max = size;
- rcode = p[3] & 0x0f;
- countrcode[rcode]++;
- countanswers++;
- if (verbose)
- printf("recv response id=%d rcode=%d size=%d rtt=%d\n", id, rcode, size, timeout);
- } else if (timeout == ERRZEROREAD) {
- countzeroread++;
- if (verbose)
- printf("recv response id=%d zeroread\n", id);
- } else if (timeout == TIMEOUTERROR) {
- counttimeout++;
- if (verbose)
- printf("recv timeout id=%d %lld usec\n", id, timediff(&current, &q->sent));
- } else {
- counterror++;
- if (verbose) {
- printf("recv error id=%d errno=%d at %s (%s)\n", id, ERROROFFSET - timeout, note, strerror(errno));
- }
- }
-#ifdef DEBUG
- printf("%ld.%03ld no=%d fd=%d %d %s\n", q->sent.tv_sec, q->sent.tv_usec/1000, q->no, q->fd, timeout, note);
- fflush(stdout);
-#endif
-}
-
-void output()
-{
- double response_size_average, response_size_variance, et;
-
- et = ((double)timediff(&current, &start))/1000000.0;
-
- printf("elapsed time: %.3f\n", et);
- printf("tcp qps: %.3f\n", (double)countanswers/et);
- printf("sent: %lld\n", countqueries);
- printf("answer: %lld %3.1f%%\n", countanswers,
- (double)((double)countanswers/(double)countqueries*100.0));
- printf("error: %lld %3.1f%%\n", counterror,
- (double)((double)counterror/(double)countqueries*100.0));
- printf("zeroread: %lld %3.1f%%\n", countzeroread,
- (double)((double)countzeroread/(double)countqueries*100.0));
- printf("timeout: %lld %3.1f%%\n", counttimeout,
- (double)((double)counttimeout/(double)countqueries*100.0));
- response_size_average = (double)response_size_sum/countanswers;
- response_size_variance = (double)response_size_sum2 / countanswers
- - response_size_average * response_size_average;
- printf("response size: %d/%.3f/%d/%.3f bytes\n", response_size_min, response_size_average, response_size_max, sqrt(response_size_variance));
- if (printrcode) {
- int i;
- for (i = 0; i < 16; i++) {
- if (countrcode[i] != 0) {
- printf("%s %lld %5.1f\n", rcodestr[i], countrcode[i], ((double)countrcode[i])/((double)countanswers)*100.0);
- }
- }
- }
-}
-
-void tcp_close(struct queries *q)
-{
-
-#ifdef DEBUG
-printf("tcp_close no=%d fd=%d\n", q->no, q->fd);
-#endif
- if (q->fd >= 0) {
- close(q->fd);
- FD_CLR(q->fd, &fdset0r);
- FD_CLR(q->fd, &fdset0w);
- }
- q->sent_flag = 0;
- q->tcpstate = TCP_NONE;
- q->fd = -1;
-}
-
-void tcp_send(struct queries *q)
-{
- int len;
-
- len = send(q->fd, &q->send, q->sendlen, MSG_NOSIGNAL);
-#ifdef DEBUG
-printf("tcp_send no=%d fd=%d %d:%d:%d\n", q->no, q->fd, len, q->wpos, q->sendlen);
-#endif
- if (len < 0) {
- if (errno == ENOTCONN) {
-printf("tcp_send no=%d fd=%d ENOTCONN return\n", q->no, q->fd);
- return;
- }
- register_response(q, ERROROFFSET - errno, "tcp_send");
- tcp_close(q);
- return;
- }
- if (len != q->sendlen) {
- register_response(q, ERROROFFSET - errno, "tcp_send:sendto");
- tcp_close(q);
- return;
- }
- FD_CLR(q->fd, &fdset0w);
- FD_SET(q->fd, &fdset0r);
-}
-
-struct typecodes {
- char *name;
- int code;
-} typecodes[] = {
- { "A", ns_t_a },
- { "NS", ns_t_ns },
- { "SOA", ns_t_soa },
- { "PTR", ns_t_ptr },
- { "HINFO", ns_t_hinfo },
- { "MX", ns_t_mx },
- { "TXT", ns_t_txt },
- { "SIG", ns_t_sig },
- { "KEY", ns_t_key },
- { "AAAA", ns_t_aaaa },
- { "NXT", ns_t_nxt },
- { "SRV", ns_t_srv },
- { "NAPTR", ns_t_naptr },
- { NULL, -1 },
-};
-
-int stringtodname(unsigned char *qname, unsigned char *buff, unsigned char *lim)
-{
- unsigned char *p, *s, *t;
- int count, total;
-
- t = qname;
- p = buff;
- total = 0;
- for ( ;; ) {
- s = p++;
- count = 0;
- if (p >= lim) return -1;
- while (*t != 0 && *t != '.')
- if (p < lim) {
- *p++ = *t++;
- count++;
- } else
- return -1;
- *s = count;
- if (count == 0)
- break;
- if (count > 63)
- return -1;
- total += count + 1;
- if (*t == '.') t++;
- }
- if (total > 250 || !(*t == 0 || (*t == '.' && t[1] == 0)))
- return -1;
- return p - buff;
-}
-
-void send_query_error(char *mesg)
-{
- err(1, "Packet size exceed: %s", mesg);
-}
-
-void send_query(struct queries *q)
-{
- u_char *p, *lim;
- char *qname;
- int qclass;
- int qtype;
- int tmp;
- struct typecodes *t = typecodes;
- u_char buff[512];
- static char sep[] = "\n\t ";
- static int lineno = 0;
-
- /*
- SEND E[send_packet_pos]
- */
- if (q->sent_flag) {
- register_response(q, TIMEOUTERROR, "send_query");
- tcp_close(q);
- }
- if (fp == NULL) {
- qname = "version.bind";
- qclass = ns_c_chaos;
- qtype = ns_t_txt;
- } else {
- do {
- if (fgets((char*)buff, sizeof(char)*512, fp) == NULL) {
- if (datafileloop == 1) {
- finished = 1;
- fclose(fp);
- fp = NULL;
- return;
- }
- if (datafileloop > 0)
- datafileloop--;
- rewind(fp);
- lineno = 0;
- if (fgets((char*)buff, sizeof(char)*512, fp) == NULL)
- err(1, "cannot rewind input file");
- }
- lineno++;
- } while(buff[0] == '#');
- qname = strtok((char*)buff, sep);
- p = (u_char*) strtok(NULL, sep);
- if (p != NULL) {
- while(t->name != NULL) {
- if (!strcasecmp(t->name, (char*)p))
- break;
- t++;
- }
- qtype = t->code;
- } else {
- qtype = ns_t_a;
- }
- if (qname == NULL || qtype < 0)
- err(1, "datafile format error at line %d, qname=%s qtype=%d", lineno, qname, qtype);
- qclass = ns_c_in;
- }
- q->send.u.h.id = counter++;
- q->send.u.h.flag1 = recursion ? 1 : 0; /* Query,OP=0,AA=0,TC=0,RD=0/1 */
- q->send.u.h.flag2 = 0;
- q->send.u.h.qdcount = htons(1);
- q->send.u.h.ancount = 0;
- q->send.u.h.nscount = 0;
- q->send.u.h.arcount = 0;
- p = q->send.u.dnsdata + sizeof(q->send.u.h);
- lim = p + sizeof(q->send.u.dnsdata);
- if ((tmp = stringtodname((u_char*) qname, p, lim)) < 0)
- send_query_error(qname);
- p += tmp;
- *(unsigned short *)p = htons(qtype);
- p += sizeof(unsigned short);
- *(unsigned short *)p = htons(qclass);
- p += sizeof(unsigned short);
- q->sendlen = p - q->send.u.dnsdata;
- if (EDNS0) {
-#define EDNS0size 11
- if (q->sendlen + EDNS0size >= sizeof(q->send.u.dnsdata))
- send_query_error("ENDS0");
- *p++ = 0; /* . */
- *(unsigned short *)p = htons(ns_t_opt);
- p += 2;
- *(unsigned short *)p = htons(4096);
- p += 2;
- *p++ = 0;
- *p++ = 0;
- *p++ = (DNSSEC == 0) ? 0 : 0x80; /* eflag: DO bit */
- *p++ = 0;
- *p++ = 0;
- *p++ = 0;
- q->sendlen += EDNS0size;
- p = (u_char*) &q->send.u.dnsdata;
- q->send.u.h.ancount = htons(1);
- }
- q->send.len = htons(q->sendlen);
- q->sendlen += sizeof(q->send.len);
- q->wpos = 0;
- q->rpos = 0;
- q->sent = current;
- if (verbose > 0) {
- int id = ntohs(*(unsigned short *)&q->send.u.dnsdata);
- printf("sending query(%s,%d,%d) id=%d %d bytes to %s\n", qname, qclass, qtype, id, q->sendlen, ServerName);
- hexdump("sending packet header:", (unsigned char*) &q->send.u.h, 12);
- }
- if (q->fd > 0)
- err(1, "q->fd > 0 but ignored\n");
-
- q->fd = socket(remote.ss_family, SOCK_STREAM, 0);
- tmp = fcntl(q->fd, F_GETFL, 0);
- fcntl(q->fd, F_SETFL, O_NONBLOCK | tmp);
- int conn_ret = connect(q->fd, (struct sockaddr *)&remote, remote_len);
- if(conn_ret < 0 && errno != EINPROGRESS) {
- register_response(q, ERROROFFSET - errno, "send_query:socket+fcntl+connect");
- tcp_close(q);
- return;
- }
-#ifdef DEBUG
-printf("send_query no=%d fd=%d socket|connect\n", q->no, q->fd);
-#endif
- q->tcpstate = TCP_WRITABLE;
- FD_SET(q->fd, &fdset0w);
- FD_CLR(q->fd, &fdset0r);
- if (nfds <= q->fd) {
- nfds = q->fd + 1;
- }
- q->sent = current;
- q->sent_flag = 1;
-}
-
-int UpdateQuery()
-{
- int i;
- timediff_t t, min = Timeout;
- struct queries *q;
- int free = 0;
-
- if (!finished && TimeLimit > 0) {
- if ((t = timediff(&current, &start)) > TimeLimit * 1000000LL) {
- finished = 1;
- send_finished = current;
- }
- }
- for(i = 0; i < nQueries; i++) {
- q = &Queries[i];
- if (q->sent_flag) {
- if ((t = timediff(&current, &q->sent)) > Timeout) {
- /* timeouted */
- register_response(q, TIMEOUTERROR, "UpdateQuery");
- tcp_close(q);
- } else
- if (t < min)
- min = t;
- }
- if (!q->sent_flag) {
- if (!finished)
- send_query(q);
- else
- free++;
- }
- }
- if (free == nQueries)
- min = -1; /* finished */
- return min;
-}
-
-char *skipname(char *p)
-{
- while(*p > 0 && *p < 0x40) p += *p + 1;
- if (*p == 0)
- return p+1;
- return p+2;
-}
-
-#define Hexdump(A,B,C)
-
-void tcp_receive(struct queries *q)
-{
- int len, len2;
- timediff_t tmp;
- unsigned char *recvp;
-
-/*printf("tcp_receive %s\n", q->nameserverlabel);*/
-
- len = read(q->fd, q->recvbuf + q->rpos, len2 = RECVBUFSIZ - q->rpos);
- if (len < 0) {
- if (errno == EAGAIN)
- return;
- register_response(q, ERROROFFSET - errno, "tcp_receive:read");
- tcp_close(q);
- return;
- }
- if (len == 0) {
- register_response(q, ERRZEROREAD, "tcp_receive:read");
- tcp_close(q);
- return;
- }
- q->rpos += len;
- if (q->rpos < 2)
- return;
- len2 = ntohs(*(unsigned short *)(q->recvbuf));
- if (q->rpos >= len2 + 2) {
- /* finished */
- recvp = q->recvbuf + 2;
- if (memcmp(recvp, q->send.u.dnsdata, 2) == 0) {
- if ((recvp[2] & 1) == 0 /* RA bit */
- || (recvp[3] & 15) != 0 /* RCODE must be 0 */
- ) {
-/*
- fprintf(stderr, "WRONG AA=%d RCODE=%d\n",
- ((recvp[2]>>2) & 1), recvp[3]&15);
-*/
- }
- tmp = timediff(&current, &q->sent);
- register_response(q, tmp, "tcp_receive");
- tcp_close(q);
- return;
- } else {
-printf("no=%d fd=%d unknown recv %d bytes, len=%d\n", q->no, q->fd, q->rpos, ntohs(*(unsigned short *)(q->recvbuf)));
- hexdump("", q->recvbuf, len);
- /*
- fprintf(stderr, "unknown recv from %s, %d bytes %02x %02x\n", q->nameserverlabel, q->rpos, recvp[0], recvp[1]);
- */
- tcp_close(q);
- }
- }
-}
-
-void query()
-{
- fd_set fdsetr, fdsetw;
- struct timeval timeout;
- int min;
- struct queries *q;
- int i, n;
- struct addrinfo hints, *res0;
- int error;
-
- Queries = Xmalloc(sizeof(Queries[0]) * nQueries);
- memset(&remote, 0, sizeof(remote));
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
- printf("resolving: %s:%s\n", ServerName, ServerPort);
- error = getaddrinfo(ServerName, 0, &hints, &res0);
- if (error) {
- errx(1, "%s", gai_strerror(error));
- }
-
- /* Update server port. */
- int port = atoi(ServerPort);
- if (res0->ai_family == AF_INET6) {
- struct sockaddr_in6 *ipv6 = (struct sockaddr_in6*)res0->ai_addr;
- ipv6->sin6_port = htons(port);
- } else {
- struct sockaddr_in *ipv4 = (struct sockaddr_in*)res0->ai_addr;
- ipv4->sin_port = htons(port);
- }
-
- remote_len = res0->ai_addrlen;
- memcpy(&remote, res0->ai_addr, res0->ai_addrlen);
- memset(&countrcode, 0, sizeof(countrcode));
-
- res_init();
- _res.options ^= ~RES_RECURSE;
- _res.options |= RES_AAONLY;
-
- for (i = 0; i < nQueries; i++) {
- Queries[i].sent_flag = 0;
- Queries[i].no = i;
- }
-
- FD_ZERO(&fdset0r);
- FD_ZERO(&fdset0w);
- nfds = 0;
- UpdateCurrentTime;
- start = current;
- finished = 0;
-
- for (;;) {
- UpdateCurrentTime;
- if ((min = UpdateQuery()) < 0)
- break;
- timeout.tv_sec = min / 1000000;
- timeout.tv_usec = min % 1000000;
- fdsetr = fdset0r;
- fdsetw = fdset0w;
- n = select(nfds, &fdsetr, &fdsetw, NULL, &timeout);
- UpdateCurrentTime;
- for(i = 0; i < nQueries; i++) {
- q = &Queries[i];
- if (q->fd < 0 || !q->sent_flag)
- continue;
- if (FD_ISSET(q->fd, &fdsetw)) {
- tcp_send(q);
- } else if (FD_ISSET(q->fd, &fdsetr)) {
- tcp_receive(q);
- }
- }
- }
-}
-
-void usage()
-{
- fprintf(stderr,
-"querytcp [-d datafile] [-s server_addr] [-p port] [-q num_queries] [-t timeout] [l limit] [-4] [-6] [-h]\n"
-" -d specifies the input data file (default: stdin)\n"
-" -s sets the server to query (default: 127.0.0.1)\n"
-" -p sets the port on which to query the server (default: 53)\n"
-" -q specifies the maximum number of queries outstanding (default: 120)\n"
-" -t specifies the timeout for query completion in seconds (default: 10)\n"
-" -l specifies how a limit for how long to run tests in seconds (no default)\n"
-" -e enable EDNS0\n"
-" -D set DO bit\n"
-" -r set RD bit\n"
-"\n"
-"\n"
-"\n"
-" -c print the number of packets with each rcode\n"
-" -v verbose: report the RCODE of each response on stdout\n"
-" -h print this usage\n"
-);
- exit(1);
-}
-
-int main(int argc, char *argv[])
-{
- int ch, i;
- printf("dnsheader size: %d\n", sizeof(struct dnsheader));
- while ((ch = getopt(argc, argv, "d:s:p:q:t:l:46eDrvh")) != -1) {
- switch (ch) {
- case 'q':
- nQueries = atoi(optarg);
- if (nQueries < 1)
- err(1, "-q requires natural number");
- break;
- case 'p':
- ServerPort = Xstrdup(optarg);
- break;
- case 's':
- ServerName = Xstrdup(optarg);
- break;
- case 'd':
- datafile = Xstrdup(optarg);
- if ((fp = fopen(datafile, "r")) == NULL)
- err(1, "cannot open %s", optarg);
- break;
- case 't':
- i = atoi(optarg);
- if (i < 1)
- err(1, "-t timeout > 0");
- Timeout = (int64_t)i * 1000000LL;
- break;
- case 'l':
- TimeLimit = atoi(optarg);
- break;
- case '4':
- family = AF_INET;
- break;
- case '6':
- family = AF_INET6;
- break;
- case 'e':
- EDNS0 = 1;
- break;
- case 'D':
- DNSSEC = 1;
- break;
- case 'r':
- recursion = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- case 'c':
- printrcode = 1;
- break;
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- query();
- output();
-
- return 0;
-}
diff --git a/ylwrap b/ylwrap
index 7befa46..9253635 100755
--- a/ylwrap
+++ b/ylwrap
@@ -1,9 +1,10 @@
#! /bin/sh
# ylwrap - wrapper for lex/yacc invocations.
-scriptversion=2012-07-14.08; # UTC
+scriptversion=2011-08-25.18; # UTC
-# Copyright (C) 1996-2012 Free Software Foundation, Inc.
+# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005,
+# 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
#
# Written by Tom Tromey <tromey@cygnus.com>.
#
@@ -29,40 +30,9 @@ scriptversion=2012-07-14.08; # UTC
# bugs to <bug-automake@gnu.org> or send patches to
# <automake-patches@gnu.org>.
-get_dirname ()
-{
- case $1 in
- */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';;
- # Otherwise, we want the empty string (not ".").
- esac
-}
-
-# guard FILE
-# ----------
-# The CPP macro used to guard inclusion of FILE.
-guard()
-{
- printf '%s\n' "$from" \
- | sed \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
- -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'
-}
-
-# quote_for_sed [STRING]
-# ----------------------
-# Return STRING (or stdin) quoted to be used as a sed pattern.
-quote_for_sed ()
-{
- case $# in
- 0) cat;;
- 1) printf '%s\n' "$1";;
- esac \
- | sed -e 's|[][\\.*]|\\&|g'
-}
-
case "$1" in
'')
- echo "$0: No files given. Try '$0 --help' for more information." 1>&2
+ echo "$0: No files given. Try \`$0 --help' for more information." 1>&2
exit 1
;;
--basedir)
@@ -97,8 +67,6 @@ esac
# The input.
input="$1"
shift
-# We'll later need for a correct munging of "#line" directives.
-input_sub_rx=`get_dirname "$input" | quote_for_sed`
case "$input" in
[\\/]* | ?:[\\/]*)
# Absolute path; do nothing.
@@ -108,40 +76,15 @@ case "$input" in
input="`pwd`/$input"
;;
esac
-input_rx=`get_dirname "$input" | quote_for_sed`
-
-# Since DOS filename conventions don't allow two dots,
-# the DOS version of Bison writes out y_tab.c instead of y.tab.c
-# and y_tab.h instead of y.tab.h. Test to see if this is the case.
-y_tab_nodot=false
-if test -f y_tab.c || test -f y_tab.h; then
- y_tab_nodot=true
-fi
-# The parser itself, the first file, is the destination of the .y.c
-# rule in the Makefile.
-parser=$1
-# A sed program to s/FROM/TO/g for all the FROM/TO so that, for
-# instance, we rename #include "y.tab.h" into #include "parse.h"
-# during the conversion from y.tab.c to parse.c.
-rename_sed=
+pairlist=
while test "$#" -ne 0; do
if test "$1" = "--"; then
shift
break
fi
- from=$1
- # Handle y_tab.c and y_tab.h output by DOS
- if $y_tab_nodot; then
- case $from in
- "y.tab.c") from=y_tab.c;;
- "y.tab.h") from=y_tab.h;;
- esac
- fi
- shift
- to=$1
+ pairlist="$pairlist $1"
shift
- rename_sed="${rename_sed}s|"`quote_for_sed "$from"`"|$to|g;"
done
# The program to run.
@@ -172,55 +115,98 @@ esac
ret=$?
if test $ret -eq 0; then
- for from in *
- do
- to=`printf '%s\n' "$from" | sed "$rename_sed"`
+ set X $pairlist
+ shift
+ first=yes
+ # Since DOS filename conventions don't allow two dots,
+ # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+ # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+ y_tab_nodot="no"
+ if test -f y_tab.c || test -f y_tab.h; then
+ y_tab_nodot="yes"
+ fi
+
+ # The directory holding the input.
+ input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+ # Quote $INPUT_DIR so we can use it in a regexp.
+ # FIXME: really we should care about more than `.' and `\'.
+ input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
+
+ while test "$#" -ne 0; do
+ from="$1"
+ # Handle y_tab.c and y_tab.h output by DOS
+ if test $y_tab_nodot = "yes"; then
+ if test $from = "y.tab.c"; then
+ from="y_tab.c"
+ else
+ if test $from = "y.tab.h"; then
+ from="y_tab.h"
+ fi
+ fi
+ fi
if test -f "$from"; then
# If $2 is an absolute path name, then just use that,
- # otherwise prepend '../'.
- case $to in
- [\\/]* | ?:[\\/]*) target=$to;;
- *) target="../$to";;
+ # otherwise prepend `../'.
+ case "$2" in
+ [\\/]* | ?:[\\/]*) target="$2";;
+ *) target="../$2";;
esac
- # Do not overwrite unchanged header files to avoid useless
- # recompilations. Always update the parser itself: it is the
- # destination of the .y.c rule in the Makefile. Divert the
- # output of all other files to a temporary file so we can
- # compare them to existing versions.
- if test $from != $parser; then
+ # We do not want to overwrite a header file if it hasn't
+ # changed. This avoid useless recompilations. However the
+ # parser itself (the first file) should always be updated,
+ # because it is the destination of the .y.c rule in the
+ # Makefile. Divert the output of all other files to a temporary
+ # file so we can compare them to existing versions.
+ if test $first = no; then
realtarget="$target"
- target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'`
+ target="tmp-`echo $target | sed s/.*[\\/]//g`"
fi
-
- # Munge "#line" or "#" directives. Don't let the resulting
- # debug information point at an absolute srcdir. Use the real
- # output file name, not yy.lex.c for instance. Adjust the
- # include guards too.
- FROM=`guard "$from"`
- TARGET=`guard "$to"`
- sed -e "/^#/!b" -e "s|$input_rx|$input_sub_rx|" -e "$rename_sed" \
- -e "s|$FROM|$TARGET|" "$from" >"$target" || ret=$?
-
- # Check whether files must be updated.
- if test "$from" != "$parser"; then
+ # Edit out `#line' or `#' directives.
+ #
+ # We don't want the resulting debug information to point at
+ # an absolute srcdir; it is better for it to just mention the
+ # .y file with no path.
+ #
+ # We want to use the real output file name, not yy.lex.c for
+ # instance.
+ #
+ # We want the include guards to be adjusted too.
+ FROM=`echo "$from" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+ TARGET=`echo "$2" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+
+ sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
+ -e "s,$FROM,$TARGET," "$from" >"$target" || ret=$?
+
+ # Check whether header files must be updated.
+ if test $first = no; then
if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
- echo "$to is unchanged"
+ echo "$2" is unchanged
rm -f "$target"
else
- echo "updating $to"
+ echo updating "$2"
mv -f "$target" "$realtarget"
fi
fi
else
- # A missing file is only an error for the parser. This is a
- # blatant hack to let us support using "yacc -d". If -d is not
- # specified, don't fail when the header file is "missing".
- if test "$from" = "$parser"; then
+ # A missing file is only an error for the first file. This
+ # is a blatant hack to let us support using "yacc -d". If -d
+ # is not specified, we don't want an error when the header
+ # file is "missing".
+ if test $first = yes; then
ret=1
fi
fi
+ shift
+ shift
+ first=no
done
+else
+ ret=$?
fi
# Remove the directory.