summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2012-08-31 16:26:55 +0200
committerOndřej Surý <ondrej@sury.org>2012-08-31 16:26:55 +0200
commit9a7b8a090ba4fa50fc023bdea04e83602a2ad0bb (patch)
treec7fec3e97f0b5e116f35272799d69d802267851f /src
parent4355eafde2b6a80d2b8feaba30b6a884aff070d9 (diff)
downloadknot-9a7b8a090ba4fa50fc023bdea04e83602a2ad0bb.tar.gz
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'src')
-rwxr-xr-x[-rw-r--r--]src/Makefile.am16
-rwxr-xr-x[-rw-r--r--]src/Makefile.in94
-rwxr-xr-x[-rw-r--r--]src/common/LICENSE.txt0
-rwxr-xr-x[-rw-r--r--]src/common/acl.c0
-rwxr-xr-x[-rw-r--r--]src/common/acl.h0
-rwxr-xr-x[-rw-r--r--]src/common/base32.c0
-rwxr-xr-x[-rw-r--r--]src/common/base32.h0
-rwxr-xr-x[-rw-r--r--]src/common/base32hex.c0
-rwxr-xr-x[-rw-r--r--]src/common/base32hex.h0
-rwxr-xr-xsrc/common/base64.c574
-rwxr-xr-xsrc/common/base64.h60
-rwxr-xr-x[-rw-r--r--]src/common/crc.h2
-rwxr-xr-x[-rw-r--r--]src/common/dSFMT-params.h0
-rwxr-xr-x[-rw-r--r--]src/common/dSFMT-params521.h0
-rwxr-xr-x[-rw-r--r--]src/common/dSFMT.c0
-rwxr-xr-x[-rw-r--r--]src/common/dSFMT.h0
-rw-r--r--src/common/dynamic-array.c225
-rw-r--r--src/common/dynamic-array.h156
-rwxr-xr-x[-rw-r--r--]src/common/errors.c0
-rwxr-xr-x[-rw-r--r--]src/common/errors.h0
-rwxr-xr-x[-rw-r--r--]src/common/evqueue.c7
-rwxr-xr-x[-rw-r--r--]src/common/evqueue.h0
-rwxr-xr-x[-rw-r--r--]src/common/evsched.c74
-rwxr-xr-x[-rw-r--r--]src/common/evsched.h4
-rwxr-xr-x[-rw-r--r--]src/common/fdset.c0
-rwxr-xr-x[-rw-r--r--]src/common/fdset.h2
-rwxr-xr-x[-rw-r--r--]src/common/fdset_epoll.c0
-rwxr-xr-x[-rw-r--r--]src/common/fdset_epoll.h0
-rwxr-xr-x[-rw-r--r--]src/common/fdset_kqueue.c0
-rwxr-xr-x[-rw-r--r--]src/common/fdset_kqueue.h0
-rwxr-xr-x[-rw-r--r--]src/common/fdset_poll.c3
-rwxr-xr-x[-rw-r--r--]src/common/fdset_poll.h0
-rwxr-xr-x[-rw-r--r--]src/common/general-tree.c0
-rwxr-xr-x[-rw-r--r--]src/common/general-tree.h0
-rwxr-xr-xsrc/common/heap.c149
-rwxr-xr-xsrc/common/heap.h57
-rwxr-xr-x[-rw-r--r--]src/common/latency.c0
-rwxr-xr-x[-rw-r--r--]src/common/latency.h0
-rwxr-xr-x[-rw-r--r--]src/common/libtap/README0
-rwxr-xr-x[-rw-r--r--]src/common/libtap/tap.c0
-rwxr-xr-x[-rw-r--r--]src/common/libtap/tap.h0
-rwxr-xr-x[-rw-r--r--]src/common/libtap/tap_unit.h0
-rwxr-xr-x[-rw-r--r--]src/common/lists.c0
-rwxr-xr-x[-rw-r--r--]src/common/lists.h1
-rwxr-xr-x[-rw-r--r--]src/common/log.c0
-rwxr-xr-x[-rw-r--r--]src/common/log.h0
-rwxr-xr-x[-rw-r--r--]src/common/mempattern.c0
-rwxr-xr-x[-rw-r--r--]src/common/mempattern.h0
-rwxr-xr-x[-rw-r--r--]src/common/modified_tree.h2
-rwxr-xr-x[-rw-r--r--]src/common/print.c0
-rwxr-xr-x[-rw-r--r--]src/common/print.h0
-rwxr-xr-x[-rw-r--r--]src/common/prng.c0
-rwxr-xr-x[-rw-r--r--]src/common/prng.h2
-rwxr-xr-x[-rw-r--r--]src/common/ref.c0
-rwxr-xr-x[-rw-r--r--]src/common/ref.h0
-rwxr-xr-x[-rw-r--r--]src/common/skip-list.c0
-rwxr-xr-x[-rw-r--r--]src/common/skip-list.h0
-rwxr-xr-x[-rw-r--r--]src/common/slab/alloc-common.h0
-rwxr-xr-x[-rw-r--r--]src/common/slab/slab.c2
-rwxr-xr-x[-rw-r--r--]src/common/slab/slab.h0
-rwxr-xr-x[-rw-r--r--]src/common/sockaddr.c0
-rwxr-xr-x[-rw-r--r--]src/common/sockaddr.h0
-rwxr-xr-x[-rw-r--r--]src/common/tree.h0
-rwxr-xr-x[-rw-r--r--]src/config.h.in15
-rwxr-xr-xsrc/knot.conf.5296
-rwxr-xr-x[-rw-r--r--]src/knot.service0
-rwxr-xr-x[-rw-r--r--]src/knot.spec0
-rwxr-xr-x[-rw-r--r--]src/knot.sysconfig0
-rwxr-xr-x[-rw-r--r--]src/knot/common.h8
-rwxr-xr-x[-rw-r--r--]src/knot/conf/cf-lex.l1
-rwxr-xr-x[-rw-r--r--]src/knot/conf/cf-parse.y25
-rwxr-xr-x[-rw-r--r--]src/knot/conf/conf.c167
-rwxr-xr-x[-rw-r--r--]src/knot/conf/conf.h30
-rwxr-xr-x[-rw-r--r--]src/knot/conf/logconf.c0
-rwxr-xr-x[-rw-r--r--]src/knot/conf/logconf.h0
-rwxr-xr-x[-rw-r--r--]src/knot/ctl/knotc_main.c48
-rwxr-xr-x[-rw-r--r--]src/knot/ctl/process.c50
-rwxr-xr-x[-rw-r--r--]src/knot/ctl/process.h9
-rwxr-xr-x[-rw-r--r--]src/knot/main.c30
-rwxr-xr-x[-rw-r--r--]src/knot/other/debug.h0
-rwxr-xr-x[-rw-r--r--]src/knot/other/error.c4
-rwxr-xr-x[-rw-r--r--]src/knot/other/error.h4
-rwxr-xr-x[-rw-r--r--]src/knot/server/dthreads.c57
-rwxr-xr-x[-rw-r--r--]src/knot/server/dthreads.h5
-rwxr-xr-x[-rw-r--r--]src/knot/server/journal.c52
-rwxr-xr-x[-rw-r--r--]src/knot/server/journal.h2
-rwxr-xr-x[-rw-r--r--]src/knot/server/notify.c38
-rwxr-xr-x[-rw-r--r--]src/knot/server/notify.h0
-rwxr-xr-x[-rw-r--r--]src/knot/server/server.c66
-rwxr-xr-x[-rw-r--r--]src/knot/server/server.h0
-rwxr-xr-x[-rw-r--r--]src/knot/server/socket.c21
-rwxr-xr-x[-rw-r--r--]src/knot/server/socket.h0
-rwxr-xr-x[-rw-r--r--]src/knot/server/tcp-handler.c66
-rwxr-xr-x[-rw-r--r--]src/knot/server/tcp-handler.h0
-rwxr-xr-x[-rw-r--r--]src/knot/server/udp-handler.c91
-rwxr-xr-x[-rw-r--r--]src/knot/server/udp-handler.h0
-rwxr-xr-x[-rw-r--r--]src/knot/server/xfr-handler.c418
-rwxr-xr-x[-rw-r--r--]src/knot/server/xfr-handler.h11
-rwxr-xr-x[-rw-r--r--]src/knot/server/zones.c778
-rwxr-xr-x[-rw-r--r--]src/knot/server/zones.h19
-rwxr-xr-x[-rw-r--r--]src/knot/stat/gatherer.c0
-rwxr-xr-x[-rw-r--r--]src/knot/stat/gatherer.h0
-rwxr-xr-x[-rw-r--r--]src/knot/stat/stat-common.h0
-rwxr-xr-x[-rw-r--r--]src/knot/stat/stat.c0
-rwxr-xr-x[-rw-r--r--]src/knot/stat/stat.h0
-rwxr-xr-x[-rw-r--r--]src/knot/zone/semantic-check.c77
-rwxr-xr-x[-rw-r--r--]src/knot/zone/semantic-check.h4
-rwxr-xr-x[-rw-r--r--]src/knot/zone/zone-dump-text.c195
-rwxr-xr-x[-rw-r--r--]src/knot/zone/zone-dump-text.h2
-rwxr-xr-x[-rw-r--r--]src/knot/zone/zone-dump.c61
-rwxr-xr-x[-rw-r--r--]src/knot/zone/zone-dump.h4
-rwxr-xr-x[-rw-r--r--]src/knot/zone/zone-load.c260
-rwxr-xr-x[-rw-r--r--]src/knot/zone/zone-load.h2
-rwxr-xr-x[-rw-r--r--]src/knotc.824
-rwxr-xr-x[-rw-r--r--]src/knotd.82
-rwxr-xr-x[-rw-r--r--]src/libknot/common.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/consts.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/dname.c192
-rwxr-xr-x[-rw-r--r--]src/libknot/dname.h2
-rwxr-xr-x[-rw-r--r--]src/libknot/edns.c45
-rwxr-xr-x[-rw-r--r--]src/libknot/edns.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/hash/cuckoo-hash-table.c677
-rwxr-xr-x[-rw-r--r--]src/libknot/hash/cuckoo-hash-table.h1
-rwxr-xr-x[-rw-r--r--]src/libknot/hash/hash-functions.c0
-rwxr-xr-x[-rw-r--r--]src/libknot/hash/hash-functions.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/hash/universal-system.c0
-rwxr-xr-x[-rw-r--r--]src/libknot/hash/universal-system.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/libknot.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/nameserver/name-server.c1560
-rwxr-xr-x[-rw-r--r--]src/libknot/nameserver/name-server.h42
-rwxr-xr-x[-rw-r--r--]src/libknot/nsec3.c30
-rwxr-xr-x[-rw-r--r--]src/libknot/nsec3.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/packet/packet.c331
-rwxr-xr-x[-rw-r--r--]src/libknot/packet/packet.h3
-rwxr-xr-x[-rw-r--r--]src/libknot/packet/query.c2
-rwxr-xr-x[-rw-r--r--]src/libknot/packet/query.h6
-rwxr-xr-x[-rw-r--r--]src/libknot/packet/response.c208
-rwxr-xr-x[-rw-r--r--]src/libknot/packet/response.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/rdata.c223
-rwxr-xr-x[-rw-r--r--]src/libknot/rdata.h7
-rwxr-xr-x[-rw-r--r--]src/libknot/rrset.c266
-rwxr-xr-x[-rw-r--r--]src/libknot/rrset.h44
-rwxr-xr-x[-rw-r--r--]src/libknot/tsig-op.c254
-rwxr-xr-x[-rw-r--r--]src/libknot/tsig-op.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/tsig.c49
-rwxr-xr-x[-rw-r--r--]src/libknot/tsig.h2
-rwxr-xr-x[-rw-r--r--]src/libknot/updates/changesets.c30
-rwxr-xr-x[-rw-r--r--]src/libknot/updates/changesets.h8
-rwxr-xr-x[-rw-r--r--]src/libknot/updates/ddns.c4
-rwxr-xr-x[-rw-r--r--]src/libknot/updates/ddns.h2
-rwxr-xr-x[-rw-r--r--]src/libknot/updates/xfr-in.c754
-rwxr-xr-x[-rw-r--r--]src/libknot/updates/xfr-in.h5
-rw-r--r--src/libknot/util/conv.c325
-rw-r--r--src/libknot/util/conv.h44
-rwxr-xr-x[-rw-r--r--]src/libknot/util/debug.c8
-rwxr-xr-x[-rw-r--r--]src/libknot/util/debug.h69
-rwxr-xr-x[-rw-r--r--]src/libknot/util/descriptor.c2
-rwxr-xr-x[-rw-r--r--]src/libknot/util/descriptor.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/util/error.h5
-rwxr-xr-x[-rw-r--r--]src/libknot/util/libknot_error.c5
-rwxr-xr-x[-rw-r--r--]src/libknot/util/tolower.c0
-rwxr-xr-x[-rw-r--r--]src/libknot/util/tolower.h2
-rwxr-xr-x[-rw-r--r--]src/libknot/util/utils.c0
-rwxr-xr-x[-rw-r--r--]src/libknot/util/utils.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/util/wire.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/dname-table.c0
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/dname-table.h0
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/node.c231
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/node.h36
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zone-contents.c1038
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zone-contents.h23
-rwxr-xr-xsrc/libknot/zone/zone-diff.c1004
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zone-diff.h (renamed from src/tests/common/da_tests.h)15
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zone-tree.c23
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zone-tree.h2
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zone.c44
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zone.h69
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zonedb.c123
-rwxr-xr-x[-rw-r--r--]src/libknot/zone/zonedb.h3
-rwxr-xr-x[-rw-r--r--]src/tests/README0
-rwxr-xr-x[-rw-r--r--]src/tests/common/acl_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/common/acl_tests.h0
-rw-r--r--src/tests/common/da_tests.c330
-rwxr-xr-x[-rw-r--r--]src/tests/common/events_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/common/events_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/common/fdset_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/common/fdset_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/common/skiplist_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/common/skiplist_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/common/slab_tests.c7
-rwxr-xr-x[-rw-r--r--]src/tests/common/slab_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/files/sample_conf0
-rwxr-xr-x[-rw-r--r--]src/tests/knot/conf_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/knot/conf_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/knot/dthreads_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/knot/dthreads_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/knot/journal_tests.c28
-rwxr-xr-x[-rw-r--r--]src/tests/knot/journal_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/knot/server_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/knot/server_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/files/parsed_databin71188 -> 71188 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/files/parsed_data_queriesbin1325 -> 1325 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/files/raw_databin72100 -> 72100 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/files/raw_data_queriesbin1387 -> 1387 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/cuckoo_tests.c1
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/cuckoo_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/dname_table_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/dname_table_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/dname_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/dname_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/edns_tests.c3
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/edns_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/node_tests.c18
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/node_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/nsec3_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/nsec3_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/packet_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/packet_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/query_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/query_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/rdata_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/rdata_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/response_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/response_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/rrset_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/rrset_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/tsig_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/tsig_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/zone_tests.c12
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/zone_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/zone_tree_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/zone_tree_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/zonedb_tests.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/libknot/zonedb_tests.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/files/parsed_databin4851 -> 4851 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/files/parsed_data_queriesbin1325 -> 1325 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/files/raw_databin4935 -> 4935 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/files/raw_data_queriesbin1387 -> 1387 bytes
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/dname_tests_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/dname_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/edns_tests_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/edns_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/node_tests_realdata.c4
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/node_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/packet_tests_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/packet_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/rdata_tests_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/rdata_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/response_tests_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/response_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/rrset_tests_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/rrset_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/zone_tests_realdata.c2
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/zone_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot_tests_loader_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/libknot_tests_loader_realdata.h0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/realdata/unittests_libknot_realdata.c0
-rwxr-xr-x[-rw-r--r--]src/tests/libknot/unittests_libknot.c0
-rwxr-xr-x[-rw-r--r--]src/tests/unittests_main.c2
-rwxr-xr-x[-rw-r--r--]src/tests/xfr_tests.c6
-rwxr-xr-x[-rw-r--r--]src/tests/xfr_tests.h0
-rwxr-xr-x[-rw-r--r--]src/zcompile/LICENSE0
-rwxr-xr-x[-rw-r--r--]src/zcompile/parser-descriptor.c1
-rwxr-xr-x[-rw-r--r--]src/zcompile/parser-descriptor.h0
-rwxr-xr-x[-rw-r--r--]src/zcompile/parser-util.c18
-rwxr-xr-x[-rw-r--r--]src/zcompile/parser-util.h0
-rwxr-xr-x[-rw-r--r--]src/zcompile/tests/unittests_zp_main.c0
-rwxr-xr-x[-rw-r--r--]src/zcompile/tests/zcompile_tests.c0
-rwxr-xr-x[-rw-r--r--]src/zcompile/zcompile-error.c0
-rwxr-xr-x[-rw-r--r--]src/zcompile/zcompile-error.h0
-rwxr-xr-x[-rw-r--r--]src/zcompile/zcompile.c263
-rwxr-xr-x[-rw-r--r--]src/zcompile/zcompile.h7
-rwxr-xr-x[-rw-r--r--]src/zcompile/zcompile_main.c3
-rwxr-xr-x[-rw-r--r--]src/zcompile/zlexer.l0
-rwxr-xr-x[-rw-r--r--]src/zcompile/zparser.y17
277 files changed, 7479 insertions, 5433 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 60c51c6..eece959 100644..100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,8 +1,8 @@
ACLOCAL_AMFLAGS = -I ../m4
libexec_PROGRAMS = knot-zcompile unittests unittests-zcompile unittests-libknot-realdata unittests-libknot unittests-xfr
sbin_PROGRAMS = knotc knotd
-MANPAGES = knotc.8 knotd.8
-man8_MANS = knotc.8 knotd.8
+MANPAGES = knotc.8 knotd.8 knot.conf.5
+man8_MANS = knotc.8 knotd.8 knot.conf.5
EXTRA_DIST = $(man8_MANS)
# $(YACC) will generate header file
@@ -58,8 +58,6 @@ knot_zcompile_SOURCES = \
unittests_SOURCES = \
tests/common/acl_tests.c \
tests/common/acl_tests.h \
- tests/common/da_tests.c \
- tests/common/da_tests.h \
tests/common/events_tests.c \
tests/common/events_tests.h \
tests/common/skiplist_tests.c \
@@ -159,8 +157,6 @@ libknot_la_SOURCES = \
libknot/util/debug.c \
libknot/util/debug.h \
libknot/util/utils.h \
- libknot/util/conv.h \
- libknot/util/conv.c \
libknot/util/descriptor.c \
libknot/util/tolower.h \
libknot/util/tolower.c \
@@ -184,6 +180,8 @@ libknot_la_SOURCES = \
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 \
@@ -225,17 +223,19 @@ libknots_la_SOURCES = \
common/mempattern.c \
common/lists.c \
common/base32.c \
+ common/base64.c \
+ common/base64.h \
common/lists.h \
+ common/heap.h \
+ common/heap.c \
common/base32.h \
common/print.c \
common/print.h \
- common/dynamic-array.c \
common/skip-list.c \
common/base32hex.c \
common/skip-list.h \
common/general-tree.h \
common/general-tree.c \
- common/dynamic-array.h \
common/tree.h \
common/base32hex.h \
common/evqueue.h \
diff --git a/src/Makefile.in b/src/Makefile.in
index c00450d..d20810f 100644..100755
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -60,13 +60,13 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libknot_la_LIBADD =
-am_libknot_la_OBJECTS = libknot_error.lo utils.lo debug.lo conv.lo \
+am_libknot_la_OBJECTS = libknot_error.lo 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 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
+ 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
libknot_la_OBJECTS = $(am_libknot_la_OBJECTS)
libknotd_la_DEPENDENCIES = libknot.la libknots.la @LIBOBJS@
am_libknotd_la_OBJECTS = gatherer.lo stat.lo error.lo \
@@ -78,7 +78,7 @@ am_libknotd_la_OBJECTS = gatherer.lo stat.lo error.lo \
libknotd_la_OBJECTS = $(am_libknotd_la_OBJECTS)
libknots_la_DEPENDENCIES = @LIBOBJS@
am_libknots_la_OBJECTS = slab.lo tap.lo mempattern.lo lists.lo \
- base32.lo print.lo dynamic-array.lo skip-list.lo base32hex.lo \
+ base32.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 dSFMT.lo prng.lo fdset.lo fdset_poll.lo \
fdset_kqueue.lo fdset_epoll.lo log.lo
@@ -99,12 +99,11 @@ knotc_DEPENDENCIES = libknotd.la libknot.la libknots.la @LIBOBJS@
am_knotd_OBJECTS = main.$(OBJEXT)
knotd_OBJECTS = $(am_knotd_OBJECTS)
knotd_DEPENDENCIES = libknotd.la libknot.la libknots.la @LIBOBJS@
-am_unittests_OBJECTS = acl_tests.$(OBJEXT) da_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) \
- unittests_main.$(OBJEXT)
+am_unittests_OBJECTS = acl_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) unittests_main.$(OBJEXT)
nodist_unittests_OBJECTS =
unittests_OBJECTS = $(am_unittests_OBJECTS) \
$(nodist_unittests_OBJECTS)
@@ -326,8 +325,8 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I ../m4
-MANPAGES = knotc.8 knotd.8
-man8_MANS = knotc.8 knotd.8
+MANPAGES = knotc.8 knotd.8 knot.conf.5
+man8_MANS = knotc.8 knotd.8 knot.conf.5
EXTRA_DIST = $(man8_MANS)
# $(YACC) will generate header file
@@ -382,8 +381,6 @@ knot_zcompile_SOURCES = \
unittests_SOURCES = \
tests/common/acl_tests.c \
tests/common/acl_tests.h \
- tests/common/da_tests.c \
- tests/common/da_tests.h \
tests/common/events_tests.c \
tests/common/events_tests.h \
tests/common/skiplist_tests.c \
@@ -482,8 +479,6 @@ libknot_la_SOURCES = \
libknot/util/debug.c \
libknot/util/debug.h \
libknot/util/utils.h \
- libknot/util/conv.h \
- libknot/util/conv.c \
libknot/util/descriptor.c \
libknot/util/tolower.h \
libknot/util/tolower.c \
@@ -507,6 +502,8 @@ libknot_la_SOURCES = \
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 \
@@ -548,17 +545,19 @@ libknots_la_SOURCES = \
common/mempattern.c \
common/lists.c \
common/base32.c \
+ common/base64.c \
+ common/base64.h \
common/lists.h \
+ common/heap.h \
+ common/heap.c \
common/base32.h \
common/print.c \
common/print.h \
- common/dynamic-array.c \
common/skip-list.c \
common/base32hex.c \
common/skip-list.h \
common/general-tree.h \
common/general-tree.c \
- common/dynamic-array.h \
common/tree.h \
common/base32hex.h \
common/evqueue.h \
@@ -844,14 +843,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/acl_tests.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base32.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base32hex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/base64.Plo@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)/conv.Plo@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)/da_tests.Po@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@
@@ -862,7 +860,6 @@ distclean-compile:
@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)/dynamic-array.Plo@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@
@@ -879,6 +876,7 @@ distclean-compile:
@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@
@@ -949,6 +947,7 @@ distclean-compile:
@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@
@@ -1005,13 +1004,6 @@ debug.lo: libknot/util/debug.c
@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
-conv.lo: libknot/util/conv.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT conv.lo -MD -MP -MF $(DEPDIR)/conv.Tpo -c -o conv.lo `test -f 'libknot/util/conv.c' || echo '$(srcdir)/'`libknot/util/conv.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/conv.Tpo $(DEPDIR)/conv.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libknot/util/conv.c' object='conv.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 conv.lo `test -f 'libknot/util/conv.c' || echo '$(srcdir)/'`libknot/util/conv.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
@@ -1089,6 +1081,13 @@ dname-table.lo: libknot/zone/dname-table.c
@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
@@ -1355,6 +1354,20 @@ base32.lo: common/base32.c
@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 base32.lo `test -f 'common/base32.c' || echo '$(srcdir)/'`common/base32.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
@@ -1362,13 +1375,6 @@ print.lo: common/print.c
@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
-dynamic-array.lo: common/dynamic-array.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT dynamic-array.lo -MD -MP -MF $(DEPDIR)/dynamic-array.Tpo -c -o dynamic-array.lo `test -f 'common/dynamic-array.c' || echo '$(srcdir)/'`common/dynamic-array.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/dynamic-array.Tpo $(DEPDIR)/dynamic-array.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='common/dynamic-array.c' object='dynamic-array.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 dynamic-array.lo `test -f 'common/dynamic-array.c' || echo '$(srcdir)/'`common/dynamic-array.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
@@ -1593,20 +1599,6 @@ acl_tests.obj: tests/common/acl_tests.c
@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`
-da_tests.o: tests/common/da_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT da_tests.o -MD -MP -MF $(DEPDIR)/da_tests.Tpo -c -o da_tests.o `test -f 'tests/common/da_tests.c' || echo '$(srcdir)/'`tests/common/da_tests.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/da_tests.Tpo $(DEPDIR)/da_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/da_tests.c' object='da_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 da_tests.o `test -f 'tests/common/da_tests.c' || echo '$(srcdir)/'`tests/common/da_tests.c
-
-da_tests.obj: tests/common/da_tests.c
-@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT da_tests.obj -MD -MP -MF $(DEPDIR)/da_tests.Tpo -c -o da_tests.obj `if test -f 'tests/common/da_tests.c'; then $(CYGPATH_W) 'tests/common/da_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/da_tests.c'; fi`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/da_tests.Tpo $(DEPDIR)/da_tests.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tests/common/da_tests.c' object='da_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 da_tests.obj `if test -f 'tests/common/da_tests.c'; then $(CYGPATH_W) 'tests/common/da_tests.c'; else $(CYGPATH_W) '$(srcdir)/tests/common/da_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
diff --git a/src/common/LICENSE.txt b/src/common/LICENSE.txt
index 15e3bef..15e3bef 100644..100755
--- a/src/common/LICENSE.txt
+++ b/src/common/LICENSE.txt
diff --git a/src/common/acl.c b/src/common/acl.c
index c8e0488..c8e0488 100644..100755
--- a/src/common/acl.c
+++ b/src/common/acl.c
diff --git a/src/common/acl.h b/src/common/acl.h
index 7ce8f26..7ce8f26 100644..100755
--- a/src/common/acl.h
+++ b/src/common/acl.h
diff --git a/src/common/base32.c b/src/common/base32.c
index 43b86c1..43b86c1 100644..100755
--- a/src/common/base32.c
+++ b/src/common/base32.c
diff --git a/src/common/base32.h b/src/common/base32.h
index 45df9fa..45df9fa 100644..100755
--- a/src/common/base32.h
+++ b/src/common/base32.h
diff --git a/src/common/base32hex.c b/src/common/base32hex.c
index cd2d2ce..cd2d2ce 100644..100755
--- a/src/common/base32hex.c
+++ b/src/common/base32hex.c
diff --git a/src/common/base32hex.h b/src/common/base32hex.h
index 9ac4fa8..9ac4fa8 100644..100755
--- a/src/common/base32hex.h
+++ b/src/common/base32hex.h
diff --git a/src/common/base64.c b/src/common/base64.c
new file mode 100755
index 0000000..f1f601c
--- /dev/null
+++ b/src/common/base64.c
@@ -0,0 +1,574 @@
+/* base64.c -- Encode binary data using printable characters.
+ Copyright (C) 1999-2001, 2004-2006, 2009-2012 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Simon Josefsson. Partially adapted from GNU MailUtils
+ * (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
+ * from Paul Eggert, Bruno Haible, and Stepan Kasal.
+ *
+ * See also RFC 4648 <http://www.ietf.org/rfc/rfc4648.txt>.
+ *
+ * Be careful with error checking. Here is how you would typically
+ * use these functions:
+ *
+ * bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
+ * if (!ok)
+ * FAIL: input was not valid base64
+ * if (out == NULL)
+ * FAIL: memory allocation error
+ * OK: data in OUT/OUTLEN
+ *
+ * size_t outlen = base64_encode_alloc (in, inlen, &out);
+ * if (out == NULL && outlen == 0 && inlen != 0)
+ * FAIL: input too long
+ * if (out == NULL)
+ * FAIL: memory allocation error
+ * OK: data in OUT/OUTLEN.
+ *
+ */
+
+#include <config.h>
+
+/* Get prototype. */
+#include "base64.h"
+
+/* Get malloc. */
+#include <stdlib.h>
+
+/* Get UCHAR_MAX. */
+#include <limits.h>
+
+#include <string.h>
+
+/* C89 compliant way to cast 'char' to 'unsigned char'. */
+static inline unsigned char
+to_uchar (char ch)
+{
+ return ch;
+}
+
+/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
+ If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
+ possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
+ terminate the output buffer. */
+void
+base64_encode (const char *restrict in, size_t inlen,
+ char *restrict out, size_t outlen)
+{
+ static const char b64str[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ while (inlen && outlen)
+ {
+ *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
+ if (!--outlen)
+ break;
+ *out++ = b64str[((to_uchar (in[0]) << 4)
+ + (--inlen ? to_uchar (in[1]) >> 4 : 0))
+ & 0x3f];
+ if (!--outlen)
+ break;
+ *out++ =
+ (inlen
+ ? b64str[((to_uchar (in[1]) << 2)
+ + (--inlen ? to_uchar (in[2]) >> 6 : 0))
+ & 0x3f]
+ : '=');
+ if (!--outlen)
+ break;
+ *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
+ if (!--outlen)
+ break;
+ if (inlen)
+ inlen--;
+ if (inlen)
+ in += 3;
+ }
+
+ if (outlen)
+ *out = '\0';
+}
+
+/* Allocate a buffer and store zero terminated base64 encoded data
+ from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
+ the length of the encoded data, excluding the terminating zero. On
+ return, the OUT variable will hold a pointer to newly allocated
+ memory that must be deallocated by the caller. If output string
+ length would overflow, 0 is returned and OUT is set to NULL. If
+ memory allocation failed, OUT is set to NULL, and the return value
+ indicates length of the requested memory block, i.e.,
+ BASE64_LENGTH(inlen) + 1. */
+size_t
+base64_encode_alloc (const char *in, size_t inlen, char **out)
+{
+ size_t outlen = 1 + BASE64_LENGTH (inlen);
+
+ /* Check for overflow in outlen computation.
+ *
+ * If there is no overflow, outlen >= inlen.
+ *
+ * If the operation (inlen + 2) overflows then it yields at most +1, so
+ * outlen is 0.
+ *
+ * If the multiplication overflows, we lose at least half of the
+ * correct value, so the result is < ((inlen + 2) / 3) * 2, which is
+ * less than (inlen + 2) * 0.66667, which is less than inlen as soon as
+ * (inlen > 4).
+ */
+ if (inlen > outlen)
+ {
+ *out = NULL;
+ return 0;
+ }
+
+ *out = malloc (outlen);
+ if (!*out)
+ return outlen;
+
+ base64_encode (in, inlen, *out, outlen);
+
+ return outlen - 1;
+}
+
+/* With this approach this file works independent of the charset used
+ (think EBCDIC). However, it does assume that the characters in the
+ Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
+ 1003.1-2001 require that char and unsigned char are 8-bit
+ quantities, though, taking care of that problem. But this may be a
+ potential problem on non-POSIX C99 platforms.
+
+ IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
+ as the formal parameter rather than "x". */
+#define B64(_) \
+ ((_) == 'A' ? 0 \
+ : (_) == 'B' ? 1 \
+ : (_) == 'C' ? 2 \
+ : (_) == 'D' ? 3 \
+ : (_) == 'E' ? 4 \
+ : (_) == 'F' ? 5 \
+ : (_) == 'G' ? 6 \
+ : (_) == 'H' ? 7 \
+ : (_) == 'I' ? 8 \
+ : (_) == 'J' ? 9 \
+ : (_) == 'K' ? 10 \
+ : (_) == 'L' ? 11 \
+ : (_) == 'M' ? 12 \
+ : (_) == 'N' ? 13 \
+ : (_) == 'O' ? 14 \
+ : (_) == 'P' ? 15 \
+ : (_) == 'Q' ? 16 \
+ : (_) == 'R' ? 17 \
+ : (_) == 'S' ? 18 \
+ : (_) == 'T' ? 19 \
+ : (_) == 'U' ? 20 \
+ : (_) == 'V' ? 21 \
+ : (_) == 'W' ? 22 \
+ : (_) == 'X' ? 23 \
+ : (_) == 'Y' ? 24 \
+ : (_) == 'Z' ? 25 \
+ : (_) == 'a' ? 26 \
+ : (_) == 'b' ? 27 \
+ : (_) == 'c' ? 28 \
+ : (_) == 'd' ? 29 \
+ : (_) == 'e' ? 30 \
+ : (_) == 'f' ? 31 \
+ : (_) == 'g' ? 32 \
+ : (_) == 'h' ? 33 \
+ : (_) == 'i' ? 34 \
+ : (_) == 'j' ? 35 \
+ : (_) == 'k' ? 36 \
+ : (_) == 'l' ? 37 \
+ : (_) == 'm' ? 38 \
+ : (_) == 'n' ? 39 \
+ : (_) == 'o' ? 40 \
+ : (_) == 'p' ? 41 \
+ : (_) == 'q' ? 42 \
+ : (_) == 'r' ? 43 \
+ : (_) == 's' ? 44 \
+ : (_) == 't' ? 45 \
+ : (_) == 'u' ? 46 \
+ : (_) == 'v' ? 47 \
+ : (_) == 'w' ? 48 \
+ : (_) == 'x' ? 49 \
+ : (_) == 'y' ? 50 \
+ : (_) == 'z' ? 51 \
+ : (_) == '0' ? 52 \
+ : (_) == '1' ? 53 \
+ : (_) == '2' ? 54 \
+ : (_) == '3' ? 55 \
+ : (_) == '4' ? 56 \
+ : (_) == '5' ? 57 \
+ : (_) == '6' ? 58 \
+ : (_) == '7' ? 59 \
+ : (_) == '8' ? 60 \
+ : (_) == '9' ? 61 \
+ : (_) == '+' ? 62 \
+ : (_) == '/' ? 63 \
+ : -1)
+
+static const signed char b64[0x100] = {
+ B64 (0), B64 (1), B64 (2), B64 (3),
+ B64 (4), B64 (5), B64 (6), B64 (7),
+ B64 (8), B64 (9), B64 (10), B64 (11),
+ B64 (12), B64 (13), B64 (14), B64 (15),
+ B64 (16), B64 (17), B64 (18), B64 (19),
+ B64 (20), B64 (21), B64 (22), B64 (23),
+ B64 (24), B64 (25), B64 (26), B64 (27),
+ B64 (28), B64 (29), B64 (30), B64 (31),
+ B64 (32), B64 (33), B64 (34), B64 (35),
+ B64 (36), B64 (37), B64 (38), B64 (39),
+ B64 (40), B64 (41), B64 (42), B64 (43),
+ B64 (44), B64 (45), B64 (46), B64 (47),
+ B64 (48), B64 (49), B64 (50), B64 (51),
+ B64 (52), B64 (53), B64 (54), B64 (55),
+ B64 (56), B64 (57), B64 (58), B64 (59),
+ B64 (60), B64 (61), B64 (62), B64 (63),
+ B64 (64), B64 (65), B64 (66), B64 (67),
+ B64 (68), B64 (69), B64 (70), B64 (71),
+ B64 (72), B64 (73), B64 (74), B64 (75),
+ B64 (76), B64 (77), B64 (78), B64 (79),
+ B64 (80), B64 (81), B64 (82), B64 (83),
+ B64 (84), B64 (85), B64 (86), B64 (87),
+ B64 (88), B64 (89), B64 (90), B64 (91),
+ B64 (92), B64 (93), B64 (94), B64 (95),
+ B64 (96), B64 (97), B64 (98), B64 (99),
+ B64 (100), B64 (101), B64 (102), B64 (103),
+ B64 (104), B64 (105), B64 (106), B64 (107),
+ B64 (108), B64 (109), B64 (110), B64 (111),
+ B64 (112), B64 (113), B64 (114), B64 (115),
+ B64 (116), B64 (117), B64 (118), B64 (119),
+ B64 (120), B64 (121), B64 (122), B64 (123),
+ B64 (124), B64 (125), B64 (126), B64 (127),
+ B64 (128), B64 (129), B64 (130), B64 (131),
+ B64 (132), B64 (133), B64 (134), B64 (135),
+ B64 (136), B64 (137), B64 (138), B64 (139),
+ B64 (140), B64 (141), B64 (142), B64 (143),
+ B64 (144), B64 (145), B64 (146), B64 (147),
+ B64 (148), B64 (149), B64 (150), B64 (151),
+ B64 (152), B64 (153), B64 (154), B64 (155),
+ B64 (156), B64 (157), B64 (158), B64 (159),
+ B64 (160), B64 (161), B64 (162), B64 (163),
+ B64 (164), B64 (165), B64 (166), B64 (167),
+ B64 (168), B64 (169), B64 (170), B64 (171),
+ B64 (172), B64 (173), B64 (174), B64 (175),
+ B64 (176), B64 (177), B64 (178), B64 (179),
+ B64 (180), B64 (181), B64 (182), B64 (183),
+ B64 (184), B64 (185), B64 (186), B64 (187),
+ B64 (188), B64 (189), B64 (190), B64 (191),
+ B64 (192), B64 (193), B64 (194), B64 (195),
+ B64 (196), B64 (197), B64 (198), B64 (199),
+ B64 (200), B64 (201), B64 (202), B64 (203),
+ B64 (204), B64 (205), B64 (206), B64 (207),
+ B64 (208), B64 (209), B64 (210), B64 (211),
+ B64 (212), B64 (213), B64 (214), B64 (215),
+ B64 (216), B64 (217), B64 (218), B64 (219),
+ B64 (220), B64 (221), B64 (222), B64 (223),
+ B64 (224), B64 (225), B64 (226), B64 (227),
+ B64 (228), B64 (229), B64 (230), B64 (231),
+ B64 (232), B64 (233), B64 (234), B64 (235),
+ B64 (236), B64 (237), B64 (238), B64 (239),
+ B64 (240), B64 (241), B64 (242), B64 (243),
+ B64 (244), B64 (245), B64 (246), B64 (247),
+ B64 (248), B64 (249), B64 (250), B64 (251),
+ B64 (252), B64 (253), B64 (254), B64 (255)
+};
+
+#if UCHAR_MAX == 255
+# define uchar_in_range(c) true
+#else
+# define uchar_in_range(c) ((c) <= 255)
+#endif
+
+/* Return true if CH is a character from the Base64 alphabet, and
+ false otherwise. Note that '=' is padding and not considered to be
+ part of the alphabet. */
+bool
+isbase64 (char ch)
+{
+ return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
+}
+
+/* Initialize decode-context buffer, CTX. */
+void
+base64_decode_ctx_init (struct base64_decode_context *ctx)
+{
+ ctx->i = 0;
+}
+
+/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
+ none of those four is a newline, then return *IN. Otherwise, copy up to
+ 4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
+ index CTX->i and setting CTX->i to reflect the number of bytes copied,
+ and return CTX->buf. In either case, advance *IN to point to the byte
+ after the last one processed, and set *N_NON_NEWLINE to the number of
+ verified non-newline bytes accessible through the returned pointer. */
+static inline char *
+get_4 (struct base64_decode_context *ctx,
+ char const *restrict *in, char const *restrict in_end,
+ size_t *n_non_newline)
+{
+ if (ctx->i == 4)
+ ctx->i = 0;
+
+ if (ctx->i == 0)
+ {
+ char const *t = *in;
+ if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
+ {
+ /* This is the common case: no newline. */
+ *in += 4;
+ *n_non_newline = 4;
+ return (char *) t;
+ }
+ }
+
+ {
+ /* Copy non-newline bytes into BUF. */
+ char const *p = *in;
+ while (p < in_end)
+ {
+ char c = *p++;
+ if (c != '\n')
+ {
+ ctx->buf[ctx->i++] = c;
+ if (ctx->i == 4)
+ break;
+ }
+ }
+
+ *in = p;
+ *n_non_newline = ctx->i;
+ return ctx->buf;
+ }
+}
+
+#define return_false \
+ do \
+ { \
+ *outp = out; \
+ return false; \
+ } \
+ while (false)
+
+/* Decode up to four bytes of base64-encoded data, IN, of length INLEN
+ into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
+ decoding is successful, false otherwise. If *OUTLEN is too small,
+ as many bytes as possible are written to *OUT. On return, advance
+ *OUT to point to the byte after the last one written, and decrement
+ *OUTLEN to reflect the number of bytes remaining in *OUT. */
+static inline bool
+decode_4 (char const *restrict in, size_t inlen,
+ char *restrict *outp, size_t *outleft)
+{
+ char *out = *outp;
+ if (inlen < 2)
+ return false;
+
+ if (!isbase64 (in[0]) || !isbase64 (in[1]))
+ return false;
+
+ if (*outleft)
+ {
+ *out++ = ((b64[to_uchar (in[0])] << 2)
+ | (b64[to_uchar (in[1])] >> 4));
+ --*outleft;
+ }
+
+ if (inlen == 2)
+ return_false;
+
+ if (in[2] == '=')
+ {
+ if (inlen != 4)
+ return_false;
+
+ if (in[3] != '=')
+ return_false;
+ }
+ else
+ {
+ if (!isbase64 (in[2]))
+ return_false;
+
+ if (*outleft)
+ {
+ *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
+ | (b64[to_uchar (in[2])] >> 2));
+ --*outleft;
+ }
+
+ if (inlen == 3)
+ return_false;
+
+ if (in[3] == '=')
+ {
+ if (inlen != 4)
+ return_false;
+ }
+ else
+ {
+ if (!isbase64 (in[3]))
+ return_false;
+
+ if (*outleft)
+ {
+ *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
+ | b64[to_uchar (in[3])]);
+ --*outleft;
+ }
+ }
+ }
+
+ *outp = out;
+ return true;
+}
+
+/* Decode base64-encoded input array IN of length INLEN to output array
+ OUT that can hold *OUTLEN bytes. The input data may be interspersed
+ with newlines. Return true if decoding was successful, i.e. if the
+ input was valid base64 data, false otherwise. If *OUTLEN is too
+ small, as many bytes as possible will be written to OUT. On return,
+ *OUTLEN holds the length of decoded bytes in OUT. Note that as soon
+ as any non-alphabet, non-newline character is encountered, decoding
+ is stopped and false is returned. If INLEN is zero, then process
+ only whatever data is stored in CTX.
+
+ Initially, CTX must have been initialized via base64_decode_ctx_init.
+ Subsequent calls to this function must reuse whatever state is recorded
+ in that buffer. It is necessary for when a quadruple of base64 input
+ bytes spans two input buffers.
+
+ If CTX is NULL then newlines are treated as garbage and the input
+ buffer is processed as a unit. */
+
+bool
+base64_decode_ctx (struct base64_decode_context *ctx,
+ const char *restrict in, size_t inlen,
+ char *restrict out, size_t *outlen)
+{
+ size_t outleft = *outlen;
+ bool ignore_newlines = ctx != NULL;
+ bool flush_ctx = false;
+ unsigned int ctx_i = 0;
+
+ if (ignore_newlines)
+ {
+ ctx_i = ctx->i;
+ flush_ctx = inlen == 0;
+ }
+
+
+ while (true)
+ {
+ size_t outleft_save = outleft;
+ if (ctx_i == 0 && !flush_ctx)
+ {
+ while (true)
+ {
+ /* Save a copy of outleft, in case we need to re-parse this
+ block of four bytes. */
+ outleft_save = outleft;
+ if (!decode_4 (in, inlen, &out, &outleft))
+ break;
+
+ in += 4;
+ inlen -= 4;
+ }
+ }
+
+ if (inlen == 0 && !flush_ctx)
+ break;
+
+ /* Handle the common case of 72-byte wrapped lines.
+ This also handles any other multiple-of-4-byte wrapping. */
+ if (inlen && *in == '\n' && ignore_newlines)
+ {
+ ++in;
+ --inlen;
+ continue;
+ }
+
+ /* Restore OUT and OUTLEFT. */
+ out -= outleft_save - outleft;
+ outleft = outleft_save;
+
+ {
+ char const *in_end = in + inlen;
+ char const *non_nl;
+
+ if (ignore_newlines)
+ non_nl = get_4 (ctx, &in, in_end, &inlen);
+ else
+ non_nl = in; /* Might have nl in this case. */
+
+ /* If the input is empty or consists solely of newlines (0 non-newlines),
+ then we're done. Likewise if there are fewer than 4 bytes when not
+ flushing context and not treating newlines as garbage. */
+ if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
+ {
+ inlen = 0;
+ break;
+ }
+ if (!decode_4 (non_nl, inlen, &out, &outleft))
+ break;
+
+ inlen = in_end - in;
+ }
+ }
+
+ *outlen -= outleft;
+
+ return inlen == 0;
+}
+
+/* Allocate an output buffer in *OUT, and decode the base64 encoded
+ data stored in IN of size INLEN to the *OUT buffer. On return, the
+ size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
+ if the caller is not interested in the decoded length. *OUT may be
+ NULL to indicate an out of memory error, in which case *OUTLEN
+ contains the size of the memory block needed. The function returns
+ true on successful decoding and memory allocation errors. (Use the
+ *OUT and *OUTLEN parameters to differentiate between successful
+ decoding and memory error.) The function returns false if the
+ input was invalid, in which case *OUT is NULL and *OUTLEN is
+ undefined. */
+bool
+base64_decode_alloc_ctx (struct base64_decode_context *ctx,
+ const char *in, size_t inlen, char **out,
+ size_t *outlen)
+{
+ /* This may allocate a few bytes too many, depending on input,
+ but it's not worth the extra CPU time to compute the exact size.
+ The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
+ input ends with "=" and minus another 1 if the input ends with "==".
+ Dividing before multiplying avoids the possibility of overflow. */
+ size_t needlen = 3 * (inlen / 4) + 3;
+
+ *out = malloc (needlen);
+ if (!*out)
+ return true;
+
+ if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
+ {
+ free (*out);
+ *out = NULL;
+ return false;
+ }
+
+ if (outlen)
+ *outlen = needlen;
+
+ return true;
+}
diff --git a/src/common/base64.h b/src/common/base64.h
new file mode 100755
index 0000000..aa0b696
--- /dev/null
+++ b/src/common/base64.h
@@ -0,0 +1,60 @@
+/* base64.h -- Encode binary data using printable characters.
+ Copyright (C) 2004-2006, 2009-2012 Free Software Foundation, Inc.
+ Written by Simon Josefsson.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef BASE64_H
+# define BASE64_H
+
+/* Get size_t. */
+# include <stddef.h>
+
+/* Get bool. */
+# include <stdbool.h>
+
+/* This uses that the expression (n+(k-1))/k means the smallest
+ integer >= n/k, i.e., the ceiling of n/k. */
+# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
+
+struct base64_decode_context
+{
+ unsigned int i;
+ char buf[4];
+};
+
+extern bool isbase64 (char ch);
+
+extern void base64_encode (const char *restrict in, size_t inlen,
+ char *restrict out, size_t outlen);
+
+extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
+
+extern void base64_decode_ctx_init (struct base64_decode_context *ctx);
+
+extern bool base64_decode_ctx (struct base64_decode_context *ctx,
+ const char *restrict in, size_t inlen,
+ char *restrict out, size_t *outlen);
+
+extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx,
+ const char *in, size_t inlen,
+ char **out, size_t *outlen);
+
+#define base64_decode(in, inlen, out, outlen) \
+ base64_decode_ctx (NULL, in, inlen, out, outlen)
+
+#define base64_decode_alloc(in, inlen, out, outlen) \
+ base64_decode_alloc_ctx (NULL, in, inlen, out, outlen)
+
+#endif /* BASE64_H */
diff --git a/src/common/crc.h b/src/common/crc.h
index cf2e123..7d748be 100644..100755
--- a/src/common/crc.h
+++ b/src/common/crc.h
@@ -77,3 +77,5 @@ static inline crc_t crc_finalize(crc_t crc)
#endif /* __CRC_H__ */
+
+/*! @} */
diff --git a/src/common/dSFMT-params.h b/src/common/dSFMT-params.h
index c779d8a..c779d8a 100644..100755
--- a/src/common/dSFMT-params.h
+++ b/src/common/dSFMT-params.h
diff --git a/src/common/dSFMT-params521.h b/src/common/dSFMT-params521.h
index f771dc1..f771dc1 100644..100755
--- a/src/common/dSFMT-params521.h
+++ b/src/common/dSFMT-params521.h
diff --git a/src/common/dSFMT.c b/src/common/dSFMT.c
index 090bb80..090bb80 100644..100755
--- a/src/common/dSFMT.c
+++ b/src/common/dSFMT.c
diff --git a/src/common/dSFMT.h b/src/common/dSFMT.h
index f1aa9bd..f1aa9bd 100644..100755
--- a/src/common/dSFMT.h
+++ b/src/common/dSFMT.h
diff --git a/src/common/dynamic-array.c b/src/common/dynamic-array.c
deleted file mode 100644
index 24f2aaa..0000000
--- a/src/common/dynamic-array.c
+++ /dev/null
@@ -1,225 +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 <pthread.h>
-#include <assert.h>
-#include <stdio.h>
-
-#include <urcu.h>
-
-//#include "common.h"
-#include "common/dynamic-array.h"
-
-#ifndef ERR_ALLOC_FAILED
-#define ERR_ALLOC_FAILED fprintf(stderr, "Allocation failed at %s:%d\n", \
- __FILE__, __LINE__)
-#endif
-
-//#define DA_DEBUG
-
-#ifndef dbg_da
-#ifdef DA_DEBUG
-#define dbg_da(msg...) fprintf(stderr, msg)
-#else
-#define dbg_da(msg...)
-#endif
-#endif
-
-/*----------------------------------------------------------------------------*/
-/* Private functions */
-/*----------------------------------------------------------------------------*/
-
-enum da_resize_type {
- DA_LARGER, DA_SMALLER
-};
-
-typedef enum da_resize_type da_resize_type_t;
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \retval 1 On success.
- * \retval -1 On failure.
- */
-static int da_resize(da_array_t *array, da_resize_type_t type)
-{
- dbg_da("da_resize(): array pointer: %p, items pointer: %p\n", array,
- array->items);
-
- unsigned new_size = ((type == DA_LARGER)
- ? (array->allocated *= 2)
- : (array->allocated /= 2));
-
- void *new_items = malloc(new_size * array->item_size);
- if (new_items == NULL) {
- ERR_ALLOC_FAILED;
- return -1;
- }
-
- dbg_da("Place for new items: %p\n", new_items);
-
- // copy the contents from the old array to the new
- memcpy(new_items, array->items, array->count * array->item_size);
-
- // do RCU update
- void *old_items = rcu_xchg_pointer(&array->items, new_items);
- array->allocated = new_size;
-
- dbg_da("Old items pointer: %p\n", old_items);
-
- // wait for readers to finish
- //synchronize_rcu();
- // deallocate the old array
- dbg_da("RCU synchronized, deallocating old items array at address %p."
- "\n", old_items);
- free(old_items);
-
- return 1;
-}
-
-/*----------------------------------------------------------------------------*/
-/* Public functions */
-/*----------------------------------------------------------------------------*/
-
-da_array_t *da_create(unsigned count, size_t item_size)
-{
- da_array_t *a = (da_array_t *)malloc(sizeof(da_array_t));
- if (a == NULL) {
- ERR_ALLOC_FAILED;
- return NULL;
- }
- da_initialize(a, count, item_size);
- return a;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int da_initialize(da_array_t *array, unsigned count, size_t item_size)
-{
- assert(array != NULL);
- pthread_mutex_init(&array->mtx, NULL);
- pthread_mutex_lock(&array->mtx);
-
- array->items = malloc(count * item_size);
- if (array->items == NULL) {
- array->allocated = 0;
- array->count = 0;
- ERR_ALLOC_FAILED;
- pthread_mutex_unlock(&array->mtx);
- return -1;
- }
-
- array->allocated = count;
- array->count = 0;
- array->item_size = item_size;
- memset(array->items, 0, count * item_size);
-
- pthread_mutex_unlock(&array->mtx);
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int da_reserve(da_array_t *array, unsigned count)
-{
- pthread_mutex_lock(&array->mtx);
- unsigned res = 0;
-
- assert(array->allocated >= array->count);
- if ((array->allocated - array->count) >= count) {
- dbg_da("Enough place in the array, no resize needed.\n");
- res = 0;
- } else {
- dbg_da("Resizing array.\n");
- res = da_resize(array, DA_LARGER);
- }
- pthread_mutex_unlock(&array->mtx);
-
- return res;
-}
-
-/*----------------------------------------------------------------------------*/
-
-int da_occupy(da_array_t *array, unsigned count)
-{
- pthread_mutex_lock(&array->mtx);
- unsigned res = 0;
- assert(array->allocated >= array->count);
-
- if ((array->allocated - array->count) < count) {
- dbg_da("Not enough place to occupy.\n");
- res = -1;
- } else {
- array->count += count;
- }
-
- pthread_mutex_unlock(&array->mtx);
- return res;
-}
-
-/*----------------------------------------------------------------------------*/
-
-unsigned da_try_reserve(const da_array_t *array, unsigned count)
-{
- assert(array->allocated >= array->count);
- if ((array->allocated - array->count) >= count) {
- return 0;
- }
-
- return 1;
-}
-
-/*----------------------------------------------------------------------------*/
-
-void da_release(da_array_t *array, unsigned count)
-{
- pthread_mutex_lock(&array->mtx);
-
- assert(array->allocated >= array->count);
- assert(array->count >= count);
- dbg_da("Decreasing count of items in array.\n");
- array->count -= count;
-
- pthread_mutex_unlock(&array->mtx);
-}
-
-/*----------------------------------------------------------------------------*/
-
-void da_destroy(da_array_t *array)
-{
- pthread_mutex_lock(&array->mtx);
- void *old_items = rcu_dereference(array->items);
- rcu_set_pointer(&array->items, NULL);
- pthread_mutex_unlock(&array->mtx);
-
- //synchronize_rcu();
- free(old_items);
- pthread_mutex_destroy(&array->mtx);
-}
-
-/*----------------------------------------------------------------------------*/
-
-void *da_get_items(const da_array_t *array)
-{
- return array->items;
-}
-
-/*----------------------------------------------------------------------------*/
-
-unsigned da_get_count(const da_array_t *array)
-{
- return array->count;
-}
diff --git a/src/common/dynamic-array.h b/src/common/dynamic-array.h
deleted file mode 100644
index 77a5d13..0000000
--- a/src/common/dynamic-array.h
+++ /dev/null
@@ -1,156 +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 dynamic-array.h
- *
- * \author Lubos Slovak <lubos.slovak@nic.cz>
- *
- * \brief Safe dynamic array implementation.
- *
- * \todo Somehow check if the array is initialized and do not use otherwise.
- * Maybe some magic, or so.
- * \todo This structure is too slow because of the mutex.
- *
- * \addtogroup common_lib
- * @{
- */
-
-#ifndef _KNOTD_COMMON_DYNAMIC_ARRAY_H_
-#define _KNOTD_COMMON_DYNAMIC_ARRAY_H_
-
-#include <string.h>
-#include <pthread.h>
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Dynamic array structure.
- *
- * Before using the dynamic array, it must be initialized using da_initialize().
- * When getting individual items always use da_get_items() to obtain pointer to
- * the actual array.
- *
- * Items in the array cannot be dereferenced (it uses void * for storing the
- * the items). It is needed to type-cast the item array (obtained by calling
- * da_get_items()) to a proper type before dereferencing.
- *
- * When adding items, first reserve enough space for them by callling
- * da_reserve() and subsequently tell the array about the inserted items by
- * calling da_occupy(). When removing, the array must be told about the fact
- * by calling da_release().
- *
- * For getting the actual number of items in array use da_get_count().
- *
- * When the array is no more needed, the da_destroy() function must be called
- * before deallocating the structure.
- */
-struct da_array {
- /*! \brief The actual array. The items can't be dereferenced directly.*/
- void *items;
-
- /*!
- * \brief Size of the stored items in bytes (used in counting of space
- * needed.
- */
- size_t item_size;
-
- /*!
- * \brief Size of allocated space in number of items that can be stored.
- */
- unsigned allocated;
-
- /*! \brief Number of items actually stored in the array. */
- unsigned count;
-
- /*! \brief Mutex. */
- pthread_mutex_t mtx;
-};
-
-typedef struct da_array da_array_t;
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \brief Creates and initializes the dynamic array.
- *
- * Initialization comprises of allocating place for \a count items of size
- * \a item_size and setting the items to zeros.
- *
- * \retval 0 if successful.
- * \retval -1 if not successful.
- */
-da_array_t *da_create(unsigned count, size_t item_size);
-
-/*!
- * \brief Initializes the dynamic array.
- *
- * Initialization comprises of allocating place for \a count items of size
- * \a item_size and setting the items to zeros.
- *
- * \retval 0 if successful.
- * \retval -1 if not successful.
- */
-int da_initialize(da_array_t *array, unsigned count, size_t item_size);
-
-/*!
- * \brief Reserves space for \a count more items.
- *
- * \retval 0 if successful and resizing was not necessary.
- * \retval 1 if successful and the array was enlarged.
- * \retval -1 if not successful - resizing was needed but could not be done.
- */
-int da_reserve(da_array_t *array, unsigned count);
-
-/*!
- * \brief Increases the number of items in array by \a count.
- *
- * \retval 0 If successful.
- * \retval -1 If not successful (not enough allocated space, i.e. must run
- * da_reserve()).
- */
-int da_occupy(da_array_t *array, unsigned count);
-
-/*!
- * \brief Tries to reserve space for \a count more items.
- *
- * \retval 0 if successful and resizing is not necessary.
- * \retval 1 if successful but the array will need to be resized.
- */
-unsigned da_try_reserve(const da_array_t *array, unsigned count);
-
-/*!
- * \brief Releases space taken by \a count items.
- */
-void da_release(da_array_t *array, unsigned count);
-
-/*!
- * \brief Poperly deallocates the array.
- */
-void da_destroy(da_array_t *array);
-
-/*!
- * \brief Returns the array of items as a void *.
- */
-void *da_get_items(const da_array_t *array);
-
-/*!
- * \brief Returns count of items in the array.
- */
-unsigned da_get_count(const da_array_t *array);
-
-/*----------------------------------------------------------------------------*/
-
-#endif /* _KNOTD_COMMON_DYNAMIC_ARRAY_H_ */
-
-/*! @} */
diff --git a/src/common/errors.c b/src/common/errors.c
index 3b770e9..3b770e9 100644..100755
--- a/src/common/errors.c
+++ b/src/common/errors.c
diff --git a/src/common/errors.h b/src/common/errors.h
index a2773ac..a2773ac 100644..100755
--- a/src/common/errors.h
+++ b/src/common/errors.h
diff --git a/src/common/evqueue.c b/src/common/evqueue.c
index 7614111..240ced6 100644..100755
--- a/src/common/evqueue.c
+++ b/src/common/evqueue.c
@@ -126,8 +126,11 @@ void evqueue_free(evqueue_t **q)
*q = 0;
/* Deinitialize. */
- close(eq->fds[EVQUEUE_READFD]);
- close(eq->fds[EVQUEUE_WRITEFD]);
+ for (int i = 0; i < 2; ++i) {
+ if (eq->fds[i] > -1) {
+ close(eq->fds[i]);
+ }
+ }
free(eq);
}
diff --git a/src/common/evqueue.h b/src/common/evqueue.h
index ffb3860..ffb3860 100644..100755
--- a/src/common/evqueue.h
+++ b/src/common/evqueue.h
diff --git a/src/common/evsched.c b/src/common/evsched.c
index cc2cf7c..8b6f721 100644..100755
--- a/src/common/evsched.c
+++ b/src/common/evsched.c
@@ -26,6 +26,15 @@
#define OPENBSD_SLAB_BROKEN
#endif
+/* Heap only cares about x<y. */
+static int compare_event_heap_nodes(event_t **e1, event_t **e2)
+{
+ if (timercmp(&(*e1)->tv, &(*e2)->tv, <)) return -1;
+ if (timercmp(&(*e1)->tv, &(*e2)->tv, >)) return 1;
+ return 0;
+}
+
+
/*!
* \brief Set event timer to T (now) + dt miliseconds.
*/
@@ -69,7 +78,7 @@ evsched_t *evsched_new()
#ifndef OPENBSD_SLAB_BROKEN
slab_cache_init(&s->cache.alloc, sizeof(event_t));
#endif
- init_list(&s->calendar);
+ heap_init(&s->heap, sizeof(event_t *), compare_event_heap_nodes, 0, NULL);
return s;
}
@@ -86,10 +95,16 @@ void evsched_delete(evsched_t **s)
pthread_mutex_destroy(&(*s)->rl);
pthread_mutex_destroy(&(*s)->mx);
pthread_cond_destroy(&(*s)->notify);
- node *n = 0, *nxt = 0;
- WALK_LIST_DELSAFE(n, nxt, (*s)->calendar) {
- evsched_event_free((*s), (event_t*)n);
+
+ while (! EMPTY_HEAP(&(*s)->heap)) /* FIXME: Would be faster to simply walk through the array */
+ {
+ event_t *e = *((event_t**)(HHEAD(&(*s)->heap)));
+ heap_delmin(&(*s)->heap);
+ evsched_event_free((*s), e);
}
+
+ free((*s)->heap.data);
+ (*s)->heap.data = NULL;;
#ifndef OPENBSD_SLAB_BROKEN
/* Free allocator. */
@@ -154,25 +169,26 @@ event_t* evsched_next(evsched_t *s)
while(1) {
/* Check event queue. */
- if (!EMPTY_LIST(s->calendar)) {
+ if (!EMPTY_HEAP(&s->heap)) {
/* Get current time. */
struct timeval dt;
gettimeofday(&dt, 0);
/* Get next event. */
- event_t *next_ev = HEAD(s->calendar);
+ event_t *next_ev = *((event_t**)HHEAD(&s->heap));
/* Immediately return. */
if (timercmp(&dt, &next_ev->tv, >=)) {
s->current = next_ev;
- rem_node(&next_ev->n);
+ heap_delmin(&s->heap);
pthread_mutex_unlock(&s->mx);
pthread_mutex_lock(&s->rl);
return next_ev;
}
/* Wait for next event or interrupt. Unlock calendar. */
+ /* FIXME: Blocks this the possibility to add any event earlier? */
struct timespec ts;
ts.tv_sec = next_ev->tv.tv_sec;
ts.tv_nsec = next_ev->tv.tv_usec * 1000L;
@@ -214,31 +230,12 @@ 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);
-
- /* Schedule event. */
- node *n = 0, *prev = 0;
- if (!EMPTY_LIST(s->calendar)) {
- WALK_LIST(n, s->calendar) {
- event_t* cur = (event_t *)n;
- if (timercmp(&cur->tv, &ev->tv, <)) {
- prev = n;
- } else {
- break;
- }
- }
- }
-
- /* Append to list. */
- ev->parent = s;
- if (prev) {
- insert_node(&ev->n, prev);
- } else {
- add_head(&s->calendar, &ev->n);
- }
-
+
+ heap_insert(&s->heap, &ev);
/* Unlock calendar. */
pthread_cond_signal(&s->notify);
@@ -293,6 +290,8 @@ event_t* evsched_schedule_term(evsched_t *s, uint32_t dt)
int evsched_cancel(evsched_t *s, event_t *ev)
{
+ int found;
+
if (!s || !ev) {
return -1;
}
@@ -303,19 +302,8 @@ int evsched_cancel(evsched_t *s, event_t *ev)
/* Lock calendar. */
pthread_mutex_lock(&s->mx);
- /* Find in list. */
- event_t *n = 0;
- int found = 0;
- WALK_LIST(n, s->calendar) {
- if (n == ev) {
- found = 1;
- break;
- }
- }
-
- /* Remove from list. */
- if (found) {
- rem_node(&ev->n);
+ if ((found = heap_find(&s->heap, &ev))) {
+ heap_delete(&s->heap, found);
}
/* Unlock calendar. */
diff --git a/src/common/evsched.h b/src/common/evsched.h
index 8ca9c62..47bf672 100644..100755
--- a/src/common/evsched.h
+++ b/src/common/evsched.h
@@ -68,7 +68,7 @@
#include <pthread.h>
#include "common/slab/slab.h"
-#include "common/lists.h"
+#include "common/heap.h"
#include "common/evqueue.h"
/*!
@@ -92,7 +92,7 @@ typedef struct {
event_t *current; /*!< Current running event. */
pthread_mutex_t mx; /*!< Event queue locking. */
pthread_cond_t notify; /*!< Event queue notification. */
- list calendar; /*!< Event calendar. */
+ struct heap heap;
struct {
slab_cache_t alloc; /*!< Events SLAB cache. */
pthread_mutex_t lock; /*!< Events cache spin lock. */
diff --git a/src/common/fdset.c b/src/common/fdset.c
index c915e01..c915e01 100644..100755
--- a/src/common/fdset.c
+++ b/src/common/fdset.c
diff --git a/src/common/fdset.h b/src/common/fdset.h
index 4fbd9bc..4038083 100644..100755
--- a/src/common/fdset.h
+++ b/src/common/fdset.h
@@ -74,7 +74,7 @@ typedef struct fdset_it_t {
/*!
* \brief File descriptor set implementation backend.
- * \notice Functions documentation following.
+ * \note Functions documentation following.
* \internal
*/
struct fdset_backend_t
diff --git a/src/common/fdset_epoll.c b/src/common/fdset_epoll.c
index d4481b5..d4481b5 100644..100755
--- a/src/common/fdset_epoll.c
+++ b/src/common/fdset_epoll.c
diff --git a/src/common/fdset_epoll.h b/src/common/fdset_epoll.h
index 58f25f8..58f25f8 100644..100755
--- a/src/common/fdset_epoll.h
+++ b/src/common/fdset_epoll.h
diff --git a/src/common/fdset_kqueue.c b/src/common/fdset_kqueue.c
index 108c572..108c572 100644..100755
--- a/src/common/fdset_kqueue.c
+++ b/src/common/fdset_kqueue.c
diff --git a/src/common/fdset_kqueue.h b/src/common/fdset_kqueue.h
index 4b650a7..4b650a7 100644..100755
--- a/src/common/fdset_kqueue.h
+++ b/src/common/fdset_kqueue.h
diff --git a/src/common/fdset_poll.c b/src/common/fdset_poll.c
index 19804f5..9b1c135 100644..100755
--- a/src/common/fdset_poll.c
+++ b/src/common/fdset_poll.c
@@ -71,9 +71,10 @@ int fdset_poll_add(fdset_t *fdset, int fd, int events)
}
/* Append. */
- int nid = fdset->nfds++;;
+ int nid = fdset->nfds++;
fdset->fds[nid].fd = fd;
fdset->fds[nid].events = POLLIN;
+ fdset->fds[nid].revents = 0;
return 0;
}
diff --git a/src/common/fdset_poll.h b/src/common/fdset_poll.h
index 68e9e69..68e9e69 100644..100755
--- a/src/common/fdset_poll.h
+++ b/src/common/fdset_poll.h
diff --git a/src/common/general-tree.c b/src/common/general-tree.c
index e1048e7..e1048e7 100644..100755
--- a/src/common/general-tree.c
+++ b/src/common/general-tree.c
diff --git a/src/common/general-tree.h b/src/common/general-tree.h
index 552638a..552638a 100644..100755
--- a/src/common/general-tree.h
+++ b/src/common/general-tree.h
diff --git a/src/common/heap.c b/src/common/heap.c
new file mode 100755
index 0000000..6fefb11
--- /dev/null
+++ b/src/common/heap.c
@@ -0,0 +1,149 @@
+/*
+ * Universal Heap Macros
+ *
+ * (c) 2012 Ondrej Filip <feela@network.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+/***
+ * [[intro]]
+ * Introduction
+ * ------------
+ *
+ * Binary heap is a simple data structure, which for example supports efficient insertions, deletions
+ * and access to the minimal inserted item. We define several macros for such operations.
+ * Note that because of simplicity of heaps, we have decided to define direct macros instead
+ * of a <<generic:,macro generator>> as for several other data structures in the Libucw.
+ *
+ * A heap is represented by a number of elements and by an array of values. Beware that we
+ * index this array from one, not from zero as do the standard C arrays.
+ *
+ * Most macros use these parameters:
+ *
+ * - @type - the type of elements
+ * - @num - a variable (signed or unsigned integer) with the number of elements
+ * - @heap - a C array of type @type; the heap is stored in `heap[1] .. heap[num]`; `heap[0]` is unused
+ * - @less - a callback to compare two element values; `less(x, y)` shall return a non-zero value iff @x is lower than @y
+ * - @swap - a callback to swap two array elements; `swap(heap, i, j, t)` must swap `heap[i]` with `heap[j]` with possible help of temporary variable @t (type @type).
+ *
+ * A valid heap must follow these rules:
+ *
+ * - `num >= 0`
+ * - `heap[i] >= heap[i / 2]` for each `i` in `[2, num]`
+ *
+ * The first element `heap[1]` is always lower or equal to all other elements.
+ *
+ * [[macros]]
+ * Macros
+ * ------
+ ***/
+
+#include "heap.h"
+#include <string.h>
+#include <stdlib.h>
+
+void _def_swap(struct heap *h, void *e1, void *e2)
+{
+ if (e1 == e2) return;
+ void *tmp = HTEMPELEMENT(h);
+ memcpy(tmp, e1, h->elm_size);
+ memcpy(e1, e2, h->elm_size);
+ memcpy(e2, tmp, h->elm_size);
+}
+
+
+int heap_init(struct heap *h, int elm_size, int (*cmp)(void *, void *), int init_size, void (*swap)(struct heap *, void *, void *))
+{
+ int isize = init_size ? init_size : INITIAL_HEAP_SIZE;
+
+ h->num = 0;
+ h->max_size = isize;
+ h->cmp = cmp;
+ h->swap = swap ? swap : _def_swap;
+ h->data = malloc((isize + 1) * elm_size);
+ h->elm_size = elm_size;
+
+ return h->data ? 1 : 0;
+};
+
+static inline void _heap_bubble_down(struct heap *h, int e)
+{
+ int e1;
+ for (;;)
+ {
+ e1 = 2*e;
+ if(e1 > h->num) break;
+ if((h->cmp(HELEMENT(h, e),HELEMENT(h,e1)) < 0) && (e1 == h->num || (h->cmp(HELEMENT(h, e),HELEMENT(h,e1+1)) < 0))) break;
+ if((e1 != h->num) && (h->cmp(HELEMENT(h, e1+1), HELEMENT(h,e1)) < 0)) e1++;
+ h->swap(h,HELEMENT(h,e),HELEMENT(h,e1));
+ e = e1;
+ }
+}
+
+static inline void _heap_bubble_up(struct heap *h, int e)
+{
+ int e1;
+ while (e > 1)
+ {
+ e1 = e/2;
+ if(h->cmp(HELEMENT(h, e1),HELEMENT(h,e)) < 0) break;
+ h->swap(h,HELEMENT(h,e),HELEMENT(h,e1));
+ e = e1;
+ }
+
+}
+
+void heap_delmin(struct heap *h)
+{
+ if(h->num == 0) return;
+ if(h->num > 1)
+ {
+ h->swap(h,HHEAD(h),HELEMENT(h,h->num));
+ }
+ --h->num;
+ _heap_bubble_down(h, 1);
+}
+
+int heap_insert(struct heap *h, void *e)
+{
+ if(h->num == h->max_size)
+ {
+ h->max_size = h->max_size * HEAP_INCREASE_STEP;
+ h->data = realloc(h->data, (h->max_size + 1) * h->elm_size);
+ }
+
+ h->num++;
+ memcpy(HELEMENT(h,h->num),e,h->elm_size);
+ _heap_bubble_up(h,h->num);
+
+ return h->data ? 1 :0 ;
+}
+
+int heap_find(struct heap *h, void *elm) /* FIXME - very slow */
+{
+ int i = h->num;
+
+ while(i > 0)
+ {
+ if(h->cmp(HELEMENT(h, i),elm) == 0) break;
+ --i;
+ }
+ return i;
+}
+
+void heap_delete(struct heap *h, int e)
+{
+ h->swap(h, HELEMENT(h, e), HELEMENT(h, h->num));
+ h->num--;
+ if(h->cmp(HELEMENT(h, e), HELEMENT(h, h->num + 1)) < 0) _heap_bubble_up(h, e);
+ else _heap_bubble_down(h, e);
+
+ if ((h->num > INITIAL_HEAP_SIZE) && (h->num < h->max_size / HEAP_DECREASE_THRESHOLD))
+ {
+ h->max_size = h->max_size / HEAP_INCREASE_STEP;
+ h->data = realloc(h->data, (h->max_size + 1) * h->elm_size);
+ }
+}
+
diff --git a/src/common/heap.h b/src/common/heap.h
new file mode 100755
index 0000000..d6f8a0b
--- /dev/null
+++ b/src/common/heap.h
@@ -0,0 +1,57 @@
+/* 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 heap.h
+ *
+ * \author Ondrej Filip <ondrej.filip@nic.cz>
+ *
+ * \brief Universal heap support
+ *
+ *
+ * \addtogroup common_lib
+ * @{
+ */
+
+#ifndef _HEAP_H_
+#define _HEAP_H_
+
+struct heap {
+ int num; /* Number of elements */
+ int elm_size; /* Size of a single element */
+ int max_size; /* Size of allocated memory */
+ int (*cmp)(void *, void *);
+ void (*swap)(struct heap *, void *, void *);
+ void *data;
+}; /* Array follows */
+
+#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 HTEMPELEMENT(h) ((h)->data) /* Pointer to tmp element (for swap) */
+#define HELEMENT(h,num) ((char*)(h)->data + (num) * (h)->elm_size)
+#define HHEAD(h) HELEMENT((h),1)
+#define EMPTY_HEAP(h) ((h)->num == 0) /* h->num == 0 */
+
+int heap_init(struct heap *, int, int (*cmp)(), int, void (*swap)());
+void heap_delmin(struct heap *);
+int heap_insert(struct heap *, void *);
+int heap_find(struct heap *, void *);
+void heap_delete(struct heap *, int);
+
+
+#endif /* _HEAP_H_ */
+
+/*! @} */
diff --git a/src/common/latency.c b/src/common/latency.c
index a563f58..a563f58 100644..100755
--- a/src/common/latency.c
+++ b/src/common/latency.c
diff --git a/src/common/latency.h b/src/common/latency.h
index d965c56..d965c56 100644..100755
--- a/src/common/latency.h
+++ b/src/common/latency.h
diff --git a/src/common/libtap/README b/src/common/libtap/README
index d57b81d..d57b81d 100644..100755
--- a/src/common/libtap/README
+++ b/src/common/libtap/README
diff --git a/src/common/libtap/tap.c b/src/common/libtap/tap.c
index d6bb995..d6bb995 100644..100755
--- a/src/common/libtap/tap.c
+++ b/src/common/libtap/tap.c
diff --git a/src/common/libtap/tap.h b/src/common/libtap/tap.h
index 89484f4..89484f4 100644..100755
--- a/src/common/libtap/tap.h
+++ b/src/common/libtap/tap.h
diff --git a/src/common/libtap/tap_unit.h b/src/common/libtap/tap_unit.h
index c248fde..c248fde 100644..100755
--- a/src/common/libtap/tap_unit.h
+++ b/src/common/libtap/tap_unit.h
diff --git a/src/common/lists.c b/src/common/lists.c
index 9a93733..9a93733 100644..100755
--- a/src/common/lists.c
+++ b/src/common/lists.c
diff --git a/src/common/lists.h b/src/common/lists.h
index 972ea49..897b1a9 100644..100755
--- a/src/common/lists.h
+++ b/src/common/lists.h
@@ -71,6 +71,7 @@ typedef struct list { /* In fact two overlayed nodes */
WALK_LIST_DELSAFE(n,nxt,list) { \
free(n); \
} \
+ init_list(&list); \
} while(0)
void add_tail(list *, node *);
diff --git a/src/common/log.c b/src/common/log.c
index c70f739..c70f739 100644..100755
--- a/src/common/log.c
+++ b/src/common/log.c
diff --git a/src/common/log.h b/src/common/log.h
index 305020c..305020c 100644..100755
--- a/src/common/log.h
+++ b/src/common/log.h
diff --git a/src/common/mempattern.c b/src/common/mempattern.c
index 5982e18..5982e18 100644..100755
--- a/src/common/mempattern.c
+++ b/src/common/mempattern.c
diff --git a/src/common/mempattern.h b/src/common/mempattern.h
index ae1fa78..ae1fa78 100644..100755
--- a/src/common/mempattern.h
+++ b/src/common/mempattern.h
diff --git a/src/common/modified_tree.h b/src/common/modified_tree.h
index 4c3e325..9ceddd1 100644..100755
--- a/src/common/modified_tree.h
+++ b/src/common/modified_tree.h
@@ -123,7 +123,7 @@
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(&(elm->data), &(self->data)); \
+ 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); \
diff --git a/src/common/print.c b/src/common/print.c
index 9764568..9764568 100644..100755
--- a/src/common/print.c
+++ b/src/common/print.c
diff --git a/src/common/print.h b/src/common/print.h
index 482f55e..482f55e 100644..100755
--- a/src/common/print.h
+++ b/src/common/print.h
diff --git a/src/common/prng.c b/src/common/prng.c
index 250a506..250a506 100644..100755
--- a/src/common/prng.c
+++ b/src/common/prng.c
diff --git a/src/common/prng.h b/src/common/prng.h
index 9f17a78..a64eabb 100644..100755
--- a/src/common/prng.h
+++ b/src/common/prng.h
@@ -39,3 +39,5 @@
double tls_rand();
#endif //_KNOTD_ACL_H_
+
+/*! @} */
diff --git a/src/common/ref.c b/src/common/ref.c
index 3b9c033..3b9c033 100644..100755
--- a/src/common/ref.c
+++ b/src/common/ref.c
diff --git a/src/common/ref.h b/src/common/ref.h
index 13a7037..13a7037 100644..100755
--- a/src/common/ref.h
+++ b/src/common/ref.h
diff --git a/src/common/skip-list.c b/src/common/skip-list.c
index cde08d7..cde08d7 100644..100755
--- a/src/common/skip-list.c
+++ b/src/common/skip-list.c
diff --git a/src/common/skip-list.h b/src/common/skip-list.h
index 784f366..784f366 100644..100755
--- a/src/common/skip-list.h
+++ b/src/common/skip-list.h
diff --git a/src/common/slab/alloc-common.h b/src/common/slab/alloc-common.h
index 32878ab..32878ab 100644..100755
--- a/src/common/slab/alloc-common.h
+++ b/src/common/slab/alloc-common.h
diff --git a/src/common/slab/slab.c b/src/common/slab/slab.c
index df30998..9a3e8de 100644..100755
--- a/src/common/slab/slab.c
+++ b/src/common/slab/slab.c
@@ -231,7 +231,7 @@ void __attribute__ ((destructor)) slab_deinit()
* Cache helper functions.
*/
-/* \notice Not used right now.
+/* \note Not used right now.
static void slab_dump(slab_t* slab) {
printf("%s: buffers (bufsize=%zuB, %u/%u free): \n",
diff --git a/src/common/slab/slab.h b/src/common/slab/slab.h
index 4ea7e31..4ea7e31 100644..100755
--- a/src/common/slab/slab.h
+++ b/src/common/slab/slab.h
diff --git a/src/common/sockaddr.c b/src/common/sockaddr.c
index b4e75ee..b4e75ee 100644..100755
--- a/src/common/sockaddr.c
+++ b/src/common/sockaddr.c
diff --git a/src/common/sockaddr.h b/src/common/sockaddr.h
index 52e621c..52e621c 100644..100755
--- a/src/common/sockaddr.h
+++ b/src/common/sockaddr.h
diff --git a/src/common/tree.h b/src/common/tree.h
index efea65b..efea65b 100644..100755
--- a/src/common/tree.h
+++ b/src/common/tree.h
diff --git a/src/config.h.in b/src/config.h.in
index bd88e96..b711d4f 100644..100755
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -27,6 +27,15 @@
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
+/* Define if FreeBSD-like cpuset_t exists. */
+#undef HAVE_CPUSET_BSD
+
+/* Define if Linux-like cpu_set_t exists. */
+#undef HAVE_CPUSET_LINUX
+
+/* Define if cpuset_t and cpuset(3) exists. */
+#undef HAVE_CPUSET_NETBSD
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
@@ -105,6 +114,9 @@
/* Define to 1 if you have the `pselect' function. */
#undef HAVE_PSELECT
+/* Define to 1 if you have the <pthread_np.h> header file. */
+#undef HAVE_PTHREAD_NP_H
+
/* Define to 1 if you have the `pthread_setaffinity_np' function. */
#undef HAVE_PTHREAD_SETAFFINITY_NP
@@ -237,6 +249,9 @@
/* RR debug. */
#undef KNOT_RR_DEBUG
+/* Hash table stash debug. */
+#undef KNOT_STASH_DEBUG
+
/* XFR debug. */
#undef KNOT_XFR_DEBUG
diff --git a/src/knot.conf.5 b/src/knot.conf.5
new file mode 100755
index 0000000..d086860
--- /dev/null
+++ b/src/knot.conf.5
@@ -0,0 +1,296 @@
+.TH "knot.conf" "5" "August 2012" "CZ.NIC Labs" "Knot DNS, version 1.1"
+.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
+# This is a comment.
+
+#
+# There are 4 main sections of this config file:
+# system, zones, interfaces and log
+#
+
+# Section 'system' contains general options for the server
+system {
+
+ # Identity of the server (see RFC 4892). Not used yet.
+ identity "I have no mouth and must scream";
+
+ # Version of the server (see RFC 4892). Not used yet.
+ version "0.1";
+
+ # 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";
+
+ # Custom pidfile path
+ # default: pidfile is created in 'storage'.
+ pidfile "/tmp/knot.pid";
+
+ # 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 1;
+
+ # User for running server
+ # May also specify user.group (f.e. knot.users)
+ user root;
+}
+
+# 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;
+ }
+}
+
+# Section 'zones' contains information about zones to be served.
+zones {
+
+ # Shared options for all listed zones
+ #
+
+ # Build differences from zone file changes
+ # 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 day, 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;
+ }
+}
+
+# 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/knot.service b/src/knot.service
index 36864d0..36864d0 100644..100755
--- a/src/knot.service
+++ b/src/knot.service
diff --git a/src/knot.spec b/src/knot.spec
index 5856aab..5856aab 100644..100755
--- a/src/knot.spec
+++ b/src/knot.spec
diff --git a/src/knot.sysconfig b/src/knot.sysconfig
index 99daeba..99daeba 100644..100755
--- a/src/knot.sysconfig
+++ b/src/knot.sysconfig
diff --git a/src/knot/common.h b/src/knot/common.h
index c321b94..ddf24b1 100644..100755
--- a/src/knot/common.h
+++ b/src/knot/common.h
@@ -85,14 +85,6 @@ typedef unsigned int uint; /*!< \brief Unsigned. */
/*! \brief Eliminate compiler warning with unused parameters. */
#define UNUSED(param) (void)(param)
-/*! \brief Type-safe minimum macro. */
-#define MIN(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 likely
/*! \brief Optimize for x to be true value. */
diff --git a/src/knot/conf/cf-lex.l b/src/knot/conf/cf-lex.l
index 16b0343..58d1f4b 100644..100755
--- a/src/knot/conf/cf-lex.l
+++ b/src/knot/conf/cf-lex.l
@@ -90,6 +90,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; }
+ixfr-from-differences { lval.t = yytext; return BUILD_DIFFS; }
interfaces { lval.t = yytext; return INTERFACES; }
address { lval.t = yytext; return ADDRESS; }
diff --git a/src/knot/conf/cf-parse.y b/src/knot/conf/cf-parse.y
index b415662..69a5415 100644..100755
--- a/src/knot/conf/cf-parse.y
+++ b/src/knot/conf/cf-parse.y
@@ -172,6 +172,7 @@ static void conf_zone_start(void *scanner, char *name) {
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);
@@ -266,6 +267,7 @@ static int conf_mask(void* scanner, int nval, int prefixlen) {
%token <tok> XFR_OUT
%token <tok> NOTIFY_IN
%token <tok> NOTIFY_OUT
+%token <tok> BUILD_DIFFS
%token <tok> INTERFACES ADDRESS PORT
%token <tok> IPA
@@ -630,12 +632,31 @@ zone_acl:
;
zone_start:
- | TEXT { conf_zone_start(scanner, $1.t); }
| USER { conf_zone_start(scanner, strdup($1.t)); }
| REMOTES { conf_zone_start(scanner, strdup($1.t)); }
| LOG_SRC { conf_zone_start(scanner, strdup($1.t)); }
| LOG { conf_zone_start(scanner, strdup($1.t)); }
| LOG_LEVEL { 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);
+ }
+ size_t len = 3 + 1 + strlen($3.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", $1.i, $3.t) < 0) {
+ cf_error(scanner,"failed to convert rfc2317 origin to string");
+ }
+ }
+ free($3.t);
+ conf_zone_start(scanner, name);
+ }
+ | TEXT { conf_zone_start(scanner, $1.t); }
;
zone:
@@ -643,6 +664,7 @@ zone:
| zone zone_acl '}'
| zone zone_acl_list
| zone FILENAME TEXT ';' { this_zone->file = $3.t; }
+ | zone BUILD_DIFFS BOOL ';' { this_zone->build_diffs = $3.i; }
| zone SEMANTIC_CHECKS BOOL ';' { this_zone->enable_checks = $3.i; }
| zone DISABLE_ANY BOOL ';' { this_zone->disable_any = $3.i; }
| zone DBSYNC_TIMEOUT NUM ';' { this_zone->dbsync_timeout = $3.i; }
@@ -669,6 +691,7 @@ zones:
ZONES '{'
| zones zone '}'
| zones DISABLE_ANY BOOL ';' { new_config->disable_any = $3.i; }
+ | zones BUILD_DIFFS BOOL ';' { new_config->build_diffs = $3.i; }
| zones SEMANTIC_CHECKS BOOL ';' { new_config->zone_checks = $3.i; }
| zones IXFR_FSLIMIT SIZE ';' { new_config->ixfr_fslimit = $3.l; }
| zones IXFR_FSLIMIT NUM ';' { new_config->ixfr_fslimit = $3.i; }
diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c
index 4bbf622..e0bd0ea 100644..100755
--- a/src/knot/conf/conf.c
+++ b/src/knot/conf/conf.c
@@ -73,74 +73,6 @@ void cf_error(void *scanner, const char *msg)
_parser_res = KNOTD_EPARSEFAIL;
}
-/*
- * Config helper functions.
- */
-
-/*! \brief Free TSIG key. */
-static void key_free(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);
- free(k);
-}
-
-/*! \brief Free config interfaces. */
-static void iface_free(conf_iface_t *iface)
-{
- if (!iface) {
- return;
- }
-
- free(iface->name);
- free(iface->address);
- free(iface);
-}
-
-/*! \brief Free config logs. */
-static void log_free(conf_log_t *log)
-{
- if (!log) {
- return;
- }
-
- if (log->file) {
- free(log->file);
- }
-
- /* Free loglevel mapping. */
- node *n = 0, *nxt = 0;
- WALK_LIST_DELSAFE(n, nxt, log->map) {
- free((conf_log_map_t*)n);
- }
-
- free(log);
-}
-
-/*! \brief Free config zones. */
-static void zone_free(conf_zone_t *zone)
-{
- if (!zone) {
- return;
- }
-
- /* Free ACL lists. */
- WALK_LIST_FREE(zone->acl.xfr_in);
- WALK_LIST_FREE(zone->acl.xfr_out);
- WALK_LIST_FREE(zone->acl.notify_in);
- WALK_LIST_FREE(zone->acl.notify_out);
-
- free(zone->name);
- free(zone->file);
- free(zone->db);
- free(zone->ixfr_db);
- free(zone);
-}
-
/*!
* \brief Call config hooks that need updating.
*
@@ -214,6 +146,11 @@ 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;
+ }
// Default policy for semantic checks
if (zone->enable_checks < 0) {
@@ -286,7 +223,12 @@ static int conf_process(conf_t *conf)
*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;
@@ -299,16 +241,26 @@ static int conf_process(conf_t *conf)
ret = KNOTD_ENOMEM; /* Error report. */
continue;
}
- strncpy(dest, conf->storage, stor_len + 1);
+ dpos = dest;
+ memcpy(dpos, conf->storage, stor_len + 1);
+ dpos += stor_len;
if (conf->storage[stor_len - 1] != '/') {
- strncat(dest, "/", 1);
+ *(dpos++) = '/';
+ *dpos = '\0';
}
const char *dbext = "diff.db";
- strncat(dest, zone->name, zname_len);
- strncat(dest, dbext, strlen(dbext));
+ memcpy(dpos, zone->name, zname_len + 1);
+ for (int 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();
return ret;
}
@@ -475,6 +427,7 @@ conf_t *conf_new(const char* path)
c->ixfr_fslimit = -1;
c->uid = -1;
c->gid = -1;
+ c->build_diffs = 0; /* Disable by default. */
return c;
}
@@ -553,33 +506,33 @@ void conf_truncate(conf_t *conf, int unload_hooks)
// Free keys
WALK_LIST_DELSAFE(n, nxt, conf->keys) {
- key_free((conf_key_t *)n);
+ conf_free_key((conf_key_t *)n);
}
// Free interfaces
WALK_LIST_DELSAFE(n, nxt, conf->ifaces) {
- iface_free((conf_iface_t*)n);
+ conf_free_iface((conf_iface_t*)n);
}
conf->ifaces_count = 0;
init_list(&conf->ifaces);
// Free logs
WALK_LIST_DELSAFE(n, nxt, conf->logs) {
- log_free((conf_log_t*)n);
+ conf_free_log((conf_log_t*)n);
}
conf->logs_count = 0;
init_list(&conf->logs);
// Free remotes
WALK_LIST_DELSAFE(n, nxt, conf->remotes) {
- iface_free((conf_iface_t*)n);
+ conf_free_iface((conf_iface_t*)n);
}
conf->remotes_count = 0;
init_list(&conf->remotes);
// Free zones
WALK_LIST_DELSAFE(n, nxt, conf->zones) {
- zone_free((conf_zone_t*)n);
+ conf_free_zone((conf_zone_t*)n);
}
conf->zones_count = 0;
init_list(&conf->zones);
@@ -784,3 +737,63 @@ char* strcpath(char *path)
return path;
}
+void conf_free_zone(conf_zone_t *zone)
+{
+ if (!zone) {
+ return;
+ }
+
+ /* Free ACL lists. */
+ WALK_LIST_FREE(zone->acl.xfr_in);
+ WALK_LIST_FREE(zone->acl.xfr_out);
+ WALK_LIST_FREE(zone->acl.notify_in);
+ WALK_LIST_FREE(zone->acl.notify_out);
+
+ 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);
+ free(k);
+}
+
+void conf_free_iface(conf_iface_t *iface)
+{
+ if (!iface) {
+ return;
+ }
+
+ free(iface->name);
+ free(iface->address);
+ free(iface);
+}
+
+void conf_free_log(conf_log_t *log)
+{
+ if (!log) {
+ return;
+ }
+
+ if (log->file) {
+ free(log->file);
+ }
+
+ /* Free loglevel mapping. */
+ node *n = 0, *nxt = 0;
+ WALK_LIST_DELSAFE(n, nxt, log->map) {
+ free((conf_log_map_t*)n);
+ }
+
+ free(log);
+}
+
diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h
index 7e1b61f..ae41454 100644..100755
--- a/src/knot/conf/conf.h
+++ b/src/knot/conf/conf.h
@@ -96,6 +96,7 @@ typedef struct conf_zone_t {
int disable_any; /*!< Disable ANY type queries for AA.*/
int notify_retries; /*!< NOTIFY query retries. */
int notify_timeout; /*!< Timeout for NOTIFY response (s). */
+ int build_diffs; /*!< Calculate differences from changes. */
struct {
list xfr_in; /*!< Remotes accepted for for xfr-in.*/
list xfr_out; /*!< Remotes accepted for xfr-out.*/
@@ -197,6 +198,7 @@ typedef struct conf_t {
int notify_timeout; /*!< Timeout for NOTIFY response in seconds. */
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. */
/*
* Implementation specifics
@@ -323,22 +325,6 @@ static inline conf_t* conf() {
return s_config; // Inline for performance reasons.
}
-/*!
- * \brief Lock configuration for reading.
- *
- * \return Configuration context.
- */
-static inline void conf_read_lock() {
- rcu_read_lock();
-}
-
-/*!
- * \brief Unlock configuration for reading.
- */
-static inline void conf_read_unlock() {
- rcu_read_unlock();
-}
-
/*
* Utilities.
*/
@@ -363,6 +349,18 @@ char* strcdup(const char *s1, const char *s2);
*/
char* strcpath(char *path);
+/*! \brief Free zone config. */
+void conf_free_zone(conf_zone_t *zone);
+
+/*! \brief Free TSIG key config. */
+void conf_free_key(conf_key_t *k);
+
+/*! \brief Free interface config. */
+void conf_free_iface(conf_iface_t *iface);
+
+/*! \brief Free log config. */
+void conf_free_log(conf_log_t *log);
+
#endif /* _KNOTD_CONF_H_ */
/*! @} */
diff --git a/src/knot/conf/logconf.c b/src/knot/conf/logconf.c
index 4d7334f..4d7334f 100644..100755
--- a/src/knot/conf/logconf.c
+++ b/src/knot/conf/logconf.c
diff --git a/src/knot/conf/logconf.h b/src/knot/conf/logconf.h
index 7b9e054..7b9e054 100644..100755
--- a/src/knot/conf/logconf.h
+++ b/src/knot/conf/logconf.h
diff --git a/src/knot/ctl/knotc_main.c b/src/knot/ctl/knotc_main.c
index 97412dd..07a9e38 100644..100755
--- a/src/knot/ctl/knotc_main.c
+++ b/src/knot/ctl/knotc_main.c
@@ -43,7 +43,8 @@ enum knotc_flag_t {
F_VERBOSE = 1 << 1,
F_WAIT = 1 << 2,
F_INTERACTIVE = 1 << 3,
- F_AUTO = 1 << 4
+ F_AUTO = 1 << 4,
+ F_UNPRIVILEGED= 1 << 5
};
static inline unsigned has_flag(unsigned flags, enum knotc_flag_t f) {
@@ -55,9 +56,9 @@ void help(int argc, char **argv)
{
printf("Usage: %sc [parameters] start|stop|restart|reload|running|"
"compile [additional]\n", PACKAGE_NAME);
- printf("Parameters:\n"
+ printf("\nParameters:\n"
" -c [file], --config=[file] Select configuration file.\n"
- " -j [num], --jobs=[num] Number of parallel tasks to run (only for 'compile').\n"
+ " -j [num], --jobs=[num] Number of parallel tasks to run when compiling.\n"
" -f, --force Force operation - override some checks.\n"
" -v, --verbose Verbose mode - additional runtime information.\n"
" -V, --version Print %s server version.\n"
@@ -66,7 +67,7 @@ void help(int argc, char **argv)
" -a, --auto Enable automatic recompilation (start or reload).\n"
" -h, --help Print help and usage.\n",
PACKAGE_NAME);
- printf("Actions:\n"
+ printf("\nActions:\n"
" start Start %s server zone (no-op if running).\n"
" stop Stop %s server (no-op if not running).\n"
" restart Stops and then starts %s server.\n"
@@ -75,8 +76,8 @@ void help(int argc, char **argv)
" running Check if server is running.\n"
" checkconf Check server configuration.\n"
"\n"
- " checkzone Check zones (accepts specific zones, f.e. "
- "'knotc checkzone example1.com example2.com').\n"
+ " checkzone Check zones (accepts specific zones, \n"
+ " e.g. 'knotc checkzone example1.com example2.com').\n"
" compile Compile zones (accepts specific zones, see above).\n",
PACKAGE_NAME, PACKAGE_NAME, PACKAGE_NAME, PACKAGE_NAME);
}
@@ -142,10 +143,15 @@ pid_t wait_cmd(pid_t proc, int *rc)
return proc;
}
-pid_t start_cmd(const char *argv[], int argc)
+pid_t start_cmd(const char *argv[], int argc, int flags)
{
pid_t chproc = fork();
if (chproc == 0) {
+
+ /* Alter privileges. */
+ if (flags & F_UNPRIVILEGED) {
+ proc_update_privileges(conf()->uid, conf()->gid);
+ }
/* Duplicate, it doesn't run from stack address anyway. */
char **args = malloc((argc + 1) * sizeof(char*));
@@ -180,7 +186,7 @@ pid_t start_cmd(const char *argv[], int argc)
int exec_cmd(const char *argv[], int argc)
{
int ret = 0;
- pid_t proc = start_cmd(argv, argc);
+ pid_t proc = start_cmd(argv, argc, 0);
wait_cmd(proc, &ret);
return ret;
}
@@ -292,15 +298,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
int rc = 0;
if (strcmp(action, "start") == 0) {
// Check pidfile for w+
- FILE* chkf = fopen(pidfile, "w+");
- if (chkf == NULL) {
- log_server_error("PID file '%s' is not writeable, "
- "refusing to start\n", pidfile);
- return 1;
- } else {
- fclose(chkf);
- chkf = NULL;
- }
+ log_server_info("Starting server...\n");
// Check PID
valid_cmd = 1;
@@ -332,7 +330,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
}
// Lock configuration
- conf_read_lock();
+ rcu_read_lock();
// Prepare command
const char *cfg = conf()->filename;
@@ -346,7 +344,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
};
// Unlock configuration
- conf_read_unlock();
+ rcu_read_unlock();
// Execute command
if (has_flag(flags, F_INTERACTIVE)) {
@@ -381,6 +379,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
if (strcmp(action, "stop") == 0) {
// Check PID
+ log_server_info("Stopping server...\n");
valid_cmd = 1;
rc = 0;
if (pid <= 0 || !pid_running(pid)) {
@@ -440,7 +439,6 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
}
}
- log_server_info("Restarting server.\n");
rc = execute("start", argv, argc, -1, flags, jobs, pidfile);
}
if (strcmp(action, "reload") == 0) {
@@ -527,7 +525,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
valid_cmd = 1;
// Lock configuration
- conf_read_lock();
+ rcu_read_lock();
// Generate databases for all zones
node *n = 0;
@@ -604,7 +602,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
}
fflush(stdout);
fflush(stderr);
- pid_t zcpid = start_cmd(args, ac);
+ pid_t zcpid = start_cmd(args, ac, F_UNPRIVILEGED);
zctask_add(tasks, jobs, zcpid, zone);
++running;
}
@@ -617,7 +615,7 @@ int execute(const char *action, char **argv, int argc, pid_t pid,
free(tasks);
// Unlock configuration
- conf_read_unlock();
+ rcu_read_unlock();
}
if (!valid_cmd) {
log_server_error("Invalid command: '%s'\n", action);
@@ -707,7 +705,7 @@ int main(int argc, char **argv)
log_server_error("Couldn't open configuration file "
"'%s'.\n", config_fn);
} else {
- log_server_error("Failed to parse configuration '%s'.\n",
+ log_server_error("Failed to load configuration '%s'.\n",
config_fn);
}
free(default_fn);
@@ -722,7 +720,7 @@ int main(int argc, char **argv)
log_levels_add(LOGT_STDOUT, LOG_ANY,
LOG_MASK(LOG_INFO)|LOG_MASK(LOG_DEBUG));
}
-
+
// Fetch PID
char* pidfile = pid_filename();
if (!pidfile) {
diff --git a/src/knot/ctl/process.c b/src/knot/ctl/process.c
index bb61804..d3fa2fc 100644..100755
--- a/src/knot/ctl/process.c
+++ b/src/knot/ctl/process.c
@@ -21,6 +21,9 @@
#include <errno.h>
#include <string.h>
#include <signal.h>
+#include <grp.h>
+#include <unistd.h>
+#include <assert.h>
#include "knot/common.h"
#include "knot/ctl/process.h"
@@ -29,7 +32,7 @@
char* pid_filename()
{
- conf_read_lock();
+ rcu_read_lock();
/* Read configuration. */
char* ret = 0;
@@ -37,7 +40,7 @@ char* pid_filename()
ret = strdup(conf()->pidfile);
}
- conf_read_unlock();
+ rcu_read_unlock();
return ret;
}
@@ -113,6 +116,7 @@ int pid_write(const char* fn)
int pid_remove(const char* fn)
{
if (unlink(fn) < 0) {
+ perror("unlink");
return KNOTD_EINVAL;
}
@@ -124,3 +128,45 @@ int pid_running(pid_t pid)
return kill(pid, 0) == 0;
}
+void proc_update_privileges(int uid, int gid)
+{
+#ifdef HAVE_SETGROUPS
+ /* Drop supplementary groups. */
+ if (uid != getuid() || gid != getgid()) {
+ if (setgroups(0, NULL) < 0) {
+ log_server_warning("Failed to drop supplementary groups"
+ " for uid '%d' (%s).\n",
+ getuid(), strerror(errno));
+ }
+ }
+#endif
+
+ /* Watch uid/gid. */
+ if (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()) {
+ 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. */
+ 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);
+ } else {
+ fclose(fp);
+ unlink(lfile);
+ }
+ free(lfile);
+}
diff --git a/src/knot/ctl/process.h b/src/knot/ctl/process.h
index d8f2f4c..a387add 100644..100755
--- a/src/knot/ctl/process.h
+++ b/src/knot/ctl/process.h
@@ -83,6 +83,15 @@ int pid_remove(const char* fn);
*/
int pid_running(pid_t pid);
+/*!
+ * \brief Update process privileges to new UID/GID.
+ *
+ * \param uid New user ID.
+ * \param gid New group ID.
+ *
+ */
+void proc_update_privileges(int uid, int gid);
+
#endif // _KNOTD_PROCESS_H_
/*! @} */
diff --git a/src/knot/main.c b/src/knot/main.c
index 99ee1cf..4486a1c 100644..100755
--- a/src/knot/main.c
+++ b/src/knot/main.c
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <getopt.h>
#include <limits.h>
+
#ifdef HAVE_CAP_NG_H
#include <cap-ng.h>
#endif /* HAVE_CAP_NG_H */
@@ -72,7 +73,7 @@ void help(int argc, char **argv)
{
printf("Usage: %sd [parameters]\n",
PACKAGE_NAME);
- printf("Parameters:\n"
+ printf("\nParameters:\n"
" -c, --config [file] Select configuration file.\n"
" -d, --daemonize Run server as a daemon.\n"
" -v, --verbose Verbose mode - additional runtime information.\n"
@@ -138,6 +139,7 @@ int main(int argc, char **argv)
emptyset.sa_flags = 0;
sigaction(SIGALRM, &emptyset, NULL); // Interrupt
sigaction(SIGPIPE, &emptyset, NULL); // Mask
+ rcu_register_thread();
// Setup event queue
evqueue_set(evqueue_new());
@@ -158,11 +160,10 @@ int main(int argc, char **argv)
server_t *server = server_create();
// Initialize configuration
- conf_read_lock();
+ rcu_read_lock();
conf_add_hook(conf(), CONF_LOG, log_conf_hook, 0);
conf_add_hook(conf(), CONF_ALL, server_conf_hook, server);
- conf_add_hook(conf(), CONF_ALL, zones_ns_conf_hook, server->nameserver);
- conf_read_unlock();
+ rcu_read_unlock();
// Find implicit configuration file
if (!config_fn) {
@@ -229,7 +230,7 @@ int main(int argc, char **argv)
log_server_error("Couldn't open configuration file "
"'%s'.\n", config_fn);
} else {
- log_server_error("Failed to parse configuration '%s'.\n",
+ log_server_error("Failed to load configuration '%s'.\n",
config_fn);
}
server_wait(server);
@@ -242,21 +243,28 @@ int main(int argc, char **argv)
}
log_server_info("\n");
- // Create server instance
- char* pidfile = pid_filename();
+ /* Alter privileges. */
+ proc_update_privileges(conf()->uid, conf()->gid);
+
+ /* 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)) == KNOTD_EOK) {
// Save PID
- int has_pid = 1;
+ has_pid = 1;
int rc = pid_write(pidfile);
if (rc < 0) {
has_pid = 0;
log_server_warning("Failed to create "
- "PID file '%s'.\n", pidfile);
+ "PID file '%s' (%s).\n",
+ pidfile, strerror(errno));
}
// Change directory if daemonized
@@ -370,7 +378,7 @@ int main(int argc, char **argv)
server_destroy(&server);
// Remove PID file
- if (pid_remove(pidfile) < 0) {
+ if (has_pid && pid_remove(pidfile) < 0) {
log_server_warning("Failed to remove PID file.\n");
}
@@ -381,6 +389,8 @@ int main(int argc, char **argv)
// Destroy event loop
evqueue_t *q = evqueue();
evqueue_free(&q);
+
+ rcu_unregister_thread();
// Free default config filename if exists
free(config_fn);
diff --git a/src/knot/other/debug.h b/src/knot/other/debug.h
index 1a8698e..1a8698e 100644..100755
--- a/src/knot/other/debug.h
+++ b/src/knot/other/debug.h
diff --git a/src/knot/other/error.c b/src/knot/other/error.c
index 70c84a3..7f005e7 100644..100755
--- a/src/knot/other/error.c
+++ b/src/knot/other/error.c
@@ -41,6 +41,8 @@ const error_table_t knotd_error_msgs[] = {
{KNOTD_ENOIPV6, "IPv6 support disabled."},
{KNOTD_EMALF, "Malformed data."},
{KNOTD_ESPACE, "Not enough space provided."},
- {KNOTD_EEXPIRED, "Resource is expired."},
+ {KNOTD_EEXPIRED, "Resource is expired."},
+ {KNOTD_ENODIFF, "Cannot create zone diff."},
+ {KNOTD_EUPTODATE, "Zone is up-to-date."},
{KNOTD_ERROR, 0}
};
diff --git a/src/knot/other/error.h b/src/knot/other/error.h
index 65c51cf..4b9efee 100644..100755
--- a/src/knot/other/error.h
+++ b/src/knot/other/error.h
@@ -63,8 +63,10 @@ enum knot_error_t {
KNOTD_EMALF, /*!< \brief Malformed data. */
KNOTD_ESPACE, /*!< \brief Not enough space provided. */
KNOTD_EEXPIRED, /*!< \brief Resource is expired. */
+ KNOTD_ENODIFF, /*!< \brief Cannot create zone diff. */
+ KNOTD_EUPTODATE, /*!< \brief Zone is up-to-date. */
- KNOTD_ERROR_COUNT = 21
+ KNOTD_ERROR_COUNT = 23
};
/*! \brief Table linking error messages to error codes. */
diff --git a/src/knot/server/dthreads.c b/src/knot/server/dthreads.c
index e2b45f2..0c38cfc 100644..100755
--- a/src/knot/server/dthreads.c
+++ b/src/knot/server/dthreads.c
@@ -21,15 +21,25 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
+#include <urcu.h>
+
#ifdef HAVE_CAP_NG_H
#include <cap-ng.h>
#endif /* HAVE_CAP_NG_H */
+#ifdef HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif /* HAVE_PTHREAD_NP_H */
#include "knot/common.h"
#include "knot/server/dthreads.h"
#include "common/log.h"
#include "knot/other/error.h"
+/* BSD cpu set compatibility. */
+#if defined(HAVE_CPUSET_BSD)
+typedef cpuset_t cpu_set_t;
+#endif
+
/*! \brief Lock thread state for R/W. */
static inline void lock_thread_rw(dthread_t *thread)
{
@@ -126,6 +136,7 @@ static void *thread_ep(void *data)
sigaddset(&ignset, SIGPIPE);
sigaddset(&ignset, SIGUSR1);
pthread_sigmask(SIG_BLOCK, &ignset, 0); /*! \todo Review under BSD (issue #1441). */
+ rcu_register_thread();
dbg_dt("dthreads: [%p] entered ep\n", thread);
@@ -207,6 +218,7 @@ static void *thread_ep(void *data)
lock_thread_rw(thread);
thread->state |= ThreadJoinable;
unlock_thread_rw(thread);
+ rcu_unregister_thread();
// Return
return 0;
@@ -854,22 +866,44 @@ int dt_stop(dt_unit_t *unit)
// return KNOTD_EOK;
//}
-int dt_setaffinity(dthread_t *thread, void *mask, size_t len)
+
+
+int dt_setaffinity(dthread_t *thread, unsigned* cpu_id, size_t cpu_count)
{
- if (thread == NULL || mask == NULL) {
+ if (thread == NULL) {
return KNOTD_EINVAL;
}
#ifdef HAVE_PTHREAD_SETAFFINITY_NP
- if (len != sizeof(cpu_set_t)) {
- return KNOTD_EINVAL;
+ int ret = -1;
+
+/* Linux, FreeBSD interface. */
+#if defined(HAVE_CPUSET_LINUX) || defined(HAVE_CPUSET_BSD)
+ cpu_set_t set;
+ CPU_ZERO(&set);
+ for (unsigned i = 0; i < cpu_count; ++i) {
+ CPU_SET(cpu_id[i], &set);
}
- pthread_t tid = pthread_self();
- int ret = pthread_setaffinity_np(tid, len, (cpu_set_t*)mask);
+ ret = pthread_setaffinity_np(thread->_thr, sizeof(cpu_set_t), &set);
+/* NetBSD interface. */
+#elif defined(HAVE_CPUSET_NETBSD)
+ cpuset_t *set = cpuset_create();
+ if (set == NULL) {
+ return KNOTD_ENOMEM;
+ }
+ cpuset_zero(set);
+ for (unsigned i = 0; i < cpu_count; ++i) {
+ cpuset_set(cpu_id[i], &set);
+ }
+ ret = pthread_setaffinity_np(thread->_thr, cpuset_size(set), set);
+ cpuset_destroy(set);
+#endif /* interface */
+
if (ret < 0) {
return KNOTD_ERROR;
}
-#else
+
+#else /* HAVE_PTHREAD_SETAFFINITY_NP */
return KNOTD_ENOTSUP;
#endif
@@ -988,8 +1022,17 @@ int dt_compact(dt_unit_t *unit)
int dt_online_cpus()
{
int ret = -1;
+/* Linux, Solaris, OS X 10.4+ */
#ifdef _SC_NPROCESSORS_ONLN
ret = (int) sysconf(_SC_NPROCESSORS_ONLN);
+#else
+/* FreeBSD, NetBSD, OpenBSD, OS X < 10.4 */
+#if HAVE_SYSCTLBYNAME
+ size_t rlen = sizeof(int);
+ if (sysctlbyname("hw.ncpu", &ret, &rlen, NULL, 0) < 0) {
+ ret = -1;
+ }
+#endif
#endif
return ret;
}
diff --git a/src/knot/server/dthreads.h b/src/knot/server/dthreads.h
index 8ba457b..758bc28 100644..100755
--- a/src/knot/server/dthreads.h
+++ b/src/knot/server/dthreads.h
@@ -254,12 +254,13 @@ int dt_stop(dt_unit_t *unit);
* \brief Set thread affinity to masked CPU's.
*
* \param thread Target thread instance.
- * \param mask CPU mask (should be pointer to cpu_set_t).
+ * \param cpu_id Array of CPU IDs to set affinity to.
+ * \param cpu_count Number of CPUs in the array, set to 0 for no CPU.
*
* \retval KNOTD_EOK on success.
* \retval KNOTD_EINVAL on invalid parameters.
*/
-int dt_setaffinity(dthread_t *thread, void *mask, size_t len);
+int dt_setaffinity(dthread_t *thread, unsigned* cpu_id, size_t cpu_count);
/*!
* \brief Set thread to execute another runnable.
diff --git a/src/knot/server/journal.c b/src/knot/server/journal.c
index f901837..fa84021 100644..100755
--- a/src/knot/server/journal.c
+++ b/src/knot/server/journal.c
@@ -117,8 +117,8 @@ static int journal_recover(journal_t *j)
}
/* Write back. */
- lseek(j->fd, JOURNAL_HSIZE - 2 * sizeof(uint16_t), SEEK_SET);
- if (!sfwrite(qstate, 2 * sizeof(uint16_t), j->fd)) {
+ 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 KNOTD_ERROR;
}
@@ -146,6 +146,7 @@ int journal_write_in(journal_t *j, journal_node_t **rn, uint64_t id, size_t len)
/* Calculate remaining bytes to reach file size limit. */
size_t fs_remaining = j->fslimit - j->fsize;
+ int seek_ret = 0;
/* Increase free segment if on the end of file. */
journal_node_t *n = j->nodes + j->qtail;
@@ -193,8 +194,8 @@ int journal_write_in(journal_t *j, journal_node_t **rn, uint64_t id, size_t len)
/* Write back evicted node. */
head->flags = JOURNAL_FREE;
- lseek(j->fd, JOURNAL_HSIZE + (j->qhead + 1) * node_len, SEEK_SET);
- if (!sfwrite(head, node_len, j->fd)) {
+ seek_ret = lseek(j->fd, JOURNAL_HSIZE + (j->qhead + 1) * node_len, SEEK_SET);
+ if (seek_ret < 0 || !sfwrite(head, node_len, j->fd)) {
return KNOTD_ERROR;
}
@@ -204,8 +205,8 @@ int journal_write_in(journal_t *j, journal_node_t **rn, uint64_t id, size_t len)
/* Write back query state. */
j->qhead = (j->qhead + 1) % j->max_nodes;
uint16_t qstate[2] = {j->qhead, j->qtail};
- lseek(j->fd, JOURNAL_HSIZE - 2 * sizeof(uint16_t), SEEK_SET);
- if (!sfwrite(qstate, 2 * sizeof(uint16_t), j->fd)) {
+ 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)) {
return KNOTD_ERROR;
}
@@ -260,8 +261,8 @@ int journal_write_out(journal_t *journal, journal_node_t *n)
journal->free.pos + journal->free.len);
/* Write back free segment state. */
- lseek(journal->fd, JOURNAL_HSIZE, SEEK_SET);
- if (!sfwrite(&journal->free, node_len, journal->fd)) {
+ int seek_ret = lseek(journal->fd, JOURNAL_HSIZE, SEEK_SET);
+ if (seek_ret < 0 || !sfwrite(&journal->free, node_len, journal->fd)) {
/* Node is marked valid and failed to shrink free space,
* node will be overwritten on the next write. Return error.
*/
@@ -278,8 +279,8 @@ int journal_write_out(journal_t *journal, journal_node_t *n)
* qtail - highest valid node identifier (most recently used)
*/
uint16_t qstate[2] = {journal->qhead, journal->qtail};
- lseek(journal->fd, JOURNAL_HSIZE - 2 * sizeof(uint16_t), SEEK_SET);
- if (!sfwrite(qstate, 2 * sizeof(uint16_t), journal->fd)) {
+ seek_ret = lseek(journal->fd, JOURNAL_HSIZE - 2 * sizeof(uint16_t), SEEK_SET);
+ if (seek_ret < 0 || !sfwrite(qstate, 2 * sizeof(uint16_t), journal->fd)) {
dbg_journal("journal: failed to write back queue state\n");
return KNOTD_ERROR;
}
@@ -297,11 +298,15 @@ int journal_update_crc(int fd)
char buf[4096];
ssize_t rb = 0;
crc_t crc = crc_init();
- lseek(fd, MAGIC_LENGTH + sizeof(crc_t), SEEK_SET);
+ if (lseek(fd, MAGIC_LENGTH + sizeof(crc_t), SEEK_SET) < 0) {
+ return KNOTD_ERROR;
+ }
while((rb = read(fd, buf, sizeof(buf))) > 0) {
crc = crc_update(crc, (const unsigned char *)buf, rb);
}
- lseek(fd, MAGIC_LENGTH, SEEK_SET);
+ if (lseek(fd, MAGIC_LENGTH, SEEK_SET) < 0) {
+ return KNOTD_ERROR;
+ }
if (!sfwrite(&crc, sizeof(crc_t), fd)) {
dbg_journal("journal: couldn't write CRC to fd=%d\n", fd);
return KNOTD_ERROR;
@@ -508,7 +513,12 @@ journal_t* journal_open(const char *fn, size_t fslimit, int mode, uint16_t bflag
/* Compare */
if (crc == crc_calc) {
- lseek(fd, MAGIC_LENGTH + sizeof(crc_t), SEEK_SET); /* Rewind. */
+ /* Rewind. */
+ if (lseek(fd, MAGIC_LENGTH + sizeof(crc_t), SEEK_SET) < 0) {
+ fcntl(fd, F_SETLK, &fl);
+ close(fd);
+ return NULL;
+ }
} else {
log_server_warning("Journal file '%s' CRC error, "
"it will be flushed.\n", fn);
@@ -717,10 +727,10 @@ int journal_read(journal_t *journal, uint64_t id, journal_cmp_t cf, char *dst)
(unsigned long long)id, n->pos, n->pos + n->len, n->flags);
/* Seek journal node. */
- lseek(journal->fd, n->pos, SEEK_SET);
+ int seek_ret = lseek(journal->fd, n->pos, SEEK_SET);
/* Read journal node content. */
- if (!sfread(dst, n->len, journal->fd)) {
+ if (seek_ret < 0 || !sfread(dst, n->len, journal->fd)) {
return KNOTD_ERROR;
}
@@ -741,8 +751,8 @@ int journal_write(journal_t *journal, uint64_t id, const char *src, size_t size)
}
/* Write data to permanent storage. */
- lseek(journal->fd, n->pos, SEEK_SET);
- if (!sfwrite(src, size, journal->fd)) {
+ int seek_ret = lseek(journal->fd, n->pos, SEEK_SET);
+ if (seek_ret < 0 || !sfwrite(src, size, journal->fd)) {
return KNOTD_ERROR;
}
@@ -765,7 +775,9 @@ int journal_map(journal_t *journal, uint64_t id, char **dst, size_t size)
/* Reserve data in permanent storage. */
/*! \todo This is only needed when inflating journal file. */
- lseek(journal->fd, n->pos, SEEK_SET);
+ if (lseek(journal->fd, n->pos, SEEK_SET) < 0) {
+ return KNOTD_ERROR;
+ }
char nbuf[4096] = {0};
size_t wb = sizeof(nbuf);
while (size > 0) {
@@ -868,8 +880,8 @@ int journal_update(journal_t *journal, journal_node_t *n)
i, (unsigned long long)n->id, n->flags);
/* Write back. */
- lseek(journal->fd, jn_fpos, SEEK_SET);
- if (!sfwrite(n, node_len, journal->fd)) {
+ int seek_ret = lseek(journal->fd, jn_fpos, SEEK_SET);
+ if (seek_ret < 0 || !sfwrite(n, node_len, journal->fd)) {
dbg_journal("journal: failed to writeback node=%llu to %ld\n",
(unsigned long long)n->id, jn_fpos);
return KNOTD_ERROR;
diff --git a/src/knot/server/journal.h b/src/knot/server/journal.h
index 322e25d..fd0e3a6 100644..100755
--- a/src/knot/server/journal.h
+++ b/src/knot/server/journal.h
@@ -359,3 +359,5 @@ void journal_release(journal_t *journal);
int journal_update_crc(int fd);
#endif /* _KNOTD_JOURNAL_H_ */
+
+/*! @} */
diff --git a/src/knot/server/notify.c b/src/knot/server/notify.c
index aa0a52b..d0292e8 100644..100755
--- a/src/knot/server/notify.c
+++ b/src/knot/server/notify.c
@@ -242,39 +242,49 @@ int notify_process_request(knot_nameserver_t *ns,
if (notify->parsed < notify->size) {
if (knot_packet_parse_rest(notify) != KNOT_EOK) {
dbg_notify("notify: failed to parse NOTIFY query\n");
- knot_ns_error_response(ns, knot_packet_id(notify),
- &notify->header.flags1,
- KNOT_RCODE_FORMERR, buffer,
- size);
+ knot_ns_error_response_from_query(ns, notify,
+ KNOT_RCODE_FORMERR,
+ buffer, size);
return KNOTD_EOK;
}
}
+ // check if it makes sense - if the QTYPE is SOA
+ if (knot_packet_qtype(notify) != KNOT_RRTYPE_SOA) {
+ // send back FORMERR
+ knot_ns_error_response_from_query(ns, notify,
+ KNOT_RCODE_FORMERR, buffer,
+ size);
+ return KNOTD_EOK;
+ }
+
// create NOTIFY response
dbg_notify("notify: creating response\n");
ret = notify_create_response(notify, buffer, size);
if (ret != KNOTD_EOK) {
dbg_notify("notify: failed to create NOTIFY response\n");
- knot_ns_error_response(ns, knot_packet_id(notify),
- &notify->header.flags1,
- KNOT_RCODE_SERVFAIL, buffer, size);
+ knot_ns_error_response_from_query(ns, notify,
+ KNOT_RCODE_SERVFAIL, buffer,
+ size);
return KNOTD_EOK;
}
// find the zone
+ rcu_read_lock();
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(ns, knot_packet_id(notify),
- &notify->header.flags1,
- KNOT_RCODE_REFUSED, buffer, size);
+ knot_ns_error_response_from_query(ns, notify,
+ KNOT_RCODE_FORMERR, buffer,
+ size);
return KNOTD_EOK;
}
notify_check_and_schedule(ns, z, from);
-
+ rcu_read_unlock();
return KNOTD_EOK;
}
@@ -294,13 +304,16 @@ int notify_process_response(knot_nameserver_t *nameserver,
*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 KNOTD_ENOENT;
}
if (!knot_zone_data(zone)) {
+ rcu_read_unlock();
return KNOTD_ENOENT;
}
@@ -318,6 +331,7 @@ int notify_process_response(knot_nameserver_t *nameserver,
/* Found waiting NOTIFY query? */
if (!match) {
+ rcu_read_unlock();
pthread_mutex_unlock(&zd->lock);
return KNOTD_ERROR;
}
@@ -327,6 +341,8 @@ int notify_process_response(knot_nameserver_t *nameserver,
/* Zone was removed/reloaded. */
pthread_mutex_unlock(&zd->lock);
+
+ rcu_read_unlock();
return KNOTD_EOK;
}
diff --git a/src/knot/server/notify.h b/src/knot/server/notify.h
index a9ba807..a9ba807 100644..100755
--- a/src/knot/server/notify.h
+++ b/src/knot/server/notify.h
diff --git a/src/knot/server/server.c b/src/knot/server/server.c
index 5611a0c..06f89b5 100644..100755
--- a/src/knot/server/server.c
+++ b/src/knot/server/server.c
@@ -22,8 +22,6 @@
#include <errno.h>
#include <openssl/evp.h>
#include <assert.h>
-#include <grp.h>
-
#include "common/prng.h"
#include "knot/common.h"
@@ -219,7 +217,7 @@ static int server_bind_sockets(server_t *server)
*/
/* Lock configuration. */
- conf_read_lock();
+ rcu_read_lock();
/* Prepare helper lists. */
int bound = 0;
@@ -290,7 +288,7 @@ static int server_bind_sockets(server_t *server)
}
/* Unlock configuration. */
- conf_read_unlock();
+ rcu_read_unlock();
/* Publish new list. */
list* oldlist = rcu_xchg_pointer(&server->ifaces, newlist);
@@ -331,7 +329,7 @@ static int server_bind_handlers(server_t *server)
}
/* Lock config. */
- conf_read_lock();
+ rcu_read_lock();
/* Estimate number of threads/manager. */
int thr_count = 0;
@@ -388,7 +386,7 @@ static int server_bind_handlers(server_t *server)
}
/* Unlock config. */
- conf_read_unlock();
+ rcu_read_unlock();
return KNOTD_EOK;
}
@@ -552,7 +550,7 @@ int server_start(server_t *server)
xfr_start(server->xfr_h);
/* Lock configuration. */
- conf_read_lock();
+ rcu_read_lock();
// Start dispatchers
int ret = KNOTD_EOK;
@@ -573,7 +571,7 @@ int server_start(server_t *server)
}
/* Unlock configuration. */
- conf_read_unlock();
+ rcu_read_unlock();
dbg_server("server: server started\n");
@@ -653,16 +651,13 @@ void server_stop(server_t *server)
{
dbg_server("server: stopping server\n");
- /* Wait for XFR master. */
- xfr_stop(server->xfr_h);
+ /* 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);
}
-
- /* Send termination event. */
- evsched_schedule_term(server->sched, 0);
/* Lock RCU. */
rcu_read_lock();
@@ -743,51 +738,9 @@ int server_conf_hook(const struct conf_t *conf, void *data)
"configured interfaces.\n");
}
}
-
- /* Lock configuration. */
- conf_read_lock();
- int priv_failed = 0;
-
-#ifdef HAVE_SETGROUPS
- /* Drop supplementary groups. */
- if (conf->gid > -1 || conf->uid > -1) {
- ret = setgroups(0, NULL);
-
- /* Collect results. */
- if (ret < 0) {
- log_server_error("Failed to set supplementary groups "
- "for uid '%d' (%s).\n",
- getuid(), strerror(errno));
- priv_failed = 1;
- }
- }
-#endif
-
- /* Watch uid/gid. */
- if (conf->gid > -1 && conf->gid != getgid()) {
- log_server_info("Changing group id to '%d'.\n", conf->gid);
- if (setregid(conf->gid, conf->gid) < 0) {
- log_server_error("Failed to change gid to '%d'.\n",
- conf->gid);
- priv_failed = 1;
- }
- }
- if (conf->uid > -1 && conf->uid != getuid()) {
- log_server_info("Changing user id to '%d'.\n", conf->uid);
- if (setreuid(conf->uid, conf->uid) < 0) {
- log_server_error("Failed to change uid to '%d'.\n",
- conf->uid);
- priv_failed = 1;
- }
- }
-
- if (priv_failed) {
- ret = KNOTD_EACCES;
- }
/* Exit if the server is not running. */
if (ret != KNOTD_EOK || !(server->state & ServerRunning)) {
- conf_read_unlock();
return KNOTD_ENOTRUNNING;
}
@@ -807,9 +760,6 @@ int server_conf_hook(const struct conf_t *conf, void *data)
}
}
- /* Unlock config. */
- conf_read_unlock();
-
return ret;
}
diff --git a/src/knot/server/server.h b/src/knot/server/server.h
index 79a4729..79a4729 100644..100755
--- a/src/knot/server/server.h
+++ b/src/knot/server/server.h
diff --git a/src/knot/server/socket.c b/src/knot/server/socket.c
index 4deb862..1e79f89 100644..100755
--- a/src/knot/server/socket.c
+++ b/src/knot/server/socket.c
@@ -99,6 +99,8 @@ int socket_connect(int fd, const char *addr, unsigned short port)
int socket_bind(int socket, int family, const char *addr, unsigned short port)
{
/* Check address family. */
+ int flag = 1;
+ int ret = 0;
struct sockaddr* paddr = 0;
socklen_t addrlen = 0;
struct sockaddr_in saddr;
@@ -150,12 +152,23 @@ int socket_bind(int socket, int family, const char *addr, unsigned short port)
addr, buf);
}
-#endif
+
+ /* Make the socket IPv6 only to allow 'any' for IPv4 and IPv6 at the same time. */
+#ifdef IPV6_V6ONLY
+ if (family == AF_INET6) {
+ /* Do not support mapping IPv4 in IPv6 sockets. */
+ ret = setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY,
+ &flag, sizeof(flag));
+ if (ret < 0) {
+ return KNOTD_EINVAL;
+ }
+ }
+#endif /* IPV6_V6ONLY */
+#endif /* DISABLE_IPV6 */
}
/* Reuse old address if taken. */
- int flag = 1;
- int ret = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR,
+ ret = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR,
&flag, sizeof(flag));
if (ret < 0) {
return KNOTD_EINVAL;
@@ -164,7 +177,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 (%d).\n",
+ 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 2185f03..2185f03 100644..100755
--- a/src/knot/server/socket.h
+++ b/src/knot/server/socket.h
diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index 977de0b..60f4301 100644..100755
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -104,7 +104,10 @@ static void tcp_sweep(fdset_t *set, int fd, void* data)
int r_port = 0;
struct sockaddr_storage addr;
socklen_t len = sizeof(addr);
- getpeername(fd, (struct sockaddr*)&addr, &len);
+ if (getpeername(fd, (struct sockaddr*)&addr, &len) < 0) {
+ dbg_net("tcp: sweep getpeername() on invalid socket=%d\n", fd);
+ return;
+ }
/* Translate */
if (addr.ss_family == AF_INET) {
@@ -158,15 +161,13 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
log_server_error("Socket type %d is not supported, "
"IPv6 support is probably disabled.\n",
w->ioh->type);
- return KNOTD_ECONNREFUSED;
+ return KNOTD_EINVAL;
}
/* Receive data. */
int n = tcp_recv(fd, qbuf, qbuf_maxlen, &addr);
if (n <= 0) {
dbg_net("tcp: client on fd=%d disconnected\n", fd);
- fdset_remove(w->fdset, fd);
- close(fd);
if (n == KNOTD_EAGAIN) {
char r_addr[SOCKADDR_STRLEN];
sockaddr_tostr(&addr, r_addr, sizeof(r_addr));
@@ -184,7 +185,7 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
knot_packet_t *packet =
knot_packet_new(KNOT_PACKET_PREALLOC_QUERY);
if (packet == NULL) {
- int ret = knot_ns_error_response_from_query(ns, qbuf, n,
+ int ret = knot_ns_error_response_from_query_wire(ns, qbuf, n,
KNOT_RCODE_SERVFAIL,
qbuf, &resp_len);
@@ -198,8 +199,8 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
int parse_res = knot_ns_parse_packet(qbuf, n, packet, &qtype);
if (unlikely(parse_res != KNOT_EOK)) {
if (parse_res > 0) { /* Returned RCODE */
- int ret = knot_ns_error_response_from_query(ns, qbuf, n,
- parse_res, qbuf, &resp_len);
+ int ret = knot_ns_error_response_from_query(ns, packet,
+ parse_res, qbuf, &resp_len);
if (ret == KNOT_EOK) {
tcp_reply(fd, qbuf, resp_len);
@@ -235,10 +236,9 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
/* Prepare context. */
res = xfr_request_init(&xfr, xfrt, XFR_FLAG_TCP, packet);
if (res != KNOTD_EOK) {
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_SERVFAIL, qbuf,
- &resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_SERVFAIL,
+ qbuf, &resp_len);
res = KNOTD_EOK;
break;
}
@@ -252,9 +252,9 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
return xfr_answer(ns, &xfr);
case KNOT_QUERY_UPDATE:
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_NOTIMPL, qbuf, &resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_NOTIMPL,
+ qbuf, &resp_len);
res = KNOTD_EOK;
break;
@@ -268,17 +268,17 @@ static int tcp_handle(tcp_worker_t *w, int fd, uint8_t *qbuf, size_t qbuf_maxlen
case KNOT_RESPONSE_NORMAL: /*!< TCP handler doesn't send queries. */
case KNOT_RESPONSE_AXFR: /*!< Processed in XFR handler. */
case KNOT_RESPONSE_IXFR: /*!< Processed in XFR handler. */
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_REFUSED, qbuf, &resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_REFUSED,
+ qbuf, &resp_len);
res = KNOTD_EOK;
break;
/* Unknown opcodes. */
default:
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_FORMERR, qbuf, &resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_FORMERR,
+ qbuf, &resp_len);
res = KNOTD_EOK;
break;
}
@@ -326,7 +326,11 @@ static int tcp_accept(int fd)
struct timeval tv;
tv.tv_sec = TCP_ACTIVITY_WD;
tv.tv_usec = 0;
- setsockopt(incoming, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ if (setsockopt(incoming, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
+ log_server_warning("Couldn't set up TCP connection "
+ "watchdog timer for fd=%d.\n",
+ incoming);
+ }
#endif
}
@@ -389,7 +393,7 @@ int tcp_send(int fd, uint8_t *msg, size_t msglen)
*/
#ifdef TCP_CORK
int cork = 1;
- setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
+ int uncork = setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
#endif
/* Send message size. */
@@ -406,9 +410,11 @@ int tcp_send(int fd, uint8_t *msg, size_t msglen)
}
#ifdef TCP_CORK
- /* Uncork. */
- cork = 0;
- setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
+ /* Uncork only if corked successfuly. */
+ if (uncork == 0) {
+ cork = 0;
+ setsockopt(fd, SOL_TCP, TCP_CORK, &cork, sizeof(cork));
+ }
#endif
return sent;
}
@@ -444,7 +450,9 @@ int tcp_recv(int fd, uint8_t *buf, size_t len, sockaddr_t *addr)
/* Get peer name. */
if (addr) {
socklen_t alen = addr->len;
- getpeername(fd, addr->ptr, &alen);
+ if (getpeername(fd, addr->ptr, &alen) < 0) {
+ return KNOTD_EMALF;
+ }
}
/* Receive payload. */
@@ -582,6 +590,12 @@ int tcp_loop_worker(dthread_t *thread)
"set to %ds\n",
it.fd, TCP_ACTIVITY_WD);
}
+ /*! \todo Refactor to allow erase on iterator.*/
+ if (ret == KNOTD_ECONNREFUSED) {
+ fdset_remove(w->fdset, it.fd);
+ close(it.fd);
+ break;
+ }
}
diff --git a/src/knot/server/tcp-handler.h b/src/knot/server/tcp-handler.h
index ab6baab..ab6baab 100644..100755
--- a/src/knot/server/tcp-handler.h
+++ b/src/knot/server/tcp-handler.h
diff --git a/src/knot/server/udp-handler.c b/src/knot/server/udp-handler.c
index dcb5b1f..fc4e9b1 100644..100755
--- a/src/knot/server/udp-handler.c
+++ b/src/knot/server/udp-handler.c
@@ -85,7 +85,7 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
if (packet == NULL) {
dbg_net("udp: failed to create packet on fd=%d\n", fd);
- int ret = knot_ns_error_response_from_query(ns, qbuf, qbuflen,
+ int ret = knot_ns_error_response_from_query_wire(ns, qbuf, qbuflen,
KNOT_RCODE_SERVFAIL,
qbuf, resp_len);
@@ -101,15 +101,25 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
if (unlikely(res != KNOTD_EOK)) {
dbg_net("udp: failed to parse packet on fd=%d\n", fd);
if (res > 0) { /* Returned RCODE */
- int ret = knot_ns_error_response_from_query(ns, qbuf,
- qbuflen,
- res, qbuf,
- resp_len);
+// int ret = knot_ns_error_response_from_query_wire(ns,
+// qbuf, qbuflen, res, qbuf, resp_len);
+ int ret = knot_ns_error_response_from_query(ns,
+ packet, res, qbuf, resp_len);
if (ret != KNOT_EOK) {
knot_packet_free(&packet);
return KNOTD_EMALF;
}
+ } else {
+ assert(res < 0);
+ int ret = knot_ns_error_response_from_query_wire(
+ ns, qbuf, qbuflen, KNOT_RCODE_SERVFAIL, qbuf,
+ resp_len);
+
+ if (ret != KNOT_EOK) {
+ knot_packet_free(&packet);
+ return ret;
+ }
}
knot_packet_free(&packet);
@@ -122,14 +132,6 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
res = KNOTD_ERROR;
switch(qtype) {
- /* Response types. */
- case KNOT_RESPONSE_NORMAL:
- res = zones_process_response(ns, addr, packet, qbuf, resp_len);
- break;
- case KNOT_RESPONSE_NOTIFY:
- res = notify_process_response(ns, packet, addr, qbuf, resp_len);
- break;
-
/* Query types. */
case KNOT_QUERY_NORMAL:
res = zones_normal_query_answer(ns, packet, addr, qbuf,
@@ -140,9 +142,9 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
* Bind responds with FORMERR.
*/
/*! \note Draft exists for AXFR/UDP, but has not been standardized. */
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_FORMERR, qbuf, resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_FORMERR, qbuf,
+ resp_len);
res = KNOTD_EOK;
break;
case KNOT_QUERY_IXFR:
@@ -151,7 +153,7 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
* but I have found no tool or slave server to actually attempt
* IXFR/UDP.
*/
- knot_packet_set_qtype(packet, KNOT_RRTYPE_SOA);
+// knot_packet_set_qtype(packet, KNOT_RRTYPE_SOA);
res = zones_normal_query_answer(ns, packet, addr,
qbuf, resp_len,
NS_TRANSPORT_UDP);
@@ -163,27 +165,26 @@ int udp_handle(int fd, uint8_t *qbuf, size_t qbuflen, size_t *resp_len,
case KNOT_QUERY_UPDATE:
dbg_net("udp: UPDATE query on fd=%d not implemented\n", fd);
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_NOTIMPL, qbuf, resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_NOTIMPL, qbuf,
+ resp_len);
res = KNOTD_EOK;
break;
/* Unhandled opcodes. */
case KNOT_RESPONSE_AXFR: /*!< Processed in XFR handler. */
case KNOT_RESPONSE_IXFR: /*!< Processed in XFR handler. */
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_REFUSED, qbuf,
- resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_REFUSED, qbuf,
+ resp_len);
res = KNOTD_EOK;
break;
/* Unknown opcodes */
default:
- knot_ns_error_response(ns, knot_packet_id(packet),
- &packet->header.flags1,
- KNOT_RCODE_FORMERR, qbuf, resp_len);
+ knot_ns_error_response_from_query(ns, packet,
+ KNOT_RCODE_FORMERR, qbuf,
+ resp_len);
res = KNOTD_EOK;
break;
}
@@ -204,17 +205,14 @@ static inline int udp_master_recvfrom(dthread_t *thread, stat_t *thread_stat)
/* Set CPU affinity to improve load distribution on multicore systems.
* Partial overlapping mask to be nice to scheduler.
*/
-#ifdef HAVE_PTHREAD_SETAFFINITY_NP
int cpcount = dt_online_cpus();
if (cpcount > 0) {
- unsigned tid = dt_get_id(thread);
- cpu_set_t cpus;
- CPU_ZERO(&cpus);
- CPU_SET(tid % cpcount, &cpus);
- CPU_SET((tid + 1) % cpcount, &cpus);
- dt_setaffinity(thread, &cpus, sizeof(cpu_set_t));
+ 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);
}
-#endif
knot_nameserver_t *ns = h->server->nameserver;
@@ -389,6 +387,7 @@ static inline int udp_master_recvmmsg(dthread_t *thread, stat_t *thread_stat)
free(addrs);
free(iov);
free(msgs);
+ close(sock);
return KNOTD_ENOMEM;
}
@@ -407,17 +406,14 @@ static inline int udp_master_recvmmsg(dthread_t *thread, stat_t *thread_stat)
/* Set CPU affinity to improve load distribution on multicore systems.
* Partial overlapping mask to be nice to scheduler.
*/
-#ifdef HAVE_PTHREAD_SETAFFINITY_NP
int cpcount = dt_online_cpus();
if (cpcount > 0) {
- unsigned tid = dt_get_id(thread);
- cpu_set_t cpus;
- CPU_ZERO(&cpus);
- CPU_SET(tid % cpcount, &cpus);
- CPU_SET((tid + 1) % cpcount, &cpus);
- dt_setaffinity(thread, &cpus, sizeof(cpu_set_t));
+ 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);
}
-#endif
/* Loop until all data is read. */
ssize_t n = 0;
@@ -433,7 +429,9 @@ static inline int udp_master_recvmmsg(dthread_t *thread, stat_t *thread_stat)
/* Error and interrupt handling. */
if (unlikely(n <= 0)) {
- if (errno != EINTR && errno != 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);
}
@@ -493,7 +491,10 @@ void __attribute__ ((constructor)) udp_master_init()
#ifdef MSG_WAITFORONE
/* Check for recvmmsg() support. */
if (dlsym(RTLD_DEFAULT, "recvmmsg") != 0) {
- _udp_master = udp_master_recvmmsg;
+ int r = recvmmsg(0, NULL, 0, 0, 0);
+ if (errno != ENOSYS) {
+ _udp_master = udp_master_recvmmsg;
+ }
}
/* Check for sendmmsg() support. */
diff --git a/src/knot/server/udp-handler.h b/src/knot/server/udp-handler.h
index f5fcd04..f5fcd04 100644..100755
--- a/src/knot/server/udp-handler.h
+++ b/src/knot/server/udp-handler.h
diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index a77f1f1..7863c9a 100644..100755
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -45,12 +45,19 @@
#define XFR_QUERY_WD 10 /*!< SOA/NOTIFY query timeout [s]. */
#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)
{
for(unsigned i = 0; i < h->unit->size; ++i) {
- evqueue_write(h->workers[i]->q, "", 1);
+ 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]);
+ }
}
}
@@ -63,6 +70,55 @@ static void xfr_request_deinit(knot_ns_xfr_t *r)
}
}
+/*!
+ * \brief Clean pending transfer data.
+ */
+static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
+{
+ int ret = KNOTD_EOK;
+ knot_changesets_t *chs = 0;
+
+ 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);
+ } 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;
+ }
+
+ // this function is called before new contents are created
+ assert(data->new_contents == NULL);
+
+ break;
+ }
+
+ /* Cleanup other data - so that the structure may be reused. */
+ data->packet_nr = 0;
+ data->tsig_data_size = 0;
+
+ dbg_xfr_detail("Done.\n");
+
+ return ret;
+}
+
/*! \brief Free allocated xfer descriptor (also deinitializes). */
static void xfr_free_task(knot_ns_xfr_t *task)
{
@@ -83,7 +139,8 @@ static void xfr_free_task(knot_ns_xfr_t *task)
}
/* Unlock if XFR/IN.*/
- if (task->type == XFR_TYPE_AIN || task->type == XFR_TYPE_IIN) {
+ 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) {
@@ -92,9 +149,24 @@ static void xfr_free_task(knot_ns_xfr_t *task)
}
}
- /* Deinitialize */
- xfr_request_deinit(task);
+ /* Free TSIG buffers. */
+ if (task->digest) {
+ free(task->digest);
+ task->digest = NULL;
+ task->digest_size = 0;
+ }
+ if (task->tsig_data) {
+ free(task->tsig_data);
+ task->tsig_data = NULL;
+ task->tsig_data_size = 0;
+ }
+
if (!task->session_closed) {
+ /* Cleanup pending request. */
+ if (is_xfer) {
+ xfr_xfrin_cleanup(w, task);
+ }
+
/* Remove fd-related data. */
xfrhandler_t *h = w->master;
pthread_mutex_lock(&h->tasks_mx);
@@ -102,6 +174,12 @@ static void xfr_free_task(knot_ns_xfr_t *task)
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);
}
@@ -139,11 +217,15 @@ static knot_ns_xfr_t *xfr_handler_task(xfrworker_t *w, int fd)
static int xfr_udp_timeout(knot_ns_xfr_t *data)
{
/* Close socket. */
+ rcu_read_lock();
knot_zone_t *z = data->zone;
if (z && knot_zone_get_contents(z) && knot_zone_data(z)) {
- log_zone_info("%s Failed, timeout exceeded.\n",
- data->msgpref);
+ if (!(knot_zone_flags(z) & KNOT_ZONE_DISCARDED)) {
+ log_zone_info("%s Failed, timeout exceeded.\n",
+ data->msgpref);
+ }
}
+ rcu_read_unlock();
/* Invalidate pending query. */
xfr_free_task(data);
@@ -161,15 +243,93 @@ static int xfr_udp_timeout(knot_ns_xfr_t *data)
*/
static int xfr_process_udp_resp(xfrworker_t *w, int fd, knot_ns_xfr_t *data)
{
+ /* Check if zone is valid. */
+ int ret = KNOTD_ECONNREFUSED;
+ rcu_read_lock();
+ if (knot_zone_flags(data->zone) & KNOT_ZONE_DISCARDED) {
+ rcu_read_unlock();
+ return ret;
+ }
+ rcu_read_unlock();
+
/* Receive msg. */
- ssize_t n = recvfrom(data->session, data->wire, data->wire_size, 0, data->addr.ptr, &data->addr.len);
+ ssize_t n = recvfrom(data->session, data->wire, data->wire_size,
+ 0, data->addr.ptr, &data->addr.len);
size_t resp_len = data->wire_size;
- if (n > 0) {
- udp_handle(fd, data->wire, n, &resp_len, &data->addr, w->ns);
+ if (n <= 0) {
+ return ret;
+ }
+
+ // parse packet
+ knot_packet_t *re = knot_packet_new(KNOT_PACKET_PREALLOC_RESPONSE);
+ if (re == NULL) {
+ return KNOTD_ENOMEM;
+ }
+
+ knot_packet_type_t rt = KNOT_RESPONSE_NORMAL;
+ ret = knot_ns_parse_packet(data->wire, n, re, &rt);
+ if (ret != KNOTD_EOK) {
+ knot_packet_free(&re);
+ return KNOTD_EOK; /* Ignore */
+ }
+
+ /* Ignore other packets. */
+ if (rt != KNOT_RESPONSE_NORMAL && rt != KNOT_RESPONSE_NOTIFY) {
+ knot_packet_free(&re);
+ return KNOTD_EOK; /* Ignore */
+ }
+ ret = knot_packet_parse_rest(re);
+ if (ret != KNOT_EOK) {
+ knot_packet_free(&re);
+ return KNOTD_EOK; /* Ignore */
+ }
+
+ // check TSIG
+ const knot_rrset_t * tsig_rr = knot_packet_tsig(re);
+ if (data->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);
+ if (ret != KNOT_EOK) {
+ log_server_error("%s %s\n",
+ data->msgpref, knot_strerror(ret));
+ knot_packet_free(&re);
+ return KNOTD_ECONNREFUSED;
+ }
+
+ }
+
+ // process response
+ switch(rt) {
+ case KNOT_RESPONSE_NORMAL:
+ ret = zones_process_response(w->ns, &data->addr, re,
+ data->wire, &resp_len);
+ break;
+ case KNOT_RESPONSE_NOTIFY:
+ ret = notify_process_response(w->ns, re, &data->addr,
+ data->wire, &resp_len);
+ break;
+ default:
+ break;
}
+ knot_packet_free(&re);
+
+ /* Check up-to-date zone. */
+ if (ret == KNOTD_EUPTODATE) {
+ log_server_info("%s %s\n", data->msgpref, knotd_strerror(ret));
+ ret = KNOTD_ECONNREFUSED;
+ }
+
/* Invalidate pending query. */
- return KNOTD_ECONNREFUSED;
+ if (ret == KNOTD_EOK) {
+ ret = KNOTD_ECONNREFUSED;
+ }
+ return ret;
}
/*! \brief Sweep non-replied connection. */
@@ -250,46 +410,6 @@ static knot_ns_xfr_t *xfr_register_task(xfrworker_t *w, const knot_ns_xfr_t *req
}
/*!
- * \brief Clean pending transfer data.
- */
-static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
-{
- int ret = KNOTD_EOK;
- knot_changesets_t *chs = 0;
-
- switch(data->type) {
- case XFR_TYPE_AIN:
- if (data->flags & XFR_FLAG_AXFR_FINISHED) {
- knot_zone_contents_deep_free(
- &data->new_contents, 1);
- } 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);
- }
-
- // this function is called before new contents are created
- assert(data->new_contents == NULL);
-
- break;
- }
-
- return ret;
-}
-
-/*!
* \brief Finalize XFR/IN transfer.
*
* \param w XFR worker.
@@ -382,7 +502,7 @@ static int xfr_xfrin_finalize(xfrworker_t *w, knot_ns_xfr_t *data)
/* Switch zone contents. */
switch_ret = xfrin_switch_zone(data->zone, data->new_contents,
- data->type);
+ data->type);
if (switch_ret != KNOT_EOK) {
log_zone_error("%s Failed to replace "
@@ -401,7 +521,7 @@ static int xfr_xfrin_finalize(xfrworker_t *w, knot_ns_xfr_t *data)
break;
}
- xfrin_cleanup_successful_update( &chs->changes);
+ xfrin_cleanup_successful_update(&chs->changes);
/* Free changesets, but not the data. */
knot_free_changesets(&chs);
@@ -418,24 +538,6 @@ static int xfr_xfrin_finalize(xfrworker_t *w, knot_ns_xfr_t *data)
}
/*!
- * \brief Prepare TSIG for XFR.
- */
-static int xfr_prepare_tsig(knot_ns_xfr_t *xfr, knot_key_t *key)
-{
- 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);
- 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;
-}
-
-/*!
* \brief Check TSIG if exists.
*/
static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode, char **tag)
@@ -473,15 +575,11 @@ static int xfr_check_tsig(knot_ns_xfr_t *xfr, knot_rcode_t *rcode, char **tag)
// return REFUSED
xfr->tsig_key = 0;
*rcode = KNOT_RCODE_REFUSED;
- return KNOT_EXFRREFUSED;
+ return KNOT_EXFRDENIED;
}
if (tsig_rr) {
tsig_algorithm_t alg = tsig_rdata_alg(tsig_rr);
if (tsig_alg_digest_length(alg) == 0) {
- log_server_info("%s Unsupported digest algorithm "
- "requested, treating as "
- "bad key.\n",
- xfr->msgpref);
*rcode = KNOT_RCODE_NOTAUTH;
xfr->tsig_key = NULL;
xfr->tsig_rcode = KNOT_TSIG_RCODE_BADKEY;
@@ -598,8 +696,14 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* 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) {
+ if (rcvd <= 0 || zone_discarded) {
data->wire_size = 0;
ret = KNOT_ECONN;
} else {
@@ -621,14 +725,15 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* AXFR-style IXFR. */
if (ret == KNOT_ENOIXFR) {
assert(data->type == XFR_TYPE_IIN);
- log_server_notice("%s Fallback to AXFR/IN.\n", data->msgpref);
+ log_server_notice("%s Fallback to AXFR.\n", data->msgpref);
data->type = XFR_TYPE_AIN;
- data->msgpref[0] = 'A';
+ data->msgpref[XFR_MSG_DLTTR] = 'A';
ret = knot_ns_process_axfrin(w->ns, data);
}
/* Check return code for errors. */
- dbg_xfr_verb("xfr: processed incoming XFR packet (res = %d)\n", ret);
+ dbg_xfr_verb("xfr: processed incoming XFR packet (%s)\n",
+ knot_strerror(ret));
/* Finished xfers. */
int xfer_finished = 0;
@@ -637,8 +742,8 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
}
/* IXFR refused, try again with AXFR. */
- if (zone && data->type == XFR_TYPE_IIN && ret == KNOT_EXFRREFUSED) {
- log_server_notice("%s Transfer failed, fallback to AXFR/IN.\n",
+ 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 */
@@ -650,20 +755,26 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
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[0] = 'A';
+ data->msgpref[XFR_MSG_DLTTR] = 'A';
return KNOTD_EOK;
}
}
}
+
+ rcu_read_unlock();
/* Handle errors. */
- 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 (!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));
+ }
}
/* Check finished zone. */
@@ -683,12 +794,11 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
knot_zone_t *zone = (knot_zone_t *)data->zone;
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
- /* Only for successful xfers. */
- if (ret > 0) {
+ /* Only for successful xfers on non-discarded zones. */
+ if (ret > 0 && !zone_discarded) {
ret = xfr_xfrin_finalize(w, data);
/* AXFR bootstrap timeout. */
- rcu_read_lock();
if (ret != KNOTD_EOK && !knot_zone_contents(zone)) {
/* Schedule request (60 - 90s random delay). */
int tmr_s = AXFR_BOOTSTRAP_RETRY;
@@ -702,25 +812,11 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
/* Update timers. */
server_t *server = (server_t *)knot_ns_get_data(w->ns);
zones_timers_update(zone, zd->conf, server->sched);
- rcu_read_unlock();
-
} else {
/* Cleanup */
xfr_xfrin_cleanup(w, data);
}
- /* Free TSIG buffers. */
- if (data->digest) {
- free(data->digest);
- data->digest = 0;
- data->digest_size = 0;
- }
- if (data->tsig_data) {
- free(data->tsig_data);
- data->tsig_data = 0;
- data->tsig_data_size = 0;
- }
-
/* Disconnect. */
result = KNOTD_ECONNREFUSED; /* Make it disconnect. */
}
@@ -753,6 +849,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
/* 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",
@@ -769,8 +866,11 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
strerror_r(errno, ebuf, sizeof(ebuf));
dbg_xfr("xfr: couldn't write request to evqueue: %s\n",
ebuf);
+ rcu_read_unlock();
return KNOTD_ERROR;
}
+
+ rcu_read_unlock();
return KNOTD_EOK;
} else {
zd->xfr_in.wrkr = w;
@@ -798,6 +898,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
}
if (ret < 0) {
+ rcu_read_unlock();
pthread_mutex_unlock(&zd->xfr_in.lock);
if (fd >= 0) {
close(fd);
@@ -811,6 +912,7 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
/* 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");
@@ -819,12 +921,11 @@ static int xfr_client_start(xfrworker_t *w, knot_ns_xfr_t *data)
}
/* Fetch zone contents. */
- rcu_read_lock();
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/IN on zone with no "
+ log_server_warning("%s Refusing to start IXFR on zone with no "
"contents.\n", data->msgpref);
close(data->session);
data->session = -1;
@@ -958,7 +1059,7 @@ static int xfr_answer_ixfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
"Fallback to AXFR.\n",
xfr->msgpref);
xfr->type = XFR_TYPE_AOUT;
- xfr->msgpref[0] = 'A';
+ xfr->msgpref[XFR_MSG_DLTTR] = 'A';
return xfr_answer_axfr(ns, xfr);
} else if (chsload == KNOTD_EMALF) {
xfr->rcode = KNOT_RCODE_FORMERR;
@@ -973,7 +1074,7 @@ static int xfr_answer_ixfr(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
/* Finally, answer. */
if (chsload == KNOTD_EOK) {
ret = knot_ns_answer_ixfr(ns, xfr);
- dbg_xfr("xfr: ns_answer_ixfr() = %d.\n", ret);
+ dbg_xfr("xfr: ns_answer_ixfr() = %s.\n", knot_strerror(ret));
}
return ret;
@@ -987,6 +1088,7 @@ static int xfr_update_msgpref(knot_ns_xfr_t *req, const char *keytag)
return KNOTD_EINVAL;
}
+ rcu_read_lock();
char r_addr[SOCKADDR_STRLEN];
char *r_key = NULL;
int r_port = sockaddr_portnum(&req->addr);
@@ -1013,13 +1115,12 @@ static int xfr_update_msgpref(knot_ns_xfr_t *req, const char *keytag)
}
/* Prepare log message. */
- conf_read_lock();
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);
- conf_read_unlock();
+ rcu_read_unlock();
return KNOTD_EINVAL;
} else {
zname = zd->conf->name;
@@ -1028,16 +1129,16 @@ static int xfr_update_msgpref(knot_ns_xfr_t *req, const char *keytag)
const char *pformat = NULL;
switch (req->type) {
case XFR_TYPE_AIN:
- pformat = "AXFR transfer of '%s/IN' with '%s@%d'%s:";
+ pformat = "Incoming AXFR transfer of '%s' with '%s@%d'%s:";
break;
case XFR_TYPE_IIN:
- pformat = "IXFR transfer of '%s/IN' with '%s@%d'%s:";
+ pformat = "Incoming IXFR transfer of '%s' with '%s@%d'%s:";
break;
case XFR_TYPE_AOUT:
- pformat = "AXFR transfer of '%s/OUT' to '%s@%d'%s:";
+ pformat = "Outgoing AXFR transfer of '%s' to '%s@%d'%s:";
break;
case XFR_TYPE_IOUT:
- pformat = "IXFR transfer of '%s/OUT' to '%s@%d'%s:";
+ pformat = "Outgoing IXFR transfer of '%s' to '%s@%d'%s:";
break;
case XFR_TYPE_NOTIFY:
pformat = "NOTIFY query of '%s' to '%s@%d'%s:";
@@ -1065,7 +1166,7 @@ static int xfr_update_msgpref(knot_ns_xfr_t *req, const char *keytag)
req->msgpref = msg;
}
- conf_read_unlock();
+ rcu_read_unlock();
free(r_key);
return KNOTD_EOK;
}
@@ -1277,9 +1378,11 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
return KNOTD_EINVAL;
}
+ rcu_read_lock();
int ret = knot_ns_init_xfr(ns, xfr);
+
int xfr_failed = (ret != KNOT_EOK);
- const char * errstr = knot_strerror(ret);
+ const char *errstr = knot_strerror(ret);
// use the QNAME as the zone name to get names also for
// zones that are not in the server
@@ -1310,6 +1413,23 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
}
free(keytag);
+ /* Announce. */
+ log_server_info("%s Started.\n", xfr->msgpref);
+ switch (ret) {
+ case KNOT_EXFRDENIED:
+ 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);
+ break;
+ default:
+ break;
+ }
+
/* Prepare place for TSIG data */
xfr->tsig_data = malloc(KNOT_NS_TSIG_DATA_MAX_SIZE);
if (xfr->tsig_data) {
@@ -1356,6 +1476,7 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *xfr)
free(xfr->tsig_data);
xfr->tsig_data = NULL;
xfr_request_deinit(xfr);
+ rcu_read_unlock();
/* Cleanup. */
free(xfr->digest);
@@ -1381,6 +1502,8 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
return KNOTD_ENOTRUNNING;
}
+ rcu_read_lock();
+
/* Update request. */
xfr.wire = buf;
xfr.wire_size = buflen;
@@ -1389,12 +1512,15 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
xfr_update_msgpref(&xfr, NULL);
/* Check if not already processing. */
- zonedata_t *zd = NULL;
- if (xfr.zone != NULL) {
- zd = (zonedata_t *)knot_zone_data(xfr.zone);
- }
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(xfr.zone);
- conf_read_lock();
+ /* 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 KNOTD_EOK;
+ }
/* Handle request. */
knot_ns_xfr_t *task = NULL;
@@ -1423,6 +1549,7 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
log_server_error("%s %s\n",
xfr.msgpref, knotd_strerror(ret));
}
+ knot_zone_release(xfr.zone); /* No further access to zone. */
}
break;
@@ -1431,21 +1558,21 @@ static int xfr_process_request(xfrworker_t *w, uint8_t *buf, size_t buflen)
/* Register task. */
task = xfr_register_task(w, &xfr);
if (!task) {
+ knot_zone_release(xfr.zone); /* No further access to zone. */
ret = KNOTD_ENOMEM;
- break;
+ } else {
+ /* Add timeout. */
+ fdset_set_watchdog(w->fdset, task->session, XFR_QUERY_WD);
+ log_server_info("%s Query issued.\n", xfr.msgpref);
+ ret = KNOTD_EOK;
}
-
- /* Add timeout. */
- fdset_set_watchdog(w->fdset, task->session, XFR_QUERY_WD);
- log_server_info("%s Query issued.\n", xfr.msgpref);
- ret = KNOTD_EOK;
break;
default:
log_server_error("Unknown XFR request type (%d).\n", xfr.type);
break;
}
- conf_read_unlock();
+ rcu_read_unlock();
/* Deinitialize (it is already registered, or discarded).
* Right now, this only frees temporary msgpref.
@@ -1506,7 +1633,6 @@ int xfr_worker(dthread_t *thread)
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. */
@@ -1527,6 +1653,8 @@ int xfr_worker(dthread_t *thread)
ret = xfr_process_event(w, it.fd, data, buf, buflen);
if (ret != KNOTD_EOK) {
xfr_free_task(data);
+ /*! \todo Refactor to allow erase on iterator.*/
+ break;
}
}
@@ -1551,6 +1679,11 @@ int xfr_worker(dthread_t *thread)
next_sweep.tv_sec += XFR_SWEEP_INTERVAL;
}
}
+
+ /* Check for interrupt request. */
+ if (ret == KNOTD_ENOTRUNNING) {
+ break;
+ }
}
/* Stop whole unit. */
@@ -1559,3 +1692,28 @@ int xfr_worker(dthread_t *thread)
thread->data = 0;
return KNOTD_EOK;
}
+
+int xfr_prepare_tsig(knot_ns_xfr_t *xfr, knot_key_t *key)
+{
+ if (xfr == NULL || key == NULL) {
+ return KNOTD_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 KNOTD_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;
+}
diff --git a/src/knot/server/xfr-handler.h b/src/knot/server/xfr-handler.h
index 02eb189..e2f5643 100644..100755
--- a/src/knot/server/xfr-handler.h
+++ b/src/knot/server/xfr-handler.h
@@ -170,6 +170,17 @@ int xfr_answer(knot_nameserver_t *ns, knot_ns_xfr_t *req);
*/
int xfr_worker(dthread_t *thread);
+/*!
+ * \brief Prepare TSIG for XFR.
+ * \param xfr XFR request.
+ * \param key Used TSIG key.
+ *
+ * \retval KNOTD_EOK on success.
+ * \retval KNOTD_EINVAL on NULL parameters.
+ * \retval KNOTD_ENOMEM when out of memory.
+ */
+int xfr_prepare_tsig(knot_ns_xfr_t *xfr, knot_key_t *key);
+
#endif // _KNOTD_XFRHANDLER_H_
/*! @} */
diff --git a/src/knot/server/zones.c b/src/knot/server/zones.c
index 37c1316..95ab2b1 100644..100755
--- a/src/knot/server/zones.c
+++ b/src/knot/server/zones.c
@@ -39,6 +39,7 @@
#include "libknot/updates/changesets.h"
#include "libknot/tsig-op.h"
#include "libknot/packet/response.h"
+#include "libknot/zone/zone-diff.h"
static const size_t XFRIN_CHANGESET_BINARY_SIZE = 100;
static const size_t XFRIN_CHANGESET_BINARY_STEP = 100;
@@ -46,7 +47,9 @@ static const size_t XFRIN_BOOTSTRAP_DELAY = 60; /*!< 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);
/*----------------------------------------------------------------------------*/
/*!
@@ -117,11 +120,13 @@ static int zonedata_destroy(knot_zone_t *zone)
/* Close IXFR db. */
journal_release(zd->ixfr_db);
+
+ /* Free assigned config. */
+ conf_free_zone(zd->conf);
free(zd);
/* Invalidate. */
- zone->dtor = 0;
zone->data = 0;
return KNOTD_EOK;
@@ -172,7 +177,7 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
char ebuf[256] = {0};
strerror_r(errno, ebuf, sizeof(ebuf));
log_server_warning("Couldn't open journal file for zone '%s', "
- "disabling IXFR/IN. (%s)\n", cfg->name, ebuf);
+ "disabling incoming IXFR. (%s)\n", cfg->name, ebuf);
}
/* Initialize IXFR database syncing event. */
@@ -180,7 +185,7 @@ static int zonedata_init(conf_zone_t *cfg, knot_zone_t *zone)
/* Set and install destructor. */
zone->data = zd;
- zone->dtor = zonedata_destroy;
+ knot_zone_set_dtor(zone, zonedata_destroy);
/* Set zonefile SOA serial. */
const knot_rrset_t *soa_rrs = 0;
@@ -305,6 +310,12 @@ static int zones_expire_ev(event_t *e)
zonedata_t *zd = (zonedata_t *)zone->data;
rcu_read_lock();
+ /* Check if zone is not discarded. */
+ if (knot_zone_flags(zone) & KNOT_ZONE_DISCARDED) {
+ rcu_read_unlock();
+ return KNOTD_EOK;
+ }
+
/* Do not issue SOA query if transfer is pending. */
int locked = pthread_mutex_trylock(&zd->xfr_in.lock);
if (locked != 0) {
@@ -336,10 +347,12 @@ static int zones_expire_ev(event_t *e)
pthread_mutex_unlock(&zd->xfr_in.lock);
log_server_warning("Non-existent zone expired. Ignoring.\n");
rcu_read_unlock();
- return 0;
+ return KNOTD_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();
@@ -368,7 +381,10 @@ static int zones_expire_ev(event_t *e)
pthread_mutex_unlock(&zd->xfr_in.lock);
rcu_read_unlock();
- return 0;
+ /* Release holding reference. */
+ knot_zone_release(zone);
+
+ return KNOTD_EOK;
}
/*!
@@ -377,16 +393,23 @@ static int zones_expire_ev(event_t *e)
static int zones_refresh_ev(event_t *e)
{
dbg_zones("zones: REFRESH or RETRY timer event\n");
+ rcu_read_lock();
knot_zone_t *zone = (knot_zone_t *)e->data;
if (zone == NULL || zone->data == NULL) {
+ rcu_read_unlock();
return KNOTD_EINVAL;
}
/* Cancel pending timers. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
+
+ /* Check if zone is not discarded. */
+ if (knot_zone_flags(zone) & KNOT_ZONE_DISCARDED) {
+ rcu_read_unlock();
+ return KNOTD_EOK;
+ }
/* Check for contents. */
- rcu_read_lock();
if (!knot_zone_contents(zone)) {
/* Bootstrap from XFR master. */
@@ -429,13 +452,20 @@ static int zones_refresh_ev(event_t *e)
++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);
+ if (ret != KNOTD_EOK) {
+ knot_zone_release(xfr_req.zone); /* Discard */
+ }
+ return ret;
- return xfr_request(zd->server->xfr_h, &xfr_req);
}
/* Do not issue SOA query if transfer is pending. */
@@ -485,17 +515,21 @@ static int zones_refresh_ev(event_t *e)
size_t buflen = SOCKET_MTU_SZ;
- /*! \todo [TSIG] CHANGE!!! only for compatibility now. */
- knot_ns_xfr_t xfr_req;
- memset(&xfr_req, 0, sizeof(knot_ns_xfr_t));
- xfr_req.wire = qbuf;
+ 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, &xfr_req, &buflen);
+ int ret = xfrin_create_soa_query(zone->name, &req, &buflen);
if (ret == KNOT_EOK) {
/* Create socket on random port. */
@@ -548,26 +582,30 @@ static int zones_refresh_ev(event_t *e)
evsched_event_finished(e->parent);
/* Watch socket. */
- knot_ns_xfr_t req;
- memset(&req, 0, sizeof(req));
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 == KNOTD_EOK) {
ret = xfr_request(zd->server->xfr_h, &req);
}
if (ret != KNOTD_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);
}
free(qbuf);
-
+
/* Unlock RCU. */
rcu_read_unlock();
@@ -580,21 +618,28 @@ static int zones_refresh_ev(event_t *e)
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 KNOTD_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 KNOTD_EINVAL;
}
-
- rcu_read_lock();
+
+ /* 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 KNOTD_EOK;
+ }
/* Check for answered/cancelled query. */
zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
@@ -675,7 +720,13 @@ static int zones_notify_send(event_t *e)
req.zone = zone;
memcpy(&req.addr, &ev->addr, sizeof(sockaddr_t));
memcpy(&req.saddr, &ev->saddr, sizeof(sockaddr_t));
- xfr_request(zd->server->xfr_h, &req);
+
+ /* Retain pointer to zone and issue request. */
+ knot_zone_retain(req.zone);
+ ret = xfr_request(zd->server->xfr_h, &req);
+ if (ret != KNOTD_EOK) {
+ knot_zone_release(req.zone); /* Discard */
+ }
}
free(qbuf);
@@ -724,6 +775,8 @@ static int zones_zonefile_sync_ev(event_t *e)
journal_t *j = journal_retain(zd->ixfr_db);
int ret = zones_zonefile_sync(zone, j);
journal_release(j);
+
+ rcu_read_lock();
if (ret == KNOTD_EOK) {
log_zone_info("Applied differences of '%s' to zonefile.\n",
zd->conf->name);
@@ -732,13 +785,14 @@ static int zones_zonefile_sync_ev(event_t *e)
"to zonefile.\n",
zd->conf->name);
}
+ rcu_read_unlock();
/* Reschedule. */
- conf_read_lock();
+ 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);
- conf_read_unlock();
+ rcu_read_unlock();
return ret;
}
@@ -813,11 +867,12 @@ static int zones_set_acl(acl_t **acl, list* acl_list)
static int zones_load_zone(knot_zone_t **dst, const char *zone_name,
const char *source, const char *filename)
{
- if (dst == NULL) {
+ if (dst == NULL || zone_name == NULL || source == NULL) {
return KNOTD_EINVAL;
}
*dst = NULL;
+ /* Duplicate zone name. */
size_t zlen = strlen(zone_name);
char *zname = NULL;
if (zlen > 0) {
@@ -827,8 +882,13 @@ static int zones_load_zone(knot_zone_t **dst, const char *zone_name,
} else {
return KNOTD_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 KNOTD_EINVAL;
+ }
+
/* Check if the compiled file still exists. */
struct stat st;
@@ -841,109 +901,90 @@ static int zones_load_zone(knot_zone_t **dst, const char *zone_name,
return KNOTD_EZONEINVAL;
}
- /* Check path */
- if (filename) {
- dbg_zones("zones: parsing zone database '%s'\n", filename);
- zloader_t *zl = 0;
- int ret = knot_zload_open(&zl, filename);
- switch(ret) {
- case KNOT_EOK:
- /* OK */
- break;
- case KNOT_EACCES:
- log_server_error("Failed to open compiled zone '%s' "
- "(Permission denied).\n", filename);
- free(zname);
- return KNOTD_EZONEINVAL;
- case KNOT_ENOENT:
- log_server_error("Couldn't find compiled zone. "
- "Please recompile '%s'.\n", zname);
- free(zname);
- return KNOTD_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 KNOTD_EZONEINVAL;
- case KNOT_EMALF:
- log_server_error("Compiled db '%s' is too old. "
- "Please recompile '%s'.\n",
- filename, zname);
- free(zname);
- return KNOTD_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);
- return KNOTD_EZONEINVAL;
- }
-
- /* Check the source file */
- 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);
-
- /* Check loaded name. */
- const knot_dname_t *dname = knot_zone_name(*dst);
- knot_dname_t *dname_req = 0;
- dname_req = knot_dname_new_from_str(zone_name, zlen, 0);
- if (knot_dname_compare(dname, dname_req) != 0) {
- log_server_warning("Origin of the zone db file is "
- "different than '%s'\n",
- zone_name);
- knot_zone_deep_free(dst, 0);
-
- }
- knot_dname_free(&dname_req);
-
- /* CLEANUP */
-// knot_zone_contents_dump(zone->contents, 1);
-// int errs = knot_zone_contents_integrity_check(zone->contents);
-// fprintf(stderr, "INTEGRITY CHECK OF ZONE. ERRORS: %d\n", errs);
-
- if (*dst != NULL) {
- /* save the timestamp from the zone db file */
- struct stat s;
- if (stat(filename, &s) < 0) {
- dbg_zones("zones: failed to stat() zone db, "
- "something is seriously wrong\n");
- knot_zone_deep_free(dst, 0);
- } else {
- knot_zone_set_version(*dst, s.st_mtime);
- }
- }
-
+ /* Attempt to open compiled zone for loading. */
+ int ret = KNOTD_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;
+ case KNOT_EACCES:
+ log_server_error("Failed to open compiled zone '%s' "
+ "(Permission denied).\n", filename);
+ free(zname);
+ return KNOTD_EZONEINVAL;
+ case KNOT_ENOENT:
+ log_server_error("Couldn't find compiled zone. "
+ "Please recompile '%s'.\n", zname);
+ free(zname);
+ return KNOTD_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 KNOTD_EZONEINVAL;
+ case KNOT_EMALF:
+ log_server_error("Compiled db '%s' is too old. "
+ "Please recompile '%s'.\n",
+ filename, zname);
+ free(zname);
+ return KNOTD_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);
+ return KNOTD_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);
knot_zload_close(zl);
-
- if (*dst == NULL) {
- log_server_error("Failed to load "
- "db '%s' for zone '%s'.\n",
- filename, zname);
- free(zname);
- return KNOTD_EZONEINVAL;
- }
- } else {
- /* db is null. */
- log_server_error("No file name for zone '%s'.\n", zname);
free(zname);
- return KNOTD_EINVAL;
+ return KNOTD_EZONEINVAL;
}
-
- /* CLEANUP */
-// knot_zone_dump(zone, 1);
+
+ /* 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);
+ 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);
+ ret = KNOTD_EZONEINVAL;
+ } else {
+ /* Save the timestamp from the zone db file. */
+ if (stat(filename, &st) < 0) {
+ dbg_zones("zones: failed to stat() zone db, "
+ "something is seriously wrong\n");
+ knot_zone_deep_free(dst, 0);
+ ret = KNOTD_EZONEINVAL;
+ } else {
+ knot_zone_set_version(*dst, st.st_mtime);
+ }
+ }
+ knot_dname_free(&dname_req);
+ knot_zload_close(zl);
free(zname);
-
- return KNOTD_EOK;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -1130,11 +1171,11 @@ static int zones_load_changesets(const knot_zone_t *zone,
dbg_zones_detail("Bad arguments: zd->ixfr_db=%p\n", zone->data);
return KNOTD_EINVAL;
}
-
- conf_read_lock();
+
+ rcu_read_lock();
dbg_xfr("xfr: loading changesets for zone '%s' from serial %u to %u\n",
zd->conf->name, from, to);
- conf_read_unlock();
+ rcu_read_unlock();
/* Retain journal for changeset loading. */
journal_t *j = journal_retain(zd->ixfr_db);
@@ -1167,7 +1208,7 @@ static int zones_load_changesets(const knot_zone_t *zone,
ret = knot_changesets_check_size(dst);
--dst->count;
if (ret != KNOT_EOK) {
- --dst->count;
+ //--dst->count;
dbg_xfr("xfr: failed to check changesets size: %s\n",
knot_strerror(ret));
journal_release(j);
@@ -1211,10 +1252,10 @@ static int zones_load_changesets(const knot_zone_t *zone,
/* Unpack binary data. */
int unpack_ret = zones_changesets_from_binary(dst);
- if (unpack_ret != KNOT_EOK) {
+ if (unpack_ret != KNOTD_EOK) {
dbg_xfr("xfr: failed to unpack changesets "
- "from binary, %s\n", knot_strerror(unpack_ret));
- return KNOTD_ERROR;
+ "from binary, %s\n", knotd_strerror(unpack_ret));
+ return unpack_ret;
}
/* Check for complete history. */
@@ -1288,7 +1329,7 @@ static int zones_journal_apply(knot_zone_t *zone)
&contents);
if (apply_ret != KNOT_EOK) {
log_server_error("Failed to apply changesets to"
- "'%s' - Apply failed: %s\n",
+ " '%s' - Apply failed: %s\n",
zd->conf->name,
knot_strerror(apply_ret));
ret = KNOTD_ERROR;
@@ -1297,27 +1338,27 @@ static int zones_journal_apply(knot_zone_t *zone)
xfrin_rollback_update(zone->contents,
&contents,
&chsets->changes);
- }
-
- /* Switch zone immediately. */
- rcu_read_unlock();
- apply_ret = xfrin_switch_zone(zone, contents,
- XFR_TYPE_IIN);
- rcu_read_lock();
- if (apply_ret == KNOT_EOK) {
- xfrin_cleanup_successful_update(
- &chsets->changes);
} else {
- log_server_error("Failed to apply changesets to"
- " '%s' - Switch failed: %s\n",
- zd->conf->name,
- knot_strerror(apply_ret));
- ret = KNOTD_ERROR;
-
- // Cleanup old and new contents
- xfrin_rollback_update(zone->contents,
- &contents,
- &chsets->changes);
+ /* Switch zone immediately. */
+ rcu_read_unlock();
+ apply_ret = xfrin_switch_zone(zone, contents,
+ XFR_TYPE_IIN);
+ rcu_read_lock();
+ if (apply_ret == KNOT_EOK) {
+ xfrin_cleanup_successful_update(
+ &chsets->changes);
+ } else {
+ log_server_error("Failed to apply "
+ "changesets to '%s' - Switch failed: "
+ "%s\n", zd->conf->name,
+ knot_strerror(apply_ret));
+ ret = KNOTD_ERROR;
+
+ // Cleanup old and new contents
+ xfrin_rollback_update(zone->contents,
+ &contents,
+ &chsets->changes);
+ }
}
}
} else {
@@ -1350,9 +1391,9 @@ static int zones_journal_apply(knot_zone_t *zone)
* \retval KNOTD_ERROR on unspecified error.
*/
static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
- knot_nameserver_t *ns, const knot_zonedb_t *db_old)
+ knot_nameserver_t *ns)
{
- if (z == NULL || dst == NULL || ns == NULL || db_old == NULL) {
+ if (z == NULL || dst == NULL || ns == NULL) {
return KNOTD_EINVAL;
}
@@ -1367,17 +1408,19 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
}
/* Try to find the zone in the current zone db. */
- knot_zone_t *zone = knot_zonedb_find_zone(db_old, dname);
+ rcu_read_lock();
+ 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 zone_changed = 0;
struct stat s = {};
int stat_ret = stat(z->file, &s);
- if (zone != NULL && stat_ret == 0) {
+ if (zone != NULL) {
/* if found, check timestamp of the file against the
* loaded zone
*/
- if (knot_zone_version(zone) < s.st_mtime) {
+ if (stat_ret == 0 && knot_zone_version(zone) < s.st_mtime) {
zone_changed = 1;
}
} else {
@@ -1385,6 +1428,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
}
/* Reload zone file. */
+ int is_bootstrapped = 0;
int ret = KNOTD_ERROR;
if (zone_changed) {
/* Zone file not exists and has master set. */
@@ -1398,9 +1442,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
zone = knot_zone_new_empty(owner);
if (zone != NULL) {
ret = KNOTD_EOK;
- log_server_info("Will attempt to bootstrap zone"
- " %s from AXFR master.\n",
- z->name);
+ is_bootstrapped = 1;
} else {
dbg_zones("zones: failed to create "
"stub zone '%s'.\n", z->name);
@@ -1410,9 +1452,21 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
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);
+ const knot_node_t *apex = NULL;
+ const knot_rrset_t *soa = NULL;
if (ret == KNOTD_EOK) {
- log_server_info("Loaded zone '%s'\n",
- z->name);
+ apex = knot_zone_contents_apex(
+ knot_zone_contents(zone));
+ soa = knot_node_rrset(apex,
+ KNOT_RRTYPE_SOA);
+ int64_t sn = 0;
+ if (apex && soa) {
+ sn = knot_rdata_soa_serial(
+ knot_rrset_rdata(soa));
+ if (sn < 0) sn = 0;
+ }
+ log_server_info("Loaded zone '%s' serial %u\n",
+ z->name, (uint32_t)sn);
}
}
@@ -1425,7 +1479,6 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
/* Initialize zone-related data. */
zonedata_init(z, zone);
*dst = zone;
-
}
} else {
dbg_zones_verb("zones: found '%s' in old database, "
@@ -1442,9 +1495,20 @@ 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. */
- zd->conf = z;
+ if (zd->conf != z) {
+ conf_free_zone(zd->conf);
+ zd->conf = z;
+ }
/* Update ACLs. */
dbg_zones("Updating zone ACLs.\n");
@@ -1486,7 +1550,13 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
}
/* Apply changesets from journal. */
- zones_journal_apply(zone);
+ int ar = zones_journal_apply(zone);
+ if (ar != KNOTD_EOK && ar != KNOTD_ERANGE && ar != KNOTD_ENOENT) {
+ log_server_warning("Failed to apply changesets "
+ "for zone '%s': %s\n",
+ z->name, knotd_strerror(ar));
+ }
+
/* Update events scheduled for zone. */
evsched_t *sch = ((server_t *)knot_ns_get_data(ns))->sched;
@@ -1526,10 +1596,32 @@ 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,
+ dname);
+ /* Ensure both new and old have zone contents. */
+ knot_zone_contents_t *zc = knot_zone_get_contents(zone);
+ knot_zone_contents_t *zc_old = knot_zone_get_contents(z_old);
+ if (z->build_diffs && zc != NULL && zc_old != NULL && zone_changed) {
+ int bd = zones_create_and_save_changesets(z_old, zone);
+ if (bd == KNOTD_ENODIFF) {
+ log_zone_warning("Zone file for '%s' changed, "
+ "but serial didn't - "
+ "won't create changesets.\n",
+ z->name);
+ } else if (bd != KNOTD_EOK) {
+ log_zone_warning("Failed to calculate differences"
+ " from the zone file update: "
+ "%s\n", knotd_strerror(bd));
+ }
+ }
+ rcu_read_unlock();
}
/* CLEANUP */
-// knot_zone_contents_dump(knot_zone_get_contents(zone), 1);
+// knot_zone_contents_dump(knot_zone_get_contents(zone), 1);
/* Directly discard zone. */
knot_dname_free(&dname);
@@ -1539,8 +1631,7 @@ static int zones_insert_zone(conf_zone_t *z, knot_zone_t **dst,
/*! \brief Structure for multithreaded zone loading. */
struct zonewalk_t {
knot_nameserver_t *ns;
- const knot_zonedb_t *db_old;
- knot_zonedb_t *db_new;
+ knot_zonedb_t *db_new;
pthread_mutex_t lock;
int inserted;
unsigned qhead;
@@ -1581,8 +1672,7 @@ static int zonewalker(dthread_t *thread)
continue;
}
- int ret = zones_insert_zone(zw->q[i], zones + inserted, zw->ns,
- zw->db_old);
+ int ret = zones_insert_zone(zw->q[i], zones + inserted, zw->ns);
if (ret == KNOTD_EOK) {
++inserted;
}
@@ -1592,11 +1682,15 @@ static int zonewalker(dthread_t *thread)
pthread_mutex_lock(&zw->lock);
zw->inserted += inserted;
for (int i = 0; i < inserted; ++i) {
+ zonedata_t *zd = (zonedata_t *)knot_zone_data(zones[i]);
if (knot_zonedb_add_zone(zw->db_new, zones[i]) != KNOT_EOK) {
- zonedata_t *zd = (zonedata_t *)knot_zone_data(zones[i]);
log_server_error("Failed to insert zone '%s' "
"into database.\n", zd->conf->name);
knot_zone_deep_free(zones + i, 0);
+ } else {
+ /* Unlink zone config from conf(),
+ * transferring ownership to zonedata. */
+ rem_node(&zd->conf->n);
}
}
pthread_mutex_unlock(&zw->lock);
@@ -1613,14 +1707,12 @@ static int zonewalker(dthread_t *thread)
*
* \param ns Name server instance.
* \param zone_conf Zone configuration.
- * \param db_old Old zone database.
* \param db_new New zone database.
*
* \return Number of inserted zones.
*/
static int zones_insert_zones(knot_nameserver_t *ns,
const list *zone_conf,
- const knot_zonedb_t *db_old,
knot_zonedb_t *db_new)
{
int inserted = 0;
@@ -1636,7 +1728,6 @@ static int zones_insert_zones(knot_nameserver_t *ns,
if (zw != NULL) {
memset(zw, 0, zwlen);
zw->ns = ns;
- zw->db_old = db_old;
zw->db_new = db_new;
zw->inserted = 0;
if (pthread_mutex_init(&zw->lock, NULL) < 0) {
@@ -1713,6 +1804,18 @@ dbg_zones_exec(
"from database.\n", name);
free(name);
);
+ /* Invalidate ACLs - since we would need to copy each
+ * remote data and keep ownership, I think it's no harm
+ * to drop all ACLs for the discarded zone.
+ * refs #1976 */
+ zonedata_t *zd = (zonedata_t*)knot_zone_data(old_zone);
+ conf_zone_t *zconf = zd->conf;
+ WALK_LIST_FREE(zconf->acl.xfr_in);
+ WALK_LIST_FREE(zconf->acl.xfr_out);
+ WALK_LIST_FREE(zconf->acl.notify_in);
+ WALK_LIST_FREE(zconf->acl.notify_out);
+
+ /* Remove from zone db. */
knot_zone_t * rm = knot_zonedb_remove_zone(db_old,
knot_zone_name(old_zone));
assert(rm == old_zone);
@@ -1758,8 +1861,10 @@ static int zones_verify_tsig_query(const knot_packet_t *query,
/*
* 2) Find the particular key used by the TSIG.
+ * Check not only name, but also the algorithm.
*/
- if (key && kname && knot_dname_compare(key->name, kname) == 0) {
+ if (key && kname && knot_dname_compare(key->name, kname) == 0
+ && key->algorithm == alg) {
dbg_zones_verb("Found claimed TSIG key for comparison\n");
} else {
*rcode = KNOT_RCODE_NOTAUTH;
@@ -1848,18 +1953,19 @@ static int zones_check_tsig_query(const knot_zone_t *zone,
assert(rcode != NULL);
assert(tsig_key_zone != NULL);
- const knot_rrset_t *tsig = NULL;
+ const knot_rrset_t *tsig = knot_packet_tsig(query);
- if (knot_packet_additional_rrset_count(query) > 0) {
- /*! \todo warning */
- 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");
- } else {
- tsig = NULL; /* Invalidate if not TSIG RRTYPE. */
- }
- }
+ // not required, TSIG is already found
+// if (knot_packet_additional_rrset_count(query) > 0) {
+// /*! \todo warning */
+// 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");
+// } else {
+// tsig = NULL; /* Invalidate if not TSIG RRTYPE. */
+// }
+// }
if (tsig == NULL) {
// no TSIG, this is completely valid
@@ -1894,7 +2000,7 @@ static int zones_check_tsig_query(const knot_zone_t *zone,
}
// save TSIG RR to query structure
- knot_packet_set_tsig(query, tsig);
+// knot_packet_set_tsig(query, tsig);
return ret;
}
@@ -1913,34 +2019,39 @@ 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 */
- *db_old = ns->zone_db;
- if (*db_old == NULL) {
+ if (ns->zone_db == NULL) {
+ rcu_read_unlock();
log_server_error("Missing zone database in nameserver structure"
".\n");
- rcu_read_unlock();
return KNOTD_ERROR;
}
+ rcu_read_unlock();
/* Create new zone DB */
knot_zonedb_t *db_new = knot_zonedb_new();
if (db_new == NULL) {
- rcu_read_unlock();
return KNOTD_ERROR;
}
log_server_info("Loading %d compiled zones...\n", conf->zones_count);
/* Insert all required zones to the new zone DB. */
- int inserted = zones_insert_zones(ns, &conf->zones, *db_old, db_new);
-
+ /*! \warning RCU must not be locked as some contents switching will
+ be required. */
+ int inserted = zones_insert_zones(ns, &conf->zones, db_new);
+
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;
dbg_zones_detail("zones: old db in nameserver: %p, old db stored: %p, "
"new db: %p\n", ns->zone_db, *db_old, db_new);
@@ -2020,19 +2131,29 @@ int zones_zonefile_sync(knot_zone_t *zone, journal_t *journal)
if (zd->zonefile_serial != serial_to) {
/* Save zone to zonefile. */
- conf_read_lock();
dbg_zones("zones: syncing '%s' differences to '%s' "
"(SOA serial %u)\n",
zd->conf->name, zd->conf->file, serial_to);
ret = zones_dump_zone_text(contents, zd->conf->file);
if (ret != KNOTD_EOK) {
- dbg_zones("zones: failed to sync '%s' to '%s'\n",
- zd->conf->name, zd->conf->file);
+ 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;
}
- conf_read_unlock();
+
+ /* Save zone to binary db file. */
+ ret = zones_dump_zone_binary(contents, zd->conf->db, zd->conf->file);
+ if (ret != KNOTD_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 KNOTD_ERROR;
+ }
/* Update journal entries. */
dbg_zones_verb("zones: unmarking all dirty nodes "
@@ -2144,15 +2265,16 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
? *rsize : 0);
// check for TSIG in the query
- 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);
- }
- }
+ // 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;
@@ -2170,7 +2292,10 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
break;
}
- if (zone == NULL && knot_packet_tsig(query) == NULL) {
+ 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.
*/
@@ -2181,10 +2306,9 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
dbg_zones_verb("Failed preparing response structure: %s.\n",
knot_strerror(rcode));
if (resp == NULL) {
- knot_ns_error_response(nameserver,
- knot_packet_id(query),
- &query->header.flags1,
- rcode, resp_wire, rsize);
+ knot_ns_error_response_from_query(nameserver, query,
+ rcode, resp_wire,
+ rsize);
rcu_read_unlock();
return KNOT_EOK;
}
@@ -2198,7 +2322,8 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
assert(rcode == KNOT_RCODE_NOERROR);
uint16_t tsig_rcode = 0;
knot_key_t *tsig_key_zone = NULL;
- uint64_t tsig_prev_time_signed = 0; /*! \todo Verify, as it was uninitialized! */
+ uint64_t tsig_prev_time_signed = 0;
+ /*! \todo Verify, as it was uninitialized! */
size_t answer_size = *rsize;
int ret = KNOT_EOK;
@@ -2206,6 +2331,7 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
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;
@@ -2228,8 +2354,20 @@ int zones_normal_query_answer(knot_nameserver_t *nameserver,
tsig_wire_maxsize(tsig_key_zone);
knot_packet_set_tsig_size(resp, tsig_max_size);
}
- ret = knot_ns_answer_normal(nameserver, zone, resp,
- resp_wire, &answer_size);
+
+ // handle IXFR queries
+ if (knot_packet_qtype(query) == KNOT_RRTYPE_IXFR) {
+ assert(transport == NS_TRANSPORT_UDP);
+ ret = knot_ns_answer_ixfr_udp(nameserver, zone,
+ resp, resp_wire,
+ &answer_size);
+ } else {
+ ret = knot_ns_answer_normal(nameserver, zone,
+ resp, resp_wire,
+ &answer_size,
+ transport ==
+ NS_TRANSPORT_UDP);
+ }
dbg_zones_detail("rsize = %zu\n", *rsize);
dbg_zones_detail("answer_size = %zu\n", answer_size);
@@ -2334,6 +2472,9 @@ 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);
*rsize = answer_size;
} else {
@@ -2385,6 +2526,7 @@ int zones_process_response(knot_nameserver_t *nameserver,
}
/* Find matching zone and ID. */
+ rcu_read_lock();
const knot_dname_t *zone_name = knot_packet_qname(packet);
/*! \todo Change the access to the zone db. */
knot_zone_t *zone = knot_zonedb_find_zone(
@@ -2392,7 +2534,6 @@ int zones_process_response(knot_nameserver_t *nameserver,
zone_name);
/* Get zone contents. */
- rcu_read_lock();
const knot_zone_contents_t *contents =
knot_zone_contents(zone);
@@ -2423,17 +2564,10 @@ int zones_process_response(knot_nameserver_t *nameserver,
evsched_t *sched =
((server_t *)knot_ns_get_data(nameserver))->sched;
if (ret == 0) {
- char r_addr[SOCKADDR_STRLEN];
- int r_port = sockaddr_portnum(from);
- sockaddr_tostr(from, r_addr, sizeof(r_addr));
- log_zone_info("SOA query of '%s' to '%s@%d': Answered, no "
- "transfer needed.\n",
- zd->conf->name, r_addr, r_port);
-
/* Reinstall timers. */
zones_timers_update(zone, zd->conf, sched);
rcu_read_unlock();
- return KNOTD_EOK;
+ return KNOTD_EUPTODATE;
}
assert(ret > 0);
@@ -2471,9 +2605,13 @@ int zones_process_response(knot_nameserver_t *nameserver,
/* Unlock zone contents. */
rcu_read_unlock();
- /* Enqueue XFR request. */
- return xfr_request(((server_t *)knot_ns_get_data(
- nameserver))->xfr_h, &xfr_req);
+ /* 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);
+ if (ret != KNOTD_EOK) {
+ knot_zone_release(xfr_req.zone); /* Discard */
+ }
}
return KNOTD_EOK;
@@ -2492,45 +2630,6 @@ knot_ns_xfr_type_t zones_transfer_to_use(zonedata_t *data)
/*----------------------------------------------------------------------------*/
-static int zones_find_zone_for_xfr(const knot_zone_contents_t *zone,
- const char **zonefile, const char **zonedb)
-{
- /* find the zone file name and zone db file name for the zone */
- conf_t *cnf = conf();
- node *n = NULL;
- WALK_LIST(n, cnf->zones) {
- conf_zone_t *zone_conf = (conf_zone_t *)n;
- knot_dname_t *zone_name = knot_dname_new_from_str(
- zone_conf->name, strlen(zone_conf->name), NULL);
- if (zone_name == NULL) {
- return KNOTD_ENOMEM;
- }
-
- int r = knot_dname_compare(zone_name, knot_node_owner(
- knot_zone_contents_apex(zone)));
-
- /* Directly discard dname, won't be needed. */
- knot_dname_free(&zone_name);
-
- if (r == 0) {
- /* found the right zone */
- *zonefile = zone_conf->file;
- *zonedb = zone_conf->db;
- return KNOTD_EOK;
- }
- }
-
- char *name = knot_dname_to_str(knot_node_owner(
- knot_zone_contents_apex(zone)));
- dbg_zones("zones: no zone found for the zone received by transfer "
- "(%s).\n", name);
- free(name);
-
- return KNOTD_ENOENT;
-}
-
-/*----------------------------------------------------------------------------*/
-
static int zones_open_free_filename(const char *old_name, char **new_name)
{
/* find zone name not present on the disk */
@@ -2571,7 +2670,6 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
FILE *f = fdopen(fd, "w");
if (f == NULL) {
log_zone_warning("Failed to open file descriptor for text zone.\n");
- close(fd);
unlink(new_fname);
free(new_fname);
return KNOTD_ERROR;
@@ -2580,11 +2678,14 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
if (zone_dump_text(zone, f) != KNOTD_EOK) {
log_zone_warning("Failed to save the transferred zone to '%s'.\n",
new_fname);
- close(fd);
+ fclose(f);
unlink(new_fname);
free(new_fname);
return KNOTD_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);
@@ -2596,8 +2697,7 @@ static int zones_dump_zone_text(knot_zone_contents_t *zone, const char *fname)
free(new_fname);
return KNOTD_ERROR;
}
-
-
+
free(new_fname);
return KNOTD_EOK;
}
@@ -2619,18 +2719,23 @@ static int zones_dump_zone_binary(knot_zone_contents_t *zone,
return KNOTD_ERROR;
}
- crc_t crc_value;
+ 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 KNOTD_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) {
- close(fd);
unlink(new_zonedb);
free(new_zonedb);
return KNOTD_ENOMEM;
@@ -2643,7 +2748,6 @@ static int zones_dump_zone_binary(knot_zone_contents_t *zone,
dbg_zdump("Failed to create CRC file path from %s.\n",
new_zonedb);
free(zonedb_crc);
- close(fd);
unlink(new_zonedb);
free(new_zonedb);
return KNOTD_ENOMEM;
@@ -2654,13 +2758,18 @@ static int zones_dump_zone_binary(knot_zone_contents_t *zone,
if (f_crc == NULL) {
dbg_zdump("Cannot open CRC file %s!\n",
zonedb_crc);
+ free(zonedb_crc);
unlink(new_zonedb);
+ free(new_zonedb);
return KNOTD_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 = KNOTD_EOK;
@@ -2689,7 +2798,6 @@ static int zones_dump_zone_binary(knot_zone_contents_t *zone,
free(new_zonedb_crc);
free(zonedb_crc);
- close(fd);
free(new_zonedb);
@@ -2700,33 +2808,48 @@ static int zones_dump_zone_binary(knot_zone_contents_t *zone,
int zones_save_zone(const knot_ns_xfr_t *xfr)
{
- if (xfr == NULL || xfr->new_contents == NULL) {
+ if (xfr == NULL || xfr->new_contents == NULL || xfr->zone == NULL) {
return KNOTD_EINVAL;
}
- knot_zone_contents_t *zone = xfr->new_contents;
-
- const char *zonefile = NULL;
- const char *zonedb = NULL;
+ rcu_read_lock();
- int ret = zones_find_zone_for_xfr(zone, &zonefile, &zonedb);
- if (ret != KNOTD_EOK) {
- return ret;
+ 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),
+ NULL);
+ const knot_dname_t *new_name = NULL;
+ new_name = knot_node_owner(knot_zone_contents_apex(new_zone));
+ int r = knot_dname_compare(cur_name, new_name);
+ knot_dname_free(&cur_name);
+ if (r != 0) {
+ rcu_read_unlock();
+ return KNOTD_EINVAL;
}
assert(zonefile != NULL && zonedb != NULL);
/* dump the zone into text zone file */
- ret = zones_dump_zone_text(zone, zonefile);
+ int ret = zones_dump_zone_text(new_zone, zonefile);
if (ret != KNOTD_EOK) {
+ rcu_read_unlock();
return KNOTD_ERROR;
}
/* dump the zone into binary db file */
- ret = zones_dump_zone_binary(zone, zonedb, zonefile);
+ ret = zones_dump_zone_binary(new_zone, zonedb, zonefile);
if (ret != KNOTD_EOK) {
+ rcu_read_unlock();
return KNOTD_ERROR;
}
+ rcu_read_unlock();
+
return KNOTD_EOK;
}
@@ -2970,10 +3093,10 @@ static int zones_store_changeset(const knot_changeset_t *chs, journal_t *j,
/* Reschedule sync timer. */
if (tmr) {
/* Fetch sync timeout. */
- conf_read_lock();
+ rcu_read_lock();
int timeout = zd->conf->dbsync_timeout;
timeout *= 1000; /* Convert to ms. */
- conf_read_unlock();
+ rcu_read_unlock();
/* Reschedule. */
dbg_xfr_verb("xfr: resuming SYNC "
@@ -3145,6 +3268,79 @@ int zones_xfr_load_changesets(knot_ns_xfr_t *xfr, uint32_t serial_from,
/*----------------------------------------------------------------------------*/
+int zones_create_and_save_changesets(const knot_zone_t *old_zone,
+ const knot_zone_t *new_zone)
+{
+ if (old_zone == NULL || old_zone->contents == NULL
+ || new_zone == NULL || new_zone->contents == NULL) {
+ dbg_zones("zones: create_changesets: "
+ "NULL arguments.\n");
+ return KNOTD_EINVAL;
+ }
+
+ knot_ns_xfr_t xfr;
+ memset(&xfr, 0, sizeof(xfr));
+ xfr.zone = (knot_zone_t *)old_zone;
+ knot_changesets_t *changesets;
+ int ret = knot_zone_diff_create_changesets(old_zone->contents,
+ new_zone->contents,
+ &changesets);
+ if (ret != KNOT_EOK) {
+ if (ret == KNOT_ERANGE) {
+ dbg_zones_detail("zones: create_changesets: "
+ "New serial was lower than the old "
+ "one.\n");
+ knot_free_changesets(&changesets);
+ return KNOTD_ERANGE;
+ } else if (ret == KNOT_ENODIFF) {
+ dbg_zones_detail("zones: create_changesets: "
+ "New serial was the same as the old "
+ "one.\n");
+ knot_free_changesets(&changesets);
+ return KNOTD_ENODIFF;
+ } else {
+ dbg_zones("zones: create_changesets: "
+ "Could not create changesets. Reason: %s\n",
+ knot_strerror(ret));
+ knot_free_changesets(&changesets);
+ return KNOTD_ERROR;
+ }
+ }
+
+ xfr.data = changesets;
+ journal_t *journal = zones_store_changesets_begin(&xfr);
+ if (journal == NULL) {
+ dbg_zones("zones: create_changesets: "
+ "Could not start journal operation.\n");
+ return KNOTD_ERROR;
+ }
+
+ ret = zones_store_changesets(&xfr);
+ if (ret != KNOTD_EOK) {
+ zones_store_changesets_rollback(journal);
+ dbg_zones("zones: create_changesets: "
+ "Could not store in the journal. Reason: %s.\n",
+ knotd_strerror(ret));
+
+ return ret;
+ }
+
+ ret = zones_store_changesets_commit(journal);
+ if (ret != KNOTD_EOK) {
+ dbg_zones("zones: create_changesets: "
+ "Could not commit to journal. Reason: %s.\n",
+ knotd_strerror(ret));
+
+ return ret;
+ }
+
+ knot_free_changesets(&changesets);
+
+ return KNOTD_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
{
if (!sch || !zone) {
@@ -3180,7 +3376,7 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
pthread_mutex_unlock(&zd->lock);
/* Check XFR/IN master server. */
- conf_read_lock();
+ rcu_read_lock();
if (zd->xfr_in.master.ptr) {
/* Schedule REFRESH timer. */
@@ -3198,13 +3394,12 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
/* Do not issue NOTIFY queries if stub. */
if (!knot_zone_contents(zone)) {
- conf_read_unlock();
+ rcu_read_unlock();
return KNOTD_EOK;
}
/* Schedule NOTIFY to slaves. */
conf_remote_t *r = 0;
- conf_read_lock();
WALK_LIST(r, cfzone->acl.notify_out) {
/* Fetch remote. */
@@ -3257,7 +3452,7 @@ int zones_timers_update(knot_zone_t *zone, conf_zone_t *cfzone, evsched_t *sch)
tmr_s, cfg_if->address, cfg_if->port);
}
- conf_read_unlock();
+ rcu_read_unlock();
return KNOTD_EOK;
}
@@ -3275,7 +3470,10 @@ int zones_cancel_notify(zonedata_t *zd, notify_ev_t *ev)
event_t *tmr = ev->timer;
ev->timer = 0;
pthread_mutex_unlock(&zd->lock);
- evsched_cancel(tmr->parent, tmr);
+ if (evsched_cancel(tmr->parent, tmr) == 0) {
+ dbg_notify("notify: NOTIFY event %p designated for cancellation "
+ "not found\n", tmr);
+ }
/* Re-lock and find again (if not deleted). */
pthread_mutex_lock(&zd->lock);
diff --git a/src/knot/server/zones.h b/src/knot/server/zones.h
index bb95b93..65e5a61 100644..100755
--- a/src/knot/server/zones.h
+++ b/src/knot/server/zones.h
@@ -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.*/
@@ -272,6 +272,23 @@ int zones_xfr_load_changesets(knot_ns_xfr_t *xfr, uint32_t serial_from,
uint32_t serial_to);
/*!
+ * \brief Creates changesets from zones difference.
+ *
+ * Also saves changesets to journal, which is taken from old zone.
+ *
+ * \param old_zone Old zone, previously served by server.
+ * \param new_zone New zone, to be served by server, after creating changesets.
+ *
+ * \retval KNOTD_EOK on success.
+ * \retval KNOTD_EINVAL on invalid arguments.
+ * \retval KNOTD_ERANGE when new serial is lower than the old one.
+ * \retval KNOTD_ENODIFF when new zone's serial are equal.
+ * \retval KNOTD_ERROR when there was error creating changesets.
+ */
+int zones_create_and_save_changesets(const knot_zone_t *old_zone,
+ const knot_zone_t *new_zone);
+
+/*!
* \brief Update zone timers.
*
* REFRESH/RETRY/EXPIRE timers are updated according to SOA.
diff --git a/src/knot/stat/gatherer.c b/src/knot/stat/gatherer.c
index 5b8eab6..5b8eab6 100644..100755
--- a/src/knot/stat/gatherer.c
+++ b/src/knot/stat/gatherer.c
diff --git a/src/knot/stat/gatherer.h b/src/knot/stat/gatherer.h
index 62b3939..62b3939 100644..100755
--- a/src/knot/stat/gatherer.h
+++ b/src/knot/stat/gatherer.h
diff --git a/src/knot/stat/stat-common.h b/src/knot/stat/stat-common.h
index 032e32b..032e32b 100644..100755
--- a/src/knot/stat/stat-common.h
+++ b/src/knot/stat/stat-common.h
diff --git a/src/knot/stat/stat.c b/src/knot/stat/stat.c
index a473085..a473085 100644..100755
--- a/src/knot/stat/stat.c
+++ b/src/knot/stat/stat.c
diff --git a/src/knot/stat/stat.h b/src/knot/stat/stat.h
index 0cf1454..0cf1454 100644..100755
--- a/src/knot/stat/stat.h
+++ b/src/knot/stat/stat.h
diff --git a/src/knot/zone/semantic-check.c b/src/knot/zone/semantic-check.c
index fc20c29..20043df 100644..100755
--- a/src/knot/zone/semantic-check.c
+++ b/src/knot/zone/semantic-check.c
@@ -16,8 +16,7 @@ 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 or in "
- "delegation point!\n",
+ [-ZC_ERR_MISSING_NS_DEL_POINT] = "NS record missing in zone apex!\n",
[-ZC_ERR_RRSIG_RDATA_TYPE_COVERED] =
"RRSIG: Type covered rdata field is wrong!\n",
@@ -169,7 +168,7 @@ int err_handler_handle_error(err_handler_t *handler,
return KNOT_EBADARG;
}
- /*!< \todo this is so wrong! This should not even return anything. */
+ /*!< \todo #1886 this is so wrong! Should not even return anything. */
if (error == ZC_ERR_ALLOC || error == 0) {
return KNOT_EBADARG;
}
@@ -262,9 +261,11 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
const knot_node_t *next_node = NULL;
uint i = 0;
-
- assert(tmp_rdata);
-
+
+ if (tmp_rdata == NULL) {
+ return KNOT_EOK;
+ }
+
const knot_dname_t *next_dname =
knot_rdata_cname_name(tmp_rdata);
/* (cname_name == dname_target) */
@@ -330,6 +331,7 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
} 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;
}
@@ -367,7 +369,7 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
next_dname);
}
-/*!< \todo this might replace some of the code above. */
+/*!< \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. */
@@ -390,7 +392,6 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
knot_dname_t *chopped_next =
knot_dname_left_chop(next_dname);
if (chopped_next == NULL) {
- /*!< \todo check. */
return KNOT_ERROR;
}
while (next_node == NULL && chopped_next != NULL) {
@@ -422,7 +423,7 @@ static int check_cname_cycles_in_zone(knot_zone_contents_t *zone,
if (next_node != NULL) {
next_rrset = knot_node_rrset(next_node,
rrset->type);
- if (next_rrset != NULL) {
+ if (next_rrset != NULL && next_rrset->rdata != NULL) {
next_dname =
knot_rdata_cname_name(next_rrset->rdata);
} else {
@@ -477,7 +478,6 @@ uint16_t type_covered_from_rdata(const knot_rdata_t *rdata)
static int check_dnskey_rdata(const knot_rdata_t *rdata)
{
/* check that Zone key bit it set - position 7 in net order */
- /*! \todo FIXME: endian? I swear I've fixed this already, it was 7 i guesss*/
uint16_t mask = 1 << 8; //0b0000000100000000;
uint16_t flags =
@@ -570,7 +570,6 @@ static int dnskey_to_wire(const knot_rdata_t *rdata, uint8_t **wire,
/* copy the wire octet by octet */
- /* TODO check if we really have that many items */
if (rdata->count < 4) {
free(*wire);
*wire = NULL;
@@ -754,28 +753,34 @@ static int check_rrsig_in_rrset(const knot_rrset_t *rrset,
return ZC_ERR_RRSIG_TTL;
}
- /* Check whether all rrsets have their rrsigs */
const knot_rdata_t *tmp_rdata = knot_rrset_rdata(rrset);
const knot_rdata_t *tmp_rrsig_rdata = knot_rrset_rdata(rrsigs);
-
- assert(tmp_rdata);
- assert(tmp_rrsig_rdata);
+
+ assert(tmp_rrsig_rdata != NULL);
+ if (tmp_rdata == NULL) {
+ /* Only RRSIG, valid, but we can't check anything. */
+ return KNOT_EOK;
+ }
+
int ret = 0;
- char all_signed = tmp_rdata && tmp_rrsig_rdata;
do {
if ((ret = check_rrsig_rdata(tmp_rrsig_rdata,
rrset,
dnskey_rrset)) != 0) {
+ /*!< \todo This should go to handler. */
return ret;
}
-
- all_signed = tmp_rdata && tmp_rrsig_rdata;
- } while (((tmp_rdata = knot_rrset_rdata_next(rrset, tmp_rdata))
- != NULL) &&
- ((tmp_rrsig_rdata =
- knot_rrset_rdata_next(rrsigs, tmp_rrsig_rdata))
- != NULL));
-
+ 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;
if (!all_signed) {
return ZC_ERR_RRSIG_NOT_ALL;
}
@@ -992,10 +997,6 @@ static int check_nsec3_node_in_zone(knot_zone_contents_t *zone, knot_node_t *nod
/* Directly discard. */
knot_dname_free(&next_dname);
- /*!< \todo These comments are not accurate anymore. */
- /* This is probably not sufficient, but again, it is covered in
- * zone load time */
-
uint count;
uint16_t *array = NULL;
if (rdata_nsec_to_type_array(
@@ -1104,8 +1105,9 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
}
}
- if (knot_rrset_rdata(cname_rrset)->next !=
- knot_rrset_rdata(cname_rrset)) {
+ if (knot_rrset_rdata(cname_rrset) &&
+ knot_rrset_rdata(cname_rrset)->next !=
+ knot_rrset_rdata(cname_rrset)) {
*fatal_error = 1;
err_handler_handle_error(handler, node,
ZC_ERR_CNAME_MULTIPLE);
@@ -1169,7 +1171,7 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
return KNOT_EOK;
}
- /*!< \todo Good Lord, move this to ist own function. */
+ /*!< \todo #1887 Good Lord, move this to ist own function. */
/* check for glue records at zone cuts and in apex. */
if (knot_node_is_deleg_point(node) || knot_zone_contents_apex(zone) ==
@@ -1184,10 +1186,12 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
//FIXME this should be an error as well ! (i guess)
knot_dname_t *ns_dname =
+ knot_dname_deep_copy(
knot_rdata_get_item(knot_rrset_rdata
- (ns_rrset), 0)->dname;
-
- assert(ns_dname);
+ (ns_rrset), 0)->dname);
+ if (ns_dname == NULL) {
+ return KNOT_ENOMEM;
+ }
const knot_node_t *glue_node =
knot_zone_contents_find_node(zone, ns_dname);
@@ -1199,6 +1203,7 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
knot_dname_t *wildcard =
knot_dname_new_from_str("*", 1, NULL);
if (wildcard == NULL) {
+ knot_dname_free(&ns_dname);
return KNOT_ENOMEM;
}
@@ -1206,6 +1211,7 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
if (knot_dname_cat(wildcard,
ns_dname) == NULL) {
+ knot_dname_free(&ns_dname);
knot_dname_free(&wildcard);
return KNOT_ENOMEM;
}
@@ -1236,6 +1242,7 @@ static int semantic_checks_plain(knot_zone_contents_t *zone,
}
}
}
+ knot_dname_free(&ns_dname);
}
return KNOT_EOK;
}
@@ -1512,7 +1519,7 @@ void log_cyclic_errors_in_zone(err_handler_t *handler,
free(next_dname_decoded);
- /*! \todo Free result and dname! */
+ /*! \todo #1887 Free result and dname! */
if (knot_dname_cat(next_dname,
knot_node_owner(knot_zone_contents_apex(zone))) ==
NULL) {
diff --git a/src/knot/zone/semantic-check.h b/src/knot/zone/semantic-check.h
index 17b774f..2f6dad7 100644..100755
--- a/src/knot/zone/semantic-check.h
+++ b/src/knot/zone/semantic-check.h
@@ -20,7 +20,7 @@
*
* \brief DNS zone semantic checks.
*
- * \addtogroup dnslib
+ * \addtogroup zoneparser
* @{
*/
@@ -200,3 +200,5 @@ int zone_do_sem_checks(knot_zone_contents_t *zone, char do_checks,
knot_node_t **last_node);
#endif // _KNOT_SEMANTIC_CHECK_H_
+
+/*! @} */
diff --git a/src/knot/zone/zone-dump-text.c b/src/knot/zone/zone-dump-text.c
index bc606d3..8f428a5 100644..100755
--- a/src/knot/zone/zone-dump-text.c
+++ b/src/knot/zone/zone-dump-text.c
@@ -305,12 +305,12 @@ static inline uint16_t rdata_item_size(knot_rdata_item_t item)
return item.raw_data[0];
}
-char *rdata_dname_to_string(knot_rdata_item_t item)
+static char *rdata_dname_to_string(knot_rdata_item_t item)
{
return knot_dname_to_str(item.dname);
}
-char *rdata_binary_dname_to_string(knot_rdata_item_t item)
+static char *rdata_binary_dname_to_string(knot_rdata_item_t item)
{
if (item.raw_data == NULL) {
return NULL;
@@ -334,7 +334,7 @@ char *rdata_binary_dname_to_string(knot_rdata_item_t item)
return str;
}
-char *rdata_dns_name_to_string(knot_rdata_item_t item)
+static char *rdata_dns_name_to_string(knot_rdata_item_t item)
{
return knot_dname_to_str(item.dname);
}
@@ -342,8 +342,7 @@ char *rdata_dns_name_to_string(knot_rdata_item_t item)
static char *rdata_txt_data_to_string(const uint8_t *data)
{
uint8_t length = data[0];
- size_t i;
-
+ size_t i = 0;
if (length == 0) {
return NULL;
}
@@ -360,38 +359,41 @@ static char *rdata_txt_data_to_string(const uint8_t *data)
}
memset(ret, 0, current_length);
- strncat(ret, "\"", 3);
+ strncat(ret, "\"", 2);
for (i = 1; i <= length; i++) {
char ch = (char) data[i];
if (isprint((int)ch)) {
if (ch == '"' || ch == '\\') {
- strncat(ret, "\"", 3);
+ strncat(ret, "\"", 2);
}
- /* for the love of god, how to this better,
- but w/o obscure self-made functions */
char tmp_str[2];
tmp_str[0] = ch;
- tmp_str[1] = 0;
+ tmp_str[1] = '\0';
strncat(ret, tmp_str, 2);
} else {
- strncat(ret, "\\", 3);
+ strncat(ret, "\\", 2);
char tmp_str[2];
tmp_str[0] = ch - '0';
- tmp_str[1] = 0;
-
+ tmp_str[1] = '\0';
strncat(ret, tmp_str, 2);
}
}
- strncat(ret, "\"", 3);
+ strncat(ret, "\"", 2);
return ret;
}
-char *rdata_text_to_string(knot_rdata_item_t item)
+static char *rdata_text_to_string(knot_rdata_item_t item)
{
uint16_t size = item.raw_data[0];
- char *ret = malloc(sizeof(char) * size * 2 + 1) ;
+ /*
+ * Times two because they can all be one char long
+ * and then it would be as much chars as spaces (and one final space).
+ */
+ size_t txt_size = size * 2 + 1;
+ /* + 1 ... space for (hypothetical) last \0. */
+ char *ret = malloc(txt_size + 1);
if (ret == NULL) {
ERR_ALLOC_FAILED;
return NULL;
@@ -399,6 +401,7 @@ char *rdata_text_to_string(knot_rdata_item_t item)
memset(ret, 0, sizeof(char) * size);
const uint8_t *data = (uint8_t *)(item.raw_data + 1);
size_t read_count = 0;
+ size_t tmp_str_current_length = 0; // Will be used with strncat.
while (read_count < size) {
assert(read_count <= size);
char *txt = rdata_txt_data_to_string(data + read_count);
@@ -406,20 +409,30 @@ char *rdata_text_to_string(knot_rdata_item_t item)
free(ret);
return NULL;
}
+ /*
+ * We can trust this strlen, as
+ * it is created in internal function.
+ */
read_count += strlen(txt) - 1;
/* Create delimiter. */
char del[2];
del[0] = ' ';
del[1] = '\0';
- strncat(ret, txt, strlen(txt));
- strncat(ret, del, 2);
+
+ /* We can only write to the remainder of string. */
+ strncat(ret, txt, txt_size - tmp_str_current_length);
+ /* Increase length of tmp string. */
+ tmp_str_current_length += strlen(txt);
+ strncat(ret, del, txt_size - tmp_str_current_length);
+ /* Increase length of tmp string by 1 ... space. */
+ tmp_str_current_length += + 1;
free(txt);
}
return ret;
}
-char *rdata_byte_to_string(knot_rdata_item_t item)
+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));
@@ -428,7 +441,7 @@ char *rdata_byte_to_string(knot_rdata_item_t item)
return ret;
}
-char *rdata_short_to_string(knot_rdata_item_t item)
+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);
@@ -438,7 +451,7 @@ char *rdata_short_to_string(knot_rdata_item_t item)
return ret;
}
-char *rdata_long_to_string(knot_rdata_item_t item)
+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);
@@ -447,7 +460,7 @@ char *rdata_long_to_string(knot_rdata_item_t item)
return ret;
}
-char *rdata_a_to_string(knot_rdata_item_t item)
+static char *rdata_a_to_string(knot_rdata_item_t item)
{
/* 200 seems like a little too much */
char *ret = malloc(sizeof(char) * 200);
@@ -458,7 +471,7 @@ char *rdata_a_to_string(knot_rdata_item_t item)
}
}
-char *rdata_aaaa_to_string(knot_rdata_item_t item)
+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)) {
@@ -468,7 +481,7 @@ char *rdata_aaaa_to_string(knot_rdata_item_t item)
}
}
-char *rdata_rrtype_to_string(knot_rdata_item_t item)
+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);
@@ -477,7 +490,7 @@ char *rdata_rrtype_to_string(knot_rdata_item_t item)
return ret;
}
-char *rdata_algorithm_to_string(knot_rdata_item_t item)
+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);
@@ -492,7 +505,7 @@ char *rdata_algorithm_to_string(knot_rdata_item_t item)
return ret;
}
-char *rdata_certificate_type_to_string(knot_rdata_item_t item)
+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);
@@ -507,7 +520,7 @@ char *rdata_certificate_type_to_string(knot_rdata_item_t item)
return ret;
}
-char *rdata_period_to_string(knot_rdata_item_t item)
+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));
@@ -516,7 +529,7 @@ char *rdata_period_to_string(knot_rdata_item_t item)
return ret;
}
-char *rdata_time_to_string(knot_rdata_item_t item)
+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;
@@ -532,7 +545,7 @@ char *rdata_time_to_string(knot_rdata_item_t item)
}
}
-char *rdata_base32_to_string(knot_rdata_item_t item)
+static char *rdata_base32_to_string(knot_rdata_item_t item)
{
int length;
size_t size = rdata_item_size(item);
@@ -555,7 +568,8 @@ char *rdata_base32_to_string(knot_rdata_item_t item)
}
}
-char *rdata_base64_to_string(knot_rdata_item_t item)
+/*!< \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);
@@ -570,7 +584,7 @@ char *rdata_base64_to_string(knot_rdata_item_t item)
}
}
-char *hex_to_string(const uint8_t *data, size_t size)
+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',
@@ -593,7 +607,7 @@ char *hex_to_string(const uint8_t *data, size_t size)
char *rdata_hex_to_string(knot_rdata_item_t item)
{
- return hex_to_string(rdata_item_data(item), rdata_item_size(item));
+ return knot_hex_to_string(rdata_item_data(item), rdata_item_size(item));
}
char *rdata_hexlen_to_string(knot_rdata_item_t item)
@@ -605,8 +619,8 @@ char *rdata_hexlen_to_string(knot_rdata_item_t item)
ret[1] = '\0';
return ret;
} else {
- return hex_to_string(rdata_item_data(item) + 1,
- rdata_item_size(item) - 1);
+ return knot_hex_to_string(rdata_item_data(item) + 1,
+ rdata_item_size(item) - 1);
}
}
@@ -622,8 +636,8 @@ char *rdata_nsap_to_string(knot_rdata_item_t item)
/* String is already terminated. */
memcpy(ret, "0x", strlen("0x"));
- char *converted = hex_to_string(rdata_item_data(item),
- rdata_item_size(item));
+ char *converted = knot_hex_to_string(rdata_item_data(item),
+ rdata_item_size(item));
if (converted == NULL) {
return NULL;
}
@@ -707,9 +721,7 @@ char *rdata_services_to_string(knot_rdata_item_t item)
if (proto) {
int i;
- /*!< \todo #1863 see below, but we can trust getprotobynumber... */
strncpy(ret, proto->p_name, strlen(proto->p_name));
-
strncat(ret, " ", 2);
for (i = 0; i < bitmap_size * 8; ++i) {
@@ -718,12 +730,6 @@ char *rdata_services_to_string(knot_rdata_item_t item)
getservbyport((int)htons(i),
proto->p_name);
if (service) {
- /*!< \todo #1863
- * using strncat with strlen
- * does not make a whole lot of sense.
- * At least it will crash wil
- * Use max length of service name!
- */
strncat(ret, service->s_name,
strlen(service->s_name));
strncat(ret, " ", 2);
@@ -738,37 +744,6 @@ char *rdata_services_to_string(knot_rdata_item_t item)
}
return ret;
-
- /*
- int result = 0;
- uint8_t protocol_number = buffer_read_u8(&packet);
- ssize_t bitmap_size = buffer_remaining(&packet);
- uint8_t *bitmap = buffer_current(&packet);
- struct protoent *proto = getprotobynumber(protocol_number);
-
-
- if (proto) {
- int i;
-
- strcpy(ret, proto->p_name);
-
- 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) {
- buffer_printf(output, " %s",
- service->s_name);
- } else {
- buffer_printf(output, " %d", i);
- }
- }
- }
- result = 1;
- }
- return ret;
- */
}
char *rdata_ipsecgateway_to_string(knot_rdata_item_t item,
@@ -830,17 +805,15 @@ char *rdata_nxt_to_string(knot_rdata_item_t item)
char *rdata_nsec_to_string(knot_rdata_item_t item)
{
- /* CLEANUP */
-// int insert_space = 0;
-
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];
@@ -870,33 +843,6 @@ char *rdata_nsec_to_string(knot_rdata_item_t item)
}
return ret;
-
- /* CLEANUP */
-/* while (buffer_available(&packet, 2)) {
- uint8_t window = buffer_read_u8(&packet);
- uint8_t bitmap_size = buffer_read_u8(&packet);
- uint8_t *bitmap = buffer_current(&packet);
- int i;
-
- if (!buffer_available(&packet, bitmap_size)) {
- buffer_set_position(output, saved_position);
- return 0;
- }
-
- for (i = 0; i < bitmap_size * 8; ++i) {
- if (get_bit(bitmap, i)) {
- buffer_printf(output,
- "%s%s",
- insert_space ? " " : "",
- rrtype_to_string(
- window * 256 + i));
- insert_space = 1;
- }
- }
- buffer_skip(&packet, bitmap_size);
- }
-
- return 1; */
}
char *rdata_unknown_to_string(knot_rdata_item_t item)
@@ -912,7 +858,7 @@ char *rdata_unknown_to_string(knot_rdata_item_t item)
snprintf(ret + strlen("\\# "),
strlen("\\# ") + U16_MAX_STR_LEN + 1, "%lu ",
(unsigned long) size);
- char *converted = hex_to_string(rdata_item_data(item), size);
+ char *converted = knot_hex_to_string(rdata_item_data(item), size);
strncat(ret, converted, size * 2 + 1);
free(converted);
return ret;
@@ -959,14 +905,13 @@ char *rdata_item_to_string(knot_rdata_zoneformat_t type,
return item_to_string_table[type](item);
}
-/* CLEANUP */
-/*void knot_zone_tree_apply_inorder(knot_zone_t *zone,
- void (*function)(knot_node_t *node, void *data),
- void *data); */
-
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_EBADARG;
+ }
+
knot_rrtype_descriptor_t *desc =
knot_rrtype_descriptor_by_type(type);
char *item_str = NULL;
@@ -1040,19 +985,23 @@ int rrsig_set_dump_text(knot_rrset_t *rrsig, FILE *f)
int rrset_dump_text(const knot_rrset_t *rrset, FILE *f)
{
- dump_rrset_header(rrset, f);
- knot_rdata_t *tmp = rrset->rdata;
+ if (rrset->rdata != NULL) { // No sense in dumping empty RR
+ dump_rrset_header(rrset, f);
- while (tmp->next != rrset->rdata) {
- int ret = rdata_dump_text(tmp, rrset->type, f, rrset);
- if (ret != KNOTD_EOK) {
- return ret;
+ knot_rdata_t *tmp = rrset->rdata;
+
+ while (tmp->next != rrset->rdata) {
+ int ret = rdata_dump_text(tmp, rrset->type, f, rrset);
+ if (ret != KNOTD_EOK) {
+ return ret;
+ }
+ dump_rrset_header(rrset, f);
+ tmp = tmp->next;
}
- dump_rrset_header(rrset, f);
- tmp = tmp->next;
+
+ rdata_dump_text(tmp, rrset->type, f, rrset);
}
- 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);
diff --git a/src/knot/zone/zone-dump-text.h b/src/knot/zone/zone-dump-text.h
index 9f9c8dd..c55f712 100644..100755
--- a/src/knot/zone/zone-dump-text.h
+++ b/src/knot/zone/zone-dump-text.h
@@ -20,7 +20,7 @@
*
* \brief Functions for dumping zone to text file.
*
- * \addtogroup dnslib
+ * \addtogroup zone-load-dump
* @{
*/
diff --git a/src/knot/zone/zone-dump.c b/src/knot/zone/zone-dump.c
index aaf0165..708cd2b 100644..100755
--- a/src/knot/zone/zone-dump.c
+++ b/src/knot/zone/zone-dump.c
@@ -360,6 +360,11 @@ static int knot_rdata_dump_binary(knot_rdata_t *rdata,
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. */
@@ -392,6 +397,8 @@ static int knot_rdata_dump_binary(knot_rdata_t *rdata,
/*! \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,
@@ -401,6 +408,8 @@ static int knot_rdata_dump_binary(knot_rdata_t *rdata,
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,
@@ -423,6 +432,9 @@ static int knot_rdata_dump_binary(knot_rdata_t *rdata,
}
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,
@@ -567,7 +579,11 @@ static int knot_rrset_dump_binary(const knot_rrset_t *rrset, int fd,
"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. */
@@ -602,10 +618,14 @@ static int knot_rrset_dump_binary(const knot_rrset_t *rrset, int fd,
/* Calculate rrset rdata count. */
knot_rdata_t *tmp_rdata = rrset->rdata;
- while(tmp_rdata->next != rrset->rdata) {
+ while(tmp_rdata && (tmp_rdata->next != rrset->rdata)) {
tmp_rdata = tmp_rdata->next;
rdata_count++;
}
+
+ if (rrset->rdata == NULL) {
+ rdata_count = 0;
+ }
if (!write_wrapper(&rdata_count, sizeof(rdata_count), 1, fd,
stream, max_size, written_bytes, crc)) {
@@ -619,29 +639,35 @@ static int knot_rrset_dump_binary(const knot_rrset_t *rrset, int fd,
}
dbg_zdump_verb("zdump: rrset_dump_binary: Static data dumped.\n");
+
+ if (rdata_count != 0) {
+
+ tmp_rdata = rrset->rdata;
- tmp_rdata = rrset->rdata;
-
- while (tmp_rdata->next != rrset->rdata) {
+ 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;
+ }
+
int ret = knot_rdata_dump_binary(tmp_rdata, rrset->type,
fd, use_ids,
- stream, max_size,
- written_bytes, crc);
+ 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;
- }
-
- 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;
}
dbg_zdump_verb("zdump: rrset_dump_binary: Rdata dumped.\n");
@@ -894,6 +920,7 @@ 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_EBADARG;
diff --git a/src/knot/zone/zone-dump.h b/src/knot/zone/zone-dump.h
index fbebae9..02d0298 100644..100755
--- a/src/knot/zone/zone-dump.h
+++ b/src/knot/zone/zone-dump.h
@@ -20,7 +20,7 @@
*
* \brief Functions for dumping zone to binary file.
*
- * \addtogroup dnslib
+ * \addtogroup zone-load-dump
* @{
*/
@@ -38,7 +38,7 @@ enum {
};
/*! \brief Magic identifier: { "knot", maj_ver, min_ver, revision } */
-#define MAGIC_BYTES {'k', 'n', 'o', 't', '1', '0', '4'}
+#define MAGIC_BYTES {'k', 'n', 'o', 't', '1', '1', '0'}
/*!
* \brief Dumps given zone to binary file.
diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c
index 3a7134e..fedd38b 100644..100755
--- a/src/knot/zone/zone-load.c
+++ b/src/knot/zone/zone-load.c
@@ -62,39 +62,57 @@ static int timet_cmp(time_t x, time_t y)
* \retval 0 if failed.
*/
static inline int fread_safe_from_file(void *dst,
- size_t size, size_t n, FILE *fp)
+ size_t size, size_t n, void *source)
{
+ if (dst == NULL || source == NULL) {
+ dbg_zload("zload: fread_safe_from_file: NULL arguments.\n");
+ return 0;
+ }
+ FILE *fp = (FILE *)source;
int rc = fread(dst, size, n, fp);
if (rc != n) {
- fprintf(stderr, "fread: invalid read %d (expected %zu)\n", rc,
- n);
+ dbg_zload("zload: fread_safe_from_file: "
+ "invalid read %d (exp. %zu)\n",
+ rc, n);
}
return rc == n;
}
-static uint8_t *knot_zload_stream = NULL;
-static size_t knot_zload_stream_remaining = 0;
-static size_t knot_zload_stream_size = 0;
+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, FILE *fp)
+ size_t size, size_t n, void *source)
{
- if (knot_zload_stream_remaining < (size * n)) {
+ if (dst == NULL || source == NULL) {
+ dbg_zload("zload: read_from_stream: NULL arguments.\n");
+ return 0;
+ }
+
+ /* Extract information from source data. */
+ load_stream_t *data = (load_stream_t *)source;
+
+
+ if (data->stream_remaining < (size * n)) {
+ dbg_zload("zload: read_from_stream: Buffer depleted.\n");
return 0;
}
memcpy(dst,
- knot_zload_stream +
- (knot_zload_stream_size - knot_zload_stream_remaining),
+ data->stream +
+ (data->stream_size - data->stream_remaining),
size * n);
- knot_zload_stream_remaining -= size * n;
+ data->stream_remaining -= size * n;
return 1;
}
-static int (*fread_wrapper)(void *dst, size_t size, size_t n, FILE *fp);
-
/*! \note Contents of dump file:
* MAGIC(knotxx) NUMBER_OF_NORMAL_NODES NUMBER_OF_NSEC3_NODES
* [normal_nodes] [nsec3_nodes]
@@ -136,23 +154,31 @@ static void load_rdata_purge(knot_rdata_t *rdata,
knot_dname_retain(items[i].dname);
break;
default:
+ /*!< \todo This would leak wire data! */
break;
}
}
/* Copy items to rdata and free the temporary rdata. */
knot_rdata_set_items(rdata, items, count);
- knot_rdata_deep_free(&rdata, type, 1);
+ knot_rdata_deep_free(&rdata, type, 0);
free(items);
}
-static knot_dname_t *read_dname_with_id(FILE *f)
+static knot_dname_t *read_dname_with_id(FILE *f, int use_ids)
{
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;
@@ -173,9 +199,12 @@ static knot_dname_t *read_dname_with_id(FILE *f)
return NULL;
}
ret->size = dname_size;
- dbg_zload("loaded: dname length: %u\n", ret->size);
-
- assert(ret->size <= DNAME_MAX_WIRE_LENGTH);
+ 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);
@@ -238,6 +267,18 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
knot_dname_t **id_array,
int use_ids)
{
+ 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;
+ } 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");
@@ -262,12 +303,14 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
malloc(sizeof(knot_rdata_item_t) * rdata_count);
if (items == NULL) {
ERR_ALLOC_FAILED;
- free(items);
+ 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;
}
@@ -285,6 +328,7 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
/*!< \todo #1686
* Refactor these variables, some might be too big.
*/
+
uint32_t dname_id = 0;
uint8_t has_wildcard = 0;
@@ -304,8 +348,13 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
knot_dname_retain(id_array[dname_id]);
items[i].dname = id_array[dname_id];
} else {
- items[i].dname = read_dname_with_id(f);
+ 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)) {
@@ -322,6 +371,27 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
"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),
@@ -332,16 +402,14 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
"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;
- } else if (use_ids && !in_the_zone) {
- /* destroy the node */
- if (id_array[dname_id]->node != NULL) {
- knot_node_free(&id_array[dname_id]->
- node, 0);
- }
- /* Also sets node to NULL! */
}
+
assert(items[i].dname);
} else {
if (!fread_wrapper(&raw_data_length,
@@ -379,10 +447,12 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
}
/* Each item has refcount already incremented for saving in rdata. */
- if (knot_rdata_set_items(rdata, items, rdata_count) != 0) {
- fprintf(stderr, "zload: read_rdata: Could not set items "
- "when loading rdata.\n");
- knot_rdata_deep_free(&rdata, type, 0);
+ 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: %\n.",
+ knot_strerror(ret));
+ load_rdata_purge(rdata, items, desc->length, desc, type);
return NULL;
}
@@ -403,7 +473,7 @@ static knot_rdata_t *knot_load_rdata(uint16_t type, FILE *f,
*
* \return pointer to created and read RRSIG on success, NULL otherwise.
*/
-static knot_rrset_t *knot_load_rrsig(FILE *f, knot_dname_t **id_array,
+static knot_rrset_t *knot_load_rrsig(void *f, knot_dname_t **id_array,
int use_ids)
{
if (f == NULL || id_array == NULL) {
@@ -411,6 +481,13 @@ static knot_rrset_t *knot_load_rrsig(FILE *f, knot_dname_t **id_array,
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 *rrsig = NULL;
uint16_t rrset_type = 0;
@@ -487,9 +564,21 @@ static knot_rrset_t *knot_load_rrsig(FILE *f, knot_dname_t **id_array,
*
* \return pointer to created and read RRSet on success, NULL otherwise.
*/
-static knot_rrset_t *knot_load_rrset(FILE *f, knot_dname_t **id_array,
+static knot_rrset_t *knot_load_rrset(void *f, knot_dname_t **id_array,
int use_ids)
{
+ 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;
@@ -504,7 +593,7 @@ static knot_rrset_t *knot_load_rrset(FILE *f, knot_dname_t **id_array,
if (!use_ids) {
dbg_zload_detail("zload: load_rrset: "
"Loading owner of new RRSet from wire.\n");
- owner = read_dname_with_id(f);
+ owner = read_dname_with_id(f, use_ids);
if (owner == NULL) {
dbg_zload("zload: load_rrset: Cannot load owner.\n");
return NULL;
@@ -587,6 +676,7 @@ dbg_zload_exec_detail(
return NULL;
}
} else {
+ dbg_zload("zload: load_rrset: Cannot load rdata.\n");
knot_rrset_deep_free(&rrset, 0, 1, 1);
return NULL;
}
@@ -628,6 +718,10 @@ static knot_node_t *knot_load_node(FILE *f, knot_dname_t **id_array)
dbg_zload("zload: load_node: Wrong parameters.\n");
return NULL;
}
+
+ 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;
@@ -661,6 +755,10 @@ static knot_node_t *knot_load_node(FILE *f, knot_dname_t **id_array)
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(
@@ -701,7 +799,7 @@ dbg_zload_exec_detail(
for (int i = 0; i < rrset_count; i++) {
if ((tmp_rrset = knot_load_rrset(f, id_array, 1)) == NULL) {
- knot_node_free(&node, 0);
+ knot_node_free(&node);
/*!< \todo #1686
* Refactor freeing, might not be enough.
*/
@@ -770,6 +868,9 @@ static void find_and_set_wildcard_child(knot_zone_contents_t *zone,
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;
@@ -791,6 +892,9 @@ static unsigned long calculate_crc(FILE *f)
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 */
@@ -836,11 +940,12 @@ int knot_zload_open(zloader_t **dst, const char *filename)
dbg_zload("zload: open: Bad arguments.\n");
return KNOT_EBADARG;
}
+
+ int (*fread_wrapper)(void *dst, size_t size, size_t n, void *source);
+ fread_wrapper = fread_safe_from_file;
*dst = 0;
- fread_wrapper = fread_safe_from_file;
-
/* Open file for binary read. */
FILE *f = fopen(filename, "rb");
if (unlikely(!f)) {
@@ -856,6 +961,15 @@ int knot_zload_open(zloader_t **dst, const char *filename)
return KNOT_EFEWDATA; // No such file or directory (POSIX.1)
}
+
+ /* 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);
@@ -983,8 +1097,14 @@ int knot_zload_open(zloader_t **dst, const char *filename)
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++) {
- knot_dname_release(id_array[i]);
+ if (id_array[i] != NULL) {
+ knot_dname_release(id_array[i]);
+ }
}
free(id_array);
@@ -1044,7 +1164,7 @@ static knot_dname_t **create_dname_array(FILE *f, uint max_id)
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);
+ 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" );
@@ -1090,8 +1210,6 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
return NULL;
}
- fread_wrapper = fread_safe_from_file;
-
FILE *f = loader->fp;
knot_node_t *tmp_node;
@@ -1099,7 +1217,10 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
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;
@@ -1147,7 +1268,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
knot_node_t *apex = knot_load_node(f, id_array);
if (!apex) {
- fprintf(stderr, "zone: Could not load apex node (in %s)\n",
+ 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);
@@ -1163,7 +1284,7 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
node_count + nsec3_node_count + 1);
dbg_zload("zload: load: Failed to create new "
"zone from apex!\n");
- knot_node_free(&apex, 0);
+ knot_node_free(&apex);
free(dname_table);
return NULL;
}
@@ -1178,19 +1299,26 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
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) {
- if (knot_zone_contents_add_node(contents, tmp_node,
- 0, 0, 0) != 0) {
+ 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.\n");
+ "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);
@@ -1229,12 +1357,12 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
assert(nsec3_first != NULL);
- if (knot_zone_contents_add_nsec3_node(contents, nsec3_first,
- 0, 0, 0)
- != 0) {
+ 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.\n");
+ "exiting: %s.\n", knot_strerror(ret));
knot_zone_deep_free(&zone, 0);
cleanup_id_array(id_array, node_count + 1,
nsec3_node_count + 1);
@@ -1249,10 +1377,11 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
tmp_node = knot_load_node(f, id_array);
if (tmp_node != NULL) {
- if (knot_zone_contents_add_nsec3_node(contents,
- tmp_node, 0, 0, 0) != 0) {
+ if ((ret = knot_zone_contents_add_nsec3_node(contents,
+ tmp_node, 0, 0, 0)) != 0) {
dbg_zload("zload: load: Cannot add "
- "NSEC3 node.\n");
+ "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);
@@ -1265,6 +1394,10 @@ knot_zone_t *knot_zload_load(zloader_t *loader)
} 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;
}
}
@@ -1332,27 +1465,20 @@ int knot_zload_rrset_deserialize(knot_rrset_t **rrset,
return KNOT_EBADARG;
}
- fread_wrapper = read_from_stream;
+ load_stream_t data;
+ data.stream = stream;
+ data.stream_remaining = *size;
+ data.stream_size = *size;
- knot_zload_stream = stream;
- knot_zload_stream_remaining = knot_zload_stream_size = *size;
-
- knot_rrset_t *ret = knot_load_rrset(NULL, NULL, 0);
+ knot_rrset_t *ret = knot_load_rrset(&data, NULL, 0);
if (ret == NULL) {
dbg_zload("zload: rrset_deserialize: Cannot load RRSet.\n");
- knot_zload_stream = NULL;
- knot_zload_stream_remaining = 0;
- knot_zload_stream_size = 0;
return KNOT_EMALF;
}
- *size = knot_zload_stream_remaining;
+ *size = data.stream_remaining;
*rrset = ret;
- knot_zload_stream = NULL;
- knot_zload_stream_remaining = 0;
- knot_zload_stream_size = 0;
-
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 2fe318f..837d5f2 100644..100755
--- a/src/knot/zone/zone-load.h
+++ b/src/knot/zone/zone-load.h
@@ -20,7 +20,7 @@
*
* \brief Loader of previously parsed zone
*
- * \addtogroup dnslib
+ * \addtogroup zone-load-dump
* @{
*/
diff --git a/src/knotc.8 b/src/knotc.8
index b61bfd3..9cd3f08 100644..100755
--- a/src/knotc.8
+++ b/src/knotc.8
@@ -1,6 +1,6 @@
-.TH knotc "8" "November 2011" "CZ.NIC Labs" "Knot DNS, version 0.8"
+.TH knotc "8" "August 2012" "CZ.NIC Labs" "Knot DNS, version 1.1"
.SH NAME
-.B knot
+.B knotc
\- Knot DNS control utility
.SH SYNOPSIS
.B knotc
@@ -28,27 +28,39 @@ 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:"
.TP
start
-Start knot server zone (no\-op if running).
+Start knot server daemon (no\-op if running).
.TP
stop
-Stop knot server (no\-op if not running).
+Stop knot server daemon (no\-op if not running).
.TP
restart
-Stops and then starts knot server.
+Stops and then starts knot server daemon.
.TP
reload
Reload knot configuration and compiled zones.
.TP
running
-check if server is running.
+Check if server is running.
.TP
compile
Compile zone file.
+.TP
+refresh
+Refresh all slave zones.
+.TP
+checkconf
+Check server configuration.
+.TP
+checkzone
+Check zones before compiling (accepts specific zones, f.e. 'knotc checkzone example1.com example2.com').
.SH "SEE ALSO"
The full documentation for
.B Knot
diff --git a/src/knotd.8 b/src/knotd.8
index df4b264..cdc450a 100644..100755
--- a/src/knotd.8
+++ b/src/knotd.8
@@ -1,4 +1,4 @@
-.TH "knotd" "8" "November 2011" "CZ.NIC Labs" "Knot DNS, version 0.8"
+.TH "knotd" "8" "August 2012" "CZ.NIC Labs" "Knot DNS, version 1.1"
.SH NAME
.B knotd
\- Knot DNS daemon
diff --git a/src/libknot/common.h b/src/libknot/common.h
index 9b2d8ae..9b2d8ae 100644..100755
--- a/src/libknot/common.h
+++ b/src/libknot/common.h
diff --git a/src/libknot/consts.h b/src/libknot/consts.h
index 4249763..4249763 100644..100755
--- a/src/libknot/consts.h
+++ b/src/libknot/consts.h
diff --git a/src/libknot/dname.c b/src/libknot/dname.c
index 80de030..7d59b6b 100644..100755
--- a/src/libknot/dname.c
+++ b/src/libknot/dname.c
@@ -163,7 +163,7 @@ static int knot_dname_str_to_wire(const char *name, uint size,
return -1;
}
- dbg_dname("Allocated space for wire format of dname: %p\n", wire);
+ dbg_dname_verb("Allocated space for wire format of dname: %p\n", wire);
if (root) {
*wire = '\0';
@@ -181,18 +181,18 @@ static int knot_dname_str_to_wire(const char *name, uint size,
assert(w - wire - 1 == ch - (const uint8_t *)name);
if (*ch == '.') {
- dbg_dname("Position %zd (%p): "
- "label length: %u\n",
- label_start - wire,
- label_start, label_length);
+ dbg_dname_detail("Position %zd (%p): "
+ "label length: %u\n",
+ label_start - wire,
+ label_start, label_length);
*label_start = label_length;
labels[label_count++] = label_start - wire;
label_start = w;
label_length = 0;
} else {
assert(w - wire < wire_size);
- dbg_dname("Position %zd (%p): character: %c\n",
- w - wire, w, *ch);
+ dbg_dname_detail("Position %zd (%p): character: %c\n",
+ w - wire, w, *ch);
*w = *ch;
++label_length;
}
@@ -205,14 +205,13 @@ static int knot_dname_str_to_wire(const char *name, uint size,
--ch;
if (*ch == '.') { // put 0 for root label if the name ended with .
--w;
- dbg_dname("Position %zd (%p): character: (null)\n",
- w - wire, w);
+ dbg_dname_detail("Position %zd (%p): character: (null)\n",
+ w - wire, w);
*w = 0;
} else { // otherwise we did not save the last label length
- dbg_dname("Position %zd (%p): "
- "label length: %u\n",
- label_start - wire,
- label_start, label_length);
+ dbg_dname_detail("Position %zd (%p): label length: %u\n",
+ label_start - wire,
+ label_start, label_length);
*label_start = label_length;
labels[label_count++] = label_start - wire;
}
@@ -277,7 +276,8 @@ 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", pos - name, *pos, size);
+ dbg_dname("Position: %d, character: %d, expected size: %d\n",
+ pos - name, *pos, size);
return -1;
}
@@ -298,12 +298,11 @@ static int knot_dname_find_labels(knot_dname_t *dname, int alloc)
static int knot_dname_cmp(const knot_dname_t *d1, const knot_dname_t *d2,
int cs)
{
-dbg_dname_exec(
+dbg_dname_exec_verb(
char *name1 = knot_dname_to_str(d1);
char *name2 = knot_dname_to_str(d2);
- dbg_dname("Comparing dnames %s and %s\n",
- name1, name2);
+ dbg_dname_verb("Comparing dnames %s and %s\n", name1, name2);
for (int i = 0; i < strlen(name1); ++i) {
name1[i] = knot_tolower(name1[i]);
@@ -312,8 +311,7 @@ dbg_dname_exec(
name2[i] = knot_tolower(name2[i]);
}
- dbg_dname("After to lower: %s and %s\n",
- name1, name2);
+ dbg_dname_detail("After to lower: %s and %s\n", name1, name2);
free(name1);
free(name2);
@@ -325,16 +323,16 @@ dbg_dname_exec(
int l1 = d1->label_count;
int l2 = d2->label_count;
- dbg_dname("Label counts: %d and %d\n", l1, l2);
+ dbg_dname_detail("Label counts: %d and %d\n", l1, l2);
assert(l1 >= 0);
assert(l2 >= 0);
// compare labels from last to first
while (l1 > 0 && l2 > 0) {
- dbg_dname("Comparing labels %d and %d\n",
- l1 - 1, l2 - 1);
- dbg_dname(" at offsets: %d and %d\n",
- d1->labels[l1 - 1], d2->labels[l2 - 1]);
+ dbg_dname_detail("Comparing labels %d and %d\n",
+ l1 - 1, l2 - 1);
+ dbg_dname_detail(" at offsets: %d and %d\n",
+ d1->labels[l1 - 1], d2->labels[l2 - 1]);
int res = knot_dname_compare_labels(
&d1->name[d1->labels[--l1]],
&d2->name[d2->labels[--l2]],
@@ -434,26 +432,6 @@ dbg_dname_exec_verb(
/*----------------------------------------------------------------------------*/
-//int knot_dname_from_wire(knot_dname_t *dname, const uint8_t *name,
-// uint size)
-//{
-// int i = 0;
-// uint8_t labels[KNOT_MAX_DNAME_LABELS];
-// int label_i = 0;
-
-// while (name[i] != 0) {
-// labels[label_i++] = i;
-// uint8_t label_length = name[i];
-// if (i + label_length >= size) {
-// return -2;
-// }
-// for (int j = 1; j <= label_length; ++j) {
-// }
-// }
-//}
-
-/*----------------------------------------------------------------------------*/
-
knot_dname_t *knot_dname_new_from_wire(const uint8_t *name, uint size,
struct knot_node *node)
{
@@ -510,12 +488,10 @@ knot_dname_t *knot_dname_parse_from_wire(const uint8_t *wire,
return NULL;
}
labels[l] = i;
- dbg_dname("Next label (%d.) position: %zu\n", l, i);
+ dbg_dname_detail("Next label (%d.) position: %zu\n", l, i);
if (knot_wire_is_pointer(wire + p)) {
// pointer.
-
-// printf("Pointer.\n");
size_t ptr = knot_wire_get_pointer(wire + p);
/* Check that the pointer points backwards
@@ -622,6 +598,10 @@ knot_dname_t *knot_dname_deep_copy(const knot_dname_t *dname)
/* dname_new_from_wire() does not accept non-FQDN dnames, so we
* do the copy by hand. It's faster anyway */
+ if (dname == NULL) {
+ return NULL;
+ }
+
knot_dname_t *copy = knot_dname_new();
CHECK_ALLOC(copy, NULL);
@@ -771,7 +751,44 @@ struct knot_node *knot_dname_get_node(const knot_dname_t *dname)
if (dname == NULL) {
return NULL;
}
- return dname->node;
+
+ knot_node_t *node = dname->node;
+
+ /*
+ * If the zone contains new zone contents (during an update), we should
+ * return new node. Check if the node has the new node set. If it does
+ * not, it means this is already the new node. If it has, return the
+ * new node. If the new node is empty, return NULL, as the node will be
+ * deleted later.
+ */
+dbg_dname_exec_detail(
+ dbg_dname_detail("Getting node from dname: node: %p, zone: %p\n", node,
+ knot_node_zone(node));
+ if (node != NULL && knot_node_zone(node) != NULL
+ && knot_zone_contents(knot_node_zone(node)) != NULL) {
+ dbg_dname_detail("zone contents gen: %d, new node of the node: "
+ "%p, is empty: %d\n",
+ knot_zone_contents_gen_is_new(knot_zone_contents(
+ knot_node_zone(node))),
+ knot_node_new_node(node),
+ knot_node_new_node(node)
+ ? knot_node_is_empty(knot_node_new_node(node))
+ : -1);
+ }
+);
+
+ if (node && knot_node_zone(node)
+ && knot_zone_contents(knot_node_zone(node))
+ && knot_zone_contents_gen_is_new(knot_zone_contents(
+ knot_node_zone(node)))
+ && knot_node_new_node(node) != NULL) {
+ node = knot_node_get_new_node(node);
+ if (knot_node_is_empty(node)) {
+ node = NULL;
+ }
+ }
+
+ return node;
}
/*----------------------------------------------------------------------------*/
@@ -785,7 +802,20 @@ void knot_dname_set_node(knot_dname_t *dname, knot_node_t *node)
void knot_dname_update_node(knot_dname_t *dname)
{
+dbg_dname_exec_detail(
+ char *name = knot_dname_to_str(dname);
+ dbg_dname_detail("Updating node pointer in dname %p: %s. Before: %p\n",
+ dname, name, dname->node);
+ free(name);
+);
+
knot_node_update_ref(&dname->node);
+ dbg_dname_detail("After: %p\n", dname->node);
+
+ if (knot_node_is_empty(dname->node)) {
+ dbg_dname_detail("Node is empty, setting to NULL.\n");
+ dname->node = NULL;
+ }
}
/*----------------------------------------------------------------------------*/
@@ -829,12 +859,6 @@ knot_dname_t *knot_dname_left_chop(const knot_dname_t *dname)
return parent;
}
-
-// if (dname->label_count <= 1) {
-// /* Nothing to chop. */
-// return NULL;
-// }
-
parent->size = dname->size - dname->name[0] - 1;
parent->name = (uint8_t *)malloc(parent->size);
@@ -894,12 +918,11 @@ void knot_dname_left_chop_no_copy(knot_dname_t *dname)
int knot_dname_is_subdomain(const knot_dname_t *sub,
const knot_dname_t *domain)
{
-dbg_dname_exec(
+dbg_dname_exec_verb(
char *name1 = knot_dname_to_str(sub);
char *name2 = knot_dname_to_str(domain);
- dbg_dname("Checking if %s is subdomain of %s\n",
- name1, name2);
+ dbg_dname_verb("Checking if %s is subdomain of %s\n", name1, name2);
free(name1);
free(name2);
);
@@ -919,7 +942,7 @@ dbg_dname_exec(
int l1 = sub->label_count;
int l2 = domain->label_count;
- dbg_dname("Label counts: %d and %d\n", l1, l2);
+ dbg_dname_detail("Label counts: %d and %d\n", l1, l2);
if (l1 <= l2) { // if sub does not have more labes than domain
return 0; // it is not its subdomain
@@ -927,10 +950,10 @@ dbg_dname_exec(
// compare labels from last to first
while (l1 > 0 && l2 > 0) {
- dbg_dname("Comparing labels %d and %d\n",
- l1 - 1, l2 - 1);
- dbg_dname(" at offsets: %d and %d\n",
- sub->labels[l1 - 1], domain->labels[l2 - 1]);
+ dbg_dname_detail("Comparing labels %d and %d\n",
+ l1 - 1, l2 - 1);
+ dbg_dname_detail(" at offsets: %d and %d\n",
+ sub->labels[l1 - 1], domain->labels[l2 - 1]);
// if some labels do not match
if (knot_dname_compare_labels(&sub->name[sub->labels[--l1]],
&domain->name[domain->labels[--l2]], 0)
@@ -989,15 +1012,6 @@ int knot_dname_label_count(const knot_dname_t *dname)
uint8_t knot_dname_label_size(const knot_dname_t *dname, int i)
{
-// printf("Returning size of %d. label starting on %d\n",
-// i, dname->labels[i]);
-// printf("Label count: %d, size of %d. label: %d, size of %d.label: %d\n",
-// dname->label_count, i, dname->labels[i], i + 1,
-// dname->labels[i+1]);
-// printf("Size from the name: %u\n", dname->name[dname->labels[i]]);
-// printf("Size from label offsets: %u\n",
-// dname->labels[i + 1] - dname->labels[i]);
-
assert(i >= 0);
assert(dname->size == 1 || i + 1 == dname->label_count
|| dname->labels[i + 1] - dname->labels[i] - 1
@@ -1007,17 +1021,16 @@ uint8_t knot_dname_label_size(const knot_dname_t *dname, int i)
/*----------------------------------------------------------------------------*/
-knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *dname,
- int size,
- const knot_dname_t *suffix)
+knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *dname, int size,
+ const knot_dname_t *suffix)
{
-dbg_dname_exec(
+dbg_dname_exec_verb(
char *name = knot_dname_to_str(dname);
- dbg_dname("Replacing suffix of name %s, size %d with ", name,
- size);
+ dbg_dname_verb("Replacing suffix of name %s, size %d with ", name,
+ size);
free(name);
name = knot_dname_to_str(suffix);
- dbg_dname("%s (size %d)\n", name, suffix->size);
+ dbg_dname_verb("%s (size %d)\n", name, suffix->size);
free(name);
);
knot_dname_t *res = knot_dname_new();
@@ -1025,7 +1038,7 @@ dbg_dname_exec(
res->size = dname->size - size + suffix->size;
- dbg_dname("Allocating %d bytes...\n", res->size);
+ dbg_dname_detail("Allocating %d bytes...\n", res->size);
res->name = (uint8_t *)malloc(res->size);
if (res->name == NULL) {
knot_dname_free(&res);
@@ -1034,12 +1047,12 @@ dbg_dname_exec(
dbg_dname_hex((char *)res->name, res->size);
- dbg_dname("Copying %d bytes from the original name.\n",
- dname->size - size);
+ dbg_dname_detail("Copying %d bytes from the original name.\n",
+ dname->size - size);
memcpy(res->name, dname->name, dname->size - size);
dbg_dname_hex((char *)res->name, res->size);
- dbg_dname("Copying %d bytes from the suffix.\n", suffix->size);
+ dbg_dname_detail("Copying %d bytes from the suffix.\n", suffix->size);
memcpy(res->name + dname->size - size, suffix->name, suffix->size);
dbg_dname_hex((char *)res->name, res->size);
@@ -1057,13 +1070,6 @@ void knot_dname_free(knot_dname_t **dname)
return;
}
-// char *name = knot_dname_to_str((*dname));
-
-// printf("freeing in dname: %s %p\n", name, *dname);
-
-// free(name);
-
-
if ((*dname)->name != NULL) {
free((*dname)->name);
}
@@ -1116,13 +1122,13 @@ knot_dname_t *knot_dname_cat(knot_dname_t *d1, const knot_dname_t *d2)
return NULL;
}
- dbg_dname("1: copying %d bytes from adress %p to %p\n",
- d1->size, d1->name, new_dname);
+ dbg_dname_detail("1: copying %d bytes from adress %p to %p\n",
+ d1->size, d1->name, new_dname);
memcpy(new_dname, d1->name, d1->size);
- dbg_dname("2: copying %d bytes from adress %p to %p\n",
- d2->size, d2->name, new_dname + d1->size);
+ dbg_dname_detail("2: copying %d bytes from adress %p to %p\n",
+ d2->size, d2->name, new_dname + d1->size);
memcpy(new_dname + d1->size, d2->name, d2->size);
diff --git a/src/libknot/dname.h b/src/libknot/dname.h
index 473bca7..43bc4d2 100644..100755
--- a/src/libknot/dname.h
+++ b/src/libknot/dname.h
@@ -224,8 +224,6 @@ const struct knot_node *knot_dname_node(const knot_dname_t *dname);
struct knot_node *knot_dname_get_node(const knot_dname_t *dname);
-void knot_dname_set_node(knot_dname_t *dname, struct knot_node *node);
-
void knot_dname_update_node(knot_dname_t *dname);
void knot_dname_set_node(knot_dname_t *dname, struct knot_node *node);
diff --git a/src/libknot/edns.c b/src/libknot/edns.c
index ea630dd..8e1efcc 100644..100755
--- a/src/libknot/edns.c
+++ b/src/libknot/edns.c
@@ -71,21 +71,20 @@ int knot_edns_new_from_wire(knot_opt_rr_t *opt_rr, const uint8_t *wire,
// owner of EDNS OPT RR must be root (0)
if (*pos != 0) {
dbg_edns("EDNS packet malformed (expected root "
- "domain as owner).\n");
+ "domain as owner).\n");
return KNOT_EMALF;
}
pos += 1;
// check the type of the record (must be OPT)
if (knot_wire_read_u16(pos) != KNOT_RRTYPE_OPT) {
- dbg_edns("EDNS packet malformed (expected OPT type"
- ".\n");
+ dbg_edns("EDNS packet malformed (expected OPT type.\n");
return KNOT_EMALF;
}
pos += 2;
opt_rr->payload = knot_wire_read_u16(pos);
- dbg_edns("Parsed payload: %u\n", opt_rr->payload);
+ dbg_edns_verb("Parsed payload: %u\n", opt_rr->payload);
pos += 2;
opt_rr->ext_rcode = *(pos++);
@@ -107,18 +106,18 @@ int knot_edns_new_from_wire(knot_opt_rr_t *opt_rr, const uint8_t *wire,
while (parsed < rdlength + KNOT_EDNS_MIN_SIZE) {
if (max_size - parsed < 4) {
dbg_edns("Not enough data to parse OPT RR"
- " OPTION header.\n");
+ " OPTION header.\n");
return KNOT_EFEWDATA;
}
uint16_t code = knot_wire_read_u16(pos);
pos += 2;
uint16_t length = knot_wire_read_u16(pos);
pos += 2;
- dbg_edns("EDNS OPTION: Code: %u, Length: %u\n",
- code, length);
+ dbg_edns_verb("EDNS OPTION: Code: %u, Length: %u\n",
+ code, length);
if (max_size - parsed - 4 < length) {
dbg_edns("Not enough data to parse OPT RR"
- " OPTION data.\n");
+ " OPTION data.\n");
return KNOT_EFEWDATA;
}
int ret;
@@ -144,28 +143,28 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
return KNOT_EBADARG;
}
- dbg_edns("Parsing payload.\n");
+ dbg_edns_verb("Parsing payload.\n");
opt_rr->payload = knot_rrset_class(rrset);
// the TTL has switched bytes
uint32_t ttl;
- dbg_edns("TTL: %u\n", knot_rrset_ttl(rrset));
+ dbg_edns_detail("TTL: %u\n", knot_rrset_ttl(rrset));
knot_wire_write_u32((uint8_t *)&ttl, knot_rrset_ttl(rrset));
// first byte of TTL is extended RCODE
- dbg_edns("TTL: %u\n", ttl);
+ dbg_edns_detail("TTL: %u\n", ttl);
memcpy(&opt_rr->ext_rcode, &ttl, 1);
- dbg_edns("Parsed extended RCODE: %u.\n", opt_rr->ext_rcode);
+ dbg_edns_detail("Parsed extended RCODE: %u.\n", opt_rr->ext_rcode);
// second is the version
memcpy(&opt_rr->version, (const uint8_t *)(&ttl) + 1, 1);
- dbg_edns("Parsed version: %u.\n", opt_rr->version);
+ dbg_edns_detail("Parsed version: %u.\n", opt_rr->version);
// third and fourth are flags
opt_rr->flags = knot_wire_read_u16((const uint8_t *)(&ttl) + 2);
- dbg_edns("Parsed flags: %u.\n", opt_rr->flags);
+ dbg_edns_detail("Parsed flags: %u.\n", opt_rr->flags);
// size of the header, options are counted elsewhere
opt_rr->size = 11;
int rc = 0;
- dbg_edns("Parsing options.\n");
+ 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,
@@ -206,7 +205,7 @@ int knot_edns_new_from_rr(knot_opt_rr_t *opt_rr,
}
- dbg_edns("EDNS created.\n");
+ dbg_edns_verb("EDNS created.\n");
return KNOT_EOK;
}
@@ -316,10 +315,10 @@ int knot_edns_add_option(knot_opt_rr_t *opt_rr, uint16_t code,
free(old_options);
}
- dbg_edns("Adding option.\n");
- dbg_edns("Code: %u.\n", code);
- dbg_edns("Length: %u.\n", length);
- dbg_edns("Data: %p.\n", data);
+ dbg_edns_verb("Adding option.\n");
+ dbg_edns_verb("Code: %u.\n", code);
+ dbg_edns_verb("Length: %u.\n", length);
+ dbg_edns_verb("Data: %p.\n", data);
opt_rr->options[opt_rr->option_count].data = (uint8_t *)malloc(length);
CHECK_ALLOC_LOG(opt_rr->options[opt_rr->option_count].data, KNOT_ENOMEM);
@@ -370,9 +369,9 @@ short knot_edns_to_wire(const knot_opt_rr_t *opt_rr, uint8_t *wire,
uint8_t *pos = wire;
- dbg_edns_detail("Putting OPT RR to the wire format. Size: %d, "
- "position: %zu\n",
- opt_rr->size, (size_t)(pos - wire));
+ dbg_edns_verb("Putting OPT RR to the wire format. Size: %d, "
+ "position: %zu\n",
+ opt_rr->size, (size_t)(pos - wire));
*(pos++) = 0;
knot_wire_write_u16(pos, KNOT_RRTYPE_OPT);
diff --git a/src/libknot/edns.h b/src/libknot/edns.h
index 022ac36..022ac36 100644..100755
--- a/src/libknot/edns.h
+++ b/src/libknot/edns.h
diff --git a/src/libknot/hash/cuckoo-hash-table.c b/src/libknot/hash/cuckoo-hash-table.c
index 9db32bf..7358e14 100644..100755
--- a/src/libknot/hash/cuckoo-hash-table.c
+++ b/src/libknot/hash/cuckoo-hash-table.c
@@ -30,7 +30,6 @@
#include "util/debug.h"
#include "hash/cuckoo-hash-table.h"
#include "hash/hash-functions.h"
-#include "common/dynamic-array.h"
/*----------------------------------------------------------------------------*/
/* Macros and inline functions */
@@ -283,6 +282,8 @@ static int ck_stash_is_full(const ck_hash_table_t *table)
*/
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;
}
@@ -320,49 +321,11 @@ static inline void ck_swap_items(ck_hash_table_item_t **item1,
static inline void ck_put_item(ck_hash_table_item_t **to,
ck_hash_table_item_t *item)
{
- *to = item;
-}
-
-/*----------------------------------------------------------------------------*/
-/*!
- * \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 uint ck_check_used_twice(da_array_t *used, uint32_t hash)
-{
- uint i = 0, found = 0;
- while (i < da_get_count(used) && found < 2) {
- if (((uint *)(da_get_items(used)))[i] == hash) {
- ++found;
- }
- ++i;
- }
-
- if (found == 2) {
- dbg_ck_hash("Hashing entered infinite loop.\n");
- return -1;
- } else {
- if (da_reserve(used, 1) < 0) {
- ERR_ALLOC_FAILED;
- return -2;
- }
- ((uint *)da_get_items(used))[da_get_count(used)] = hash;
- da_occupy(used, 1);
- assert(da_get_count(used) < RELOCATIONS_MAX);
- return 0;
+ if (item == NULL) {
+ dbg_stash("[EMPTY STASH] [CREATE] Putting NULL to item %p.\n",
+ to);
}
+ *to = item;
}
/*----------------------------------------------------------------------------*/
@@ -419,12 +382,14 @@ static ck_hash_table_item_t **ck_find_in_stash(const ck_hash_table_t *table,
* non-NULL.
*/
if (item->item && ck_items_match(item->item, key, length)) {
- dbg_ck("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);
+ 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;
}
@@ -448,18 +413,18 @@ static ck_hash_table_item_t **ck_find_gen(const ck_hash_table_t *table,
size_t length, uint8_t generation)
{
uint32_t hash;
- dbg_ck("Finding item in generation: %u\n", generation);
+ 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("Hash: %u, key: %.*s\n", hash, (int)length, key);
- dbg_ck("Table %d, hash: %u, item: %p\n", t + 1, hash,
- table->tables[t][hash]);
+ 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("Table %u, key: %.*s, value: %p, key "
+ 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,
@@ -475,16 +440,16 @@ static ck_hash_table_item_t **ck_find_gen(const ck_hash_table_t *table,
}
// try to find in stash
- dbg_ck("Searching in stash...\n");
+ dbg_ck_verb("Searching in stash...\n");
ck_hash_table_item_t **found =
ck_find_in_stash(table, key, length);
- dbg_ck("Found pointer: %p\n", found);
+ dbg_ck_verb("Found pointer: %p\n", found);
if (found != NULL) {
- dbg_ck("Stash, key: %.*s, value: %p, key length: %zu\n",
- (int)(*found)->key_length, (*found)->key,
- (*found)->value, (*found)->key_length);
+ 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
@@ -520,6 +485,136 @@ static ck_hash_table_item_t **ck_find_item_nc(const ck_hash_table_t *table,
}
/*----------------------------------------------------------------------------*/
+/* 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.
*
@@ -532,20 +627,26 @@ static ck_hash_table_item_t **ck_find_item_nc(const ck_hash_table_t *table,
*
* \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));
+// 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("Hashing key: %.*s of size %zu.\n",
- (int)(*to_hash)->key_length, (*to_hash)->key,
- (*to_hash)->key_length);
+ 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;
@@ -553,21 +654,24 @@ static int ck_hash_item(ck_hash_table_t *table, ck_hash_table_item_t **to_hash,
(*to_hash)->key_length, table->table_size_exp,
generation, next_table);
- dbg_ck_hash("New hash: %u.\n", hash);
+ dbg_ck_hash_detail("New hash: %u.\n", hash);
assert(hash < hashsize(table->table_size_exp));
- ((uint *)da_get_items(&used[next_table]))
- [da_get_count(&used[next_table])] = hash;
+ 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("Item to be moved: %p, place in table: %p\n",
- *next, next);
+ 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("Swapping items to hash: %p and Moving: %p\n",
- to_hash, moving);
+ 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
@@ -575,9 +679,10 @@ static int ck_hash_item(ck_hash_table_t *table, ck_hash_table_item_t **to_hash,
moving = next;
- dbg_ck_hash("Moving item from table %u, key: %.*s, hash %u ",
- next_table + 1, (int)(*moving)->key_length,
- (*moving)->key, hash);
+ 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
@@ -594,31 +699,31 @@ static int ck_hash_item(ck_hash_table_t *table, ck_hash_table_item_t **to_hash,
next = &table->tables[next_table][hash];
- dbg_ck_hash("to table %u, hash %u, item: %p, place: %p\n",
- next_table + 1, hash, *next, next);
+ 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("Table %u, hash: %u, key: %.*s\n",
- next_table + 1, hash,
- (int)(*next)->key_length, (*next)->key);
+ 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) {
+ if (ck_check_used_twice(&used, next_table, hash) != 0) {
next = free;
loop = -1;
break;
}
}
- dbg_ck_hash("Putting pointer %p (*moving) to item %p (next).\n",
- *moving, next);
+ 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("Putting pointer %p (*old) to item %p (moving).\n",
- *to_hash, moving);
+ dbg_ck_hash_detail("Putting pointer %p (*old) to item %p (moving).\n",
+ *to_hash, moving);
ck_put_item(moving, *to_hash);
@@ -626,9 +731,7 @@ static int ck_hash_item(ck_hash_table_t *table, ck_hash_table_item_t **to_hash,
SET_GENERATION(&(*moving)->timestamp, generation);
*to_hash = NULL;
- for (uint i = 0; i < table->table_count; ++i) {
- da_destroy(&used[i]);
- }
+ ck_used_free(&used);
return loop;
}
@@ -670,6 +773,10 @@ static void ck_rollback_rehash(ck_hash_table_t *table)
*/
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) {
@@ -681,8 +788,8 @@ int ck_add_to_stash(ck_hash_table_t *table, ck_hash_table_item_t *item)
new_item->next = table->stash;
table->stash = new_item;
- dbg_ck_hash("First item in stash (now inserted): key: %.*s (size %zu)"
- ", value: %p\n", (int)table->stash->item->key_length,
+ 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);
@@ -739,12 +846,12 @@ ck_hash_table_t *ck_create_table(uint items)
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);
+ 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 *));
+ 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) {
@@ -805,18 +912,6 @@ void ck_destroy_table(ck_hash_table_t **table, void (*dtor_value)(void *value),
}
// destroy items in stash
-// ck_hash_table_item_t **stash =
-// ((ck_hash_table_item_t **)(da_get_items(&(*table)->stash)));
-// for (uint i = 0; i < da_get_count(&(*table)->stash); ++i) {
-// assert(stash[i] != NULL);
-// if (dtor_value) {
-// dtor_value(stash[i]->value);
-// }
-// if (delete_key != 0) {
-// free((void *)stash[i]->key);
-// }
-// free((void *)stash[i]);
-// }
ck_stash_item_t *item = (*table)->stash;
while (item != NULL) {
// disconnect the item
@@ -842,8 +937,6 @@ void ck_destroy_table(ck_hash_table_t **table, void (*dtor_value)(void *value),
for (uint t = 0; t < (*table)->table_count; ++t) {
free((*table)->tables[t]);
}
- // destroy stash
-// da_destroy(&(*table)->stash);
pthread_mutex_unlock(&(*table)->mtx_table);
// destroy mutex, assuming that here noone will lock the mutex again
@@ -884,7 +977,7 @@ void ck_table_free(ck_hash_table_t **table)
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
@@ -900,7 +993,7 @@ int ck_resize_table(ck_hash_table_t *table)
ck_hash_table_item_t **tables_old[MAX_TABLES];
int exp_new = table->table_size_exp + 1;
- dbg_ck("New tables exponent: %d\n", exp_new);
+ 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) {
@@ -919,14 +1012,14 @@ int ck_resize_table(ck_hash_table_t *table)
* sizeof(ck_hash_table_item_t *);
// copy the old table items
- dbg_ck("Copying to: %p, from %p, size: %zu\n",
- tables_new[t], table->tables[t], old_size);
+ 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("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);
+ 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);
@@ -948,7 +1041,6 @@ int ck_resize_table(ck_hash_table_t *table)
}
return ck_rehash(table);
- //return 0;
}
int ck_insert_item(ck_hash_table_t *table, const char *key,
@@ -980,9 +1072,6 @@ int ck_insert_item(ck_hash_table_t *table, const char *key,
}
}
- // there should be at least 2 free places
- //assert(da_try_reserve(&table->stash, 2) == 0);
- //da_reserve(&table->stash, 1);
ck_hash_table_item_t *free_place = NULL;
if (ck_hash_item(table, &new_item, &free_place,
table->generation) != 0) {
@@ -1104,6 +1193,8 @@ ck_hash_table_item_t *ck_remove_item(ck_hash_table_t *table, const char *key,
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;
}
@@ -1176,26 +1267,27 @@ int ck_shallow_copy(const ck_hash_table_t *from, ck_hash_table_t **to)
return -2;
}
- dbg_ck("Copying stash item: %p with item %p, ", si, si->item);
- dbg_ck("key: %.*s\n", (int)si->item->key_length, si->item->key);
+ 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;
*pos = si_new;
pos = &si_new->next;
si = si->next;
-
- dbg_ck("Old stash item: %p with item %p, ", si,
- ((si == NULL) ? NULL : si->item));
+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("key: %.*s\n", (int)si->item->key_length, si->item->key);
- } else {
- dbg_ck("\n");
+ dbg_ck_detail("key: %.*s\n", (int)si->item->key_length,
+ si->item->key);
}
- dbg_ck("New stash item: %p with item %p, ", si_new,
- si_new->item);
- dbg_ck("key: %.*s\n", (int)si_new->item->key_length,
- si_new->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);
+);
}
*pos = NULL;
@@ -1273,11 +1365,12 @@ void ck_deep_copy_cleanup(ck_hash_table_t *table, int table_count)
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;
}
- dbg_ck("Allocating new table...\n");
*to = (ck_hash_table_t *)malloc(sizeof(ck_hash_table_t));
if (*to == NULL) {
@@ -1341,10 +1434,12 @@ int ck_deep_copy(ck_hash_table_t *from, ck_hash_table_t **to)
return -2;
}
- dbg_ck("Copying stash item: %p with item %p, ", si, si->item);
-// dbg_ck("key: %.*s\n", (int)si->item->key_length, si->item->key);
+ dbg_ck_detail("Copying stash item: %p with item %p, ", 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 {
@@ -1367,22 +1462,20 @@ int ck_deep_copy(ck_hash_table_t *from, ck_hash_table_t **to)
pos = &si_new->next;
si = si->next;
-dbg_ck_exec(
- dbg_ck("Old stash item: %p with item %p, ", si,
- ((si == NULL) ? NULL : si->item));
+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("key: %.*s\n", (int)si->item->key_length,
- si->item->key);
- } else {
- dbg_ck("\n");
+ dbg_ck_detail("key: %.*s\n", (int)si->item->key_length,
+ si->item->key);
}
- dbg_ck("New stash item: %p with item %p, ", si_new,
- (si_new) ? si_new->item : NULL);
+ dbg_ck_detail("New stash item: %p with item %p, ", si_new,
+ (si_new) ? si_new->item : NULL);
assert(si_new != NULL);
assert(si_new->item != NULL);
- dbg_ck("key: %.*s\n", (int)si_new->item->key_length,
- si_new->item->key);
+ dbg_ck_detail("key: %.*s\n", (int)si_new->item->key_length,
+ si_new->item->key);
);
}
@@ -1446,13 +1539,13 @@ int ck_rehash(ck_hash_table_t *table)
do {
// 1) Rehash items from stash
- dbg_ck_rehash("Rehashing items from stash.\n");
+ 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_rehash("Rehashing item with "
+ 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,
@@ -1481,6 +1574,8 @@ int ck_rehash(ck_hash_table_t *table)
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;
@@ -1501,12 +1596,11 @@ int ck_rehash(ck_hash_table_t *table)
// which will be put to the stash
ck_hash_table_item_t *free = NULL;
assert(table->hashed == NULL);
-// ck_hash_table_item_t *old = table->hashed;
for (uint t = 0; t < table->table_count; ++t) {
uint rehashed = 0;
- dbg_ck_rehash("Rehashing table %d.\n", t);
+ dbg_ck_hash_verb("Rehashing table %d.\n", t);
while (rehashed < hashsize(table->table_size_exp)) {
@@ -1516,13 +1610,13 @@ int ck_rehash(ck_hash_table_t *table)
|| !(EQUAL_GENERATIONS(
table->tables[t][rehashed]->timestamp,
table->generation))) {
- dbg_ck_rehash("Skipping item.\n");
+ dbg_ck_hash_detail("Skipping item.\n");
++rehashed;
continue;
}
- dbg_ck_rehash("Rehashing item with hash %u, "
- "key (length %zu): %.*s, generation: %hu, "
+ 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),
@@ -1537,8 +1631,8 @@ int ck_rehash(ck_hash_table_t *table)
// get rehashed again
ck_clear_item(&table->tables[t][rehashed]);
- dbg_ck_rehash("Table generation: %hu, next "
- "generation: %hu.\n",
+ dbg_ck_hash_detail("Table generation: %hu, next"
+ " generation: %hu.\n",
GET_GENERATION(table->generation),
NEXT_GENERATION(table->generation));
@@ -1546,8 +1640,8 @@ int ck_rehash(ck_hash_table_t *table)
NEXT_GENERATION(table->generation)) != 0) {
// loop occured
dbg_ck_hash("Hashing entered a loop."
- "\n");
- dbg_ck_rehash("Item with key %.*s "
+ "\n");
+ dbg_ck_hash_verb("Item with key %.*s "
"inserted into the free slot.\n",
free->key_length, free->key);
@@ -1561,6 +1655,12 @@ int ck_rehash(ck_hash_table_t *table)
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;
@@ -1579,15 +1679,15 @@ int ck_rehash(ck_hash_table_t *table)
}
}
- dbg_ck_rehash("Old table generation: %u\n",
- GET_GENERATION(table->generation));
+ 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_rehash("New table generation: %u\n",
- GET_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_rehash("Generating coeficients for generation: %u\n",
- NEXT_GENERATION(table->generation));
+ dbg_ck_hash("Generating coeficients for generation: %u\n",
+ NEXT_GENERATION(table->generation));
us_next(&table->hash_system,
NEXT_GENERATION(table->generation));
@@ -1609,248 +1709,6 @@ int ck_rehash(ck_hash_table_t *table)
}
/*----------------------------------------------------------------------------*/
-/*!
- * \brief Rehashes the whole table.
- *
- * \param table Hash table to be rehashed.
- *
- * \note While rehashing no item should be inserted as it will result in a
- * deadlock.
- *
- * \retval 0 No error.
- * \retval -1 Rehashing failed. Some items may have been already moved and the
- * rehashing flag remains set.
- *
- * \todo What if the stash is reallocated during ck_hash_item()? We'd be using
- * the old stash for saving items! The old stash would not get deallocated
- * (due to RCU - maybe put some rcu_read_lock() here), but the item
- * would not be saved into the new stash!
- * Maybe add a function for getting a pointer to particular item from
- * the dynamic array and protect it using rcu_read_lock().
- * Other option: Do not use pointer to an item in stash in the call to
- * ck_hash_item(). Use some new place & put the item to the stash
- * afterwards, protecting it using rcu_read_lock() and rcu_assign_pointer.
- */
-//int ck_rehash(ck_hash_table_t *table)
-//{
-// dbg_ck_rehash("Rehashing items in table.\n");
-// SET_REHASHING_ON(&table->generation);
-
-// // we already have functions for the next generation, begin rehashing
-// // we wil use the last item in the buffer as free cell for hashing
-// assert(da_try_reserve(&table->stash, 1) == 0);
-// ck_hash_table_item_t *old = (ck_hash_table_item_t *)
-// (malloc(sizeof(ck_hash_table_item_t)));
-
-// do {
-// dbg_ck_hash("Rehash!\n");
-
-// if (da_get_count(&table->stash) > STASH_SIZE) {
-// dbg_ck_hash("STASH RESIZED!!! (new stash size: %d)\n",
-// da_get_count(&table->stash));
-// }
-
-// // rehash items from stash, starting from the last old item
-// int stash_i = da_get_count(&table->stash) - 1;
-// while (stash_i >= 0) {
-// // if item's generation is the new generation, skip
-// if (STASH_ITEMS(&table->stash)[stash_i] == NULL
-// || !(EQUAL_GENERATIONS(STASH_ITEMS(&table->stash)
-// [stash_i]->timestamp,
-// table->generation))) {
-// dbg_ck_rehash("Skipping item.\n");
-// --stash_i;
-// continue;
-// }
-
-// dbg_ck_rehash("Rehashing item from buffer position %u"
-// ", key (length %u): %.*s, generation: "
-// "%hu, table generation: %hu.\n",
-// stash_i,
-// STASH_ITEMS(&table->stash)[stash_i]->key_length,
-// (int)STASH_ITEMS(&table->stash)[stash_i]->key_length,
-// STASH_ITEMS(&table->stash)[stash_i]->key,
-// GET_GENERATION(
-// STASH_ITEMS(&table->stash)[stash_i]->timestamp),
-// GET_GENERATION(table->generation));
-
-// // otherwise copy the item for rehashing
-// ck_put_item(&old, STASH_ITEMS(&table->stash)[stash_i]);
-// // clear the place so that this item will not get
-// // rehashed again
-// ck_clear_item(&STASH_ITEMS(&table->stash)[stash_i]);
-// da_release(&table->stash, 1);
-
-// // there should be at least one place in the stash
-// assert(da_try_reserve(&table->stash, 1) == 0);
-// da_reserve(&table->stash, 1);
-
-// assert(STASH_ITEMS(&table->stash)[stash_i] == NULL);
-
-// // and start rehashing
-// if (ck_hash_item(table, &old,
-// &STASH_ITEMS(&table->stash)[stash_i],
-// NEXT_GENERATION(table->generation)) != 0) {
-// // loop occured
-// dbg_ck_hash("Hashing entered a loop.\n");
-
-// dbg_ck_rehash("Item with key %.*s inserted "
-// "into the stash on position %d.\n",
-// STASH_ITEMS(&table->stash)
-// [stash_i]->key_length,
-// STASH_ITEMS(&table->stash)
-// [stash_i]->key,
-// da_get_count(&table->stash));
-
-// // hashing unsuccessful, the item was inserted
-// // into the stash
-// da_occupy(&table->stash, 1);
-// assert(STASH_ITEMS(&table->stash)[stash_i]
-// != NULL);
-
-// // if only one place left, resize the stash
-// // TODO: Why???
-// if (da_reserve(&table->stash, 2) < 0) {
-// // stash could not be resized => !!!
-// dbg_ck_hash("Failed to rehash items "
-// "from "
-// "table, no other rehash possible!\n");
-// // so rollback
-// ck_rollback_rehash(table);
-// // clear the 'old' item
-// ck_clear_item(&old);
-// return -1;
-// }
-// }
-
-// // clear the 'old' item
-// ck_clear_item(&old);
-// // decrement the index
-// --stash_i;
-// }
-
-// uint i = 0;
-// while (i < da_get_count(&table->stash)) {
-// assert(STASH_ITEMS(&table->stash)[i] != NULL);
-// ++i;
-// }
-// dbg_ck_hash("OK\n");
-// assert(da_try_reserve(&table->stash, 1) == 0);
-// assert(STASH_ITEMS(&table->stash)[da_get_count(&table->stash)]
-// == NULL);
-
-// // rehash items from hash tables
-// for (uint t = TABLE_FIRST;
-// t <= TABLE_LAST(table->table_count); ++t) {
-// dbg_ck_rehash("Rehashing items from table %d.\n",
-// t + 1);
-// uint rehashed = 0;
-
-// 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_rehash("Skipping item.\n");
-// ++rehashed;
-// continue;
-// }
-
-// dbg_ck_rehash("Rehashing item with hash %u, "
-// "key (length %u): %.*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(&old, 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_rehash("Table generation: %hu, next "
-// "generation: %hu.\n",
-// GET_GENERATION(table->generation),
-// NEXT_GENERATION(table->generation));
-
-// // and start rehashing
-// assert(&old != &STASH_ITEMS(&table->stash)[
-// da_get_count(&table->stash)]);
-// assert(da_try_reserve(&table->stash, 1) == 0);
-// da_reserve(&table->stash, 1);
-
-// if (ck_hash_item(table, &old,
-// &STASH_ITEMS(&table->stash)[
-// da_get_count(&table->stash)],
-// NEXT_GENERATION(table->generation)) != 0) {
-// // loop occured
-// dbg_ck_hash("Hashing entered a loop."
-// "\n");
-// dbg_ck_rehash("Item with key %.*s "
-// "inserted into the stash on position "
-// "%d.\n", STASH_ITEMS(&table->stash)[
-// da_get_count(&table->stash)]
-// ->key_length,
-// STASH_ITEMS(&table->stash)[
-// da_get_count(&table->stash)]->key,
-// da_get_count(&table->stash));
-
-// assert(STASH_ITEMS(&table->stash)[
-// da_get_count(&table->stash)] != NULL);
-// // loop occured, the item is already at
-// // its new place in the buffer, so just
-// // increment the index
-// da_occupy(&table->stash, 1);
-
-// // if only one place left, resize the
-// // stash TODO: Why?
-// if (da_reserve(&table->stash, 2) < 0) {
-// // stash could not be resized
-// dbg_ck_hash("Failed to rehash"
-// " items from table, no other "
-// "rehash possible!\n");
-// // so rollback
-// ck_rollback_rehash(table);
-// // clear the 'old' item
-// ck_clear_item(&old);
-// return -1;
-// }
-// }
-// ++rehashed;
-// }
-// }
-
-// dbg_ck_rehash("Old table generation: %u\n",
-// GET_GENERATION(table->generation));
-// // rehashing completed, switch generation of the table
-// SET_NEXT_GENERATION(&table->generation);
-// dbg_ck_rehash("New table generation: %u\n",
-// GET_GENERATION(table->generation));
-// // generate new hash functions for the old generation
-// dbg_ck_rehash("Generating coeficients for generation: %u\n",
-// NEXT_GENERATION(table->generation));
-// us_next(NEXT_GENERATION(table->generation));
-
-// // repeat rehashing while there are more items in the stash than
-// // its initial size
-// if (da_get_count(&table->stash) > STASH_SIZE) {
-// dbg_ck_rehash("Rehashing again!\n");
-// }
-// } while (da_get_count(&table->stash) > STASH_SIZE);
-
-// SET_REHASHING_OFF(&table->generation);
-
-// return 0;
-//}
-
-/*----------------------------------------------------------------------------*/
void ck_dump_table(const ck_hash_table_t *table)
{
@@ -1872,15 +1730,6 @@ void ck_dump_table(const ck_hash_table_t *table)
}
dbg_ck("Stash:\n");
-// for (i = 0; i < da_get_count(&table->stash); ++i) {
-// dbg_ck("Index: %u, Key: %.*s Value: %p.\n", i,
-// ((ck_hash_table_item_t **)
-// da_get_items(&table->stash))[i]->key_length,
-// ((ck_hash_table_item_t **)
-// da_get_items(&table->stash))[i]->key,
-// ((ck_hash_table_item_t **)
-// da_get_items(&table->stash))[i]->value);
-// }
ck_stash_item_t *item = table->stash;
while (item != NULL) {
dbg_ck("Hash: %u, Key: %.*s, Value: %p.\n", i,
diff --git a/src/libknot/hash/cuckoo-hash-table.h b/src/libknot/hash/cuckoo-hash-table.h
index eaa6a89..c0fe9cc 100644..100755
--- a/src/libknot/hash/cuckoo-hash-table.h
+++ b/src/libknot/hash/cuckoo-hash-table.h
@@ -42,7 +42,6 @@
#include <pthread.h>
#include "hash/universal-system.h"
-#include "common/dynamic-array.h"
/*----------------------------------------------------------------------------*/
diff --git a/src/libknot/hash/hash-functions.c b/src/libknot/hash/hash-functions.c
index a33dd6b..a33dd6b 100644..100755
--- a/src/libknot/hash/hash-functions.c
+++ b/src/libknot/hash/hash-functions.c
diff --git a/src/libknot/hash/hash-functions.h b/src/libknot/hash/hash-functions.h
index f23730b..f23730b 100644..100755
--- a/src/libknot/hash/hash-functions.h
+++ b/src/libknot/hash/hash-functions.h
diff --git a/src/libknot/hash/universal-system.c b/src/libknot/hash/universal-system.c
index 096974c..096974c 100644..100755
--- a/src/libknot/hash/universal-system.c
+++ b/src/libknot/hash/universal-system.c
diff --git a/src/libknot/hash/universal-system.h b/src/libknot/hash/universal-system.h
index 25330de..25330de 100644..100755
--- a/src/libknot/hash/universal-system.h
+++ b/src/libknot/hash/universal-system.h
diff --git a/src/libknot/libknot.h b/src/libknot/libknot.h
index a401be7..a401be7 100644..100755
--- a/src/libknot/libknot.h
+++ b/src/libknot/libknot.h
diff --git a/src/libknot/nameserver/name-server.c b/src/libknot/nameserver/name-server.c
index 7a6bc4d..6924f44 100644..100755
--- a/src/libknot/nameserver/name-server.c
+++ b/src/libknot/nameserver/name-server.c
@@ -126,10 +126,9 @@ 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("Synthetizing RRSet from wildcard...\n");
+ dbg_ns_verb("Synthetizing RRSet from wildcard...\n");
knot_dname_t *owner = knot_dname_deep_copy(qname);
-// printf("Copied owner ptr: %p\n", owner);
knot_rrset_t *synth_rrset = knot_rrset_new(
owner, knot_rrset_type(wildcard_rrset),
@@ -143,7 +142,7 @@ static knot_rrset_t *ns_synth_from_wildcard(
return NULL;
}
- dbg_ns("Created RRSet header:\n");
+ dbg_ns_verb("Created RRSet header:\n");
knot_rrset_dump(synth_rrset, 1);
// copy all RDATA
@@ -159,15 +158,15 @@ static knot_rrset_t *ns_synth_from_wildcard(
return NULL;
}
- dbg_ns("Copied RDATA:\n");
+ dbg_ns_verb("Copied RDATA:\n");
knot_rdata_dump(rdata_copy,
knot_rrset_type(synth_rrset), 1);
- knot_rrset_add_rdata(synth_rrset, rdata_copy);
+ int ret = knot_rrset_add_rdata(synth_rrset, rdata_copy);
+ assert(ret == KNOT_EOK);
rdata = knot_rrset_rdata_next(wildcard_rrset, rdata);
}
-// printf("Synthetized RRSet pointer: %p\n", synth_rrset);
return synth_rrset;
}
@@ -182,8 +181,8 @@ static knot_rrset_t *ns_synth_from_wildcard(
* temporary RRSet).
* \param rrset RRSet to check (and possibly replace).
*/
-static void ns_check_wildcard(const knot_dname_t *name, knot_packet_t *resp,
- knot_rrset_t **rrset)
+static int ns_check_wildcard(const knot_dname_t *name, knot_packet_t *resp,
+ knot_rrset_t **rrset)
{
assert(name != NULL);
assert(resp != NULL);
@@ -193,11 +192,26 @@ static void ns_check_wildcard(const knot_dname_t *name, knot_packet_t *resp,
if (knot_dname_is_wildcard((*rrset)->owner)) {
knot_rrset_t *synth_rrset =
ns_synth_from_wildcard(*rrset, name);
- dbg_ns("Synthetized RRSet:\n");
+ if (synth_rrset == NULL) {
+ dbg_ns("Failed to synthetize RRSet from wildcard.\n");
+ return KNOT_ERROR;
+ }
+
+dbg_ns_exec_verb(
+ dbg_ns_verb("Synthetized RRSet:\n");
knot_rrset_dump(synth_rrset, 1);
- knot_packet_add_tmp_rrset(resp, 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);
+ return ret;
+ }
*rrset = synth_rrset;
}
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -230,23 +244,28 @@ static int ns_add_rrsigs(knot_rrset_t *rrset, knot_packet_t *resp,
{
knot_rrset_t *rrsigs;
- dbg_ns("Adding RRSIGs for RRSet, type: %s.\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ dbg_ns_verb("Adding RRSIGs for RRSet, type: %s.\n",
+ knot_rrtype_to_string(knot_rrset_type(rrset)));
assert(resp != NULL);
assert(add_rrset_to_resp != NULL);
- dbg_ns("DNSSEC requested: %d\n",
- knot_query_dnssec_requested(knot_packet_query(resp)));
- dbg_ns("RRSIGS: %p\n", knot_rrset_rrsigs(rrset));
+ dbg_ns_detail("DNSSEC requested: %d\n",
+ knot_query_dnssec_requested(knot_packet_query(resp)));
+ dbg_ns_detail("RRSIGS: %p\n", knot_rrset_rrsigs(rrset));
if (DNSSEC_ENABLED
&& knot_query_dnssec_requested(knot_packet_query(resp))
&& (rrsigs = knot_rrset_get_rrsigs(rrset)) != NULL) {
if (name != NULL) {
- ns_check_wildcard(name, resp, &rrsigs);
+ int ret = ns_check_wildcard(name, resp, &rrsigs);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to process wildcard: %s\n",
+ knot_strerror(ret));
+ return ret;
+ }
}
- return add_rrset_to_resp(resp, rrsigs, tc, 0, 0, 1);
+ return add_rrset_to_resp(resp, rrsigs, tc, 1, 0, 1);
}
return KNOT_EOK;
@@ -265,7 +284,7 @@ static int ns_add_rrsigs(knot_rrset_t *rrset, knot_packet_t *resp,
* \param tc Set to 1 if omitting the RRSIG RRSet should result in setting the
* TC bit in the response.
*/
-static void ns_follow_cname(const knot_node_t **node,
+static int ns_follow_cname(const knot_node_t **node,
const knot_dname_t **qname,
knot_packet_t *resp,
int (*add_rrset_to_resp)(knot_packet_t *,
@@ -273,19 +292,22 @@ static void ns_follow_cname(const knot_node_t **node,
int, int, int, int),
int tc)
{
- dbg_ns("Resolving CNAME chain...\n");
+ dbg_ns_verb("Resolving CNAME chain...\n");
knot_rrset_t *cname_rrset;
+ int ret = 0;
+
while (*node != NULL
&& (cname_rrset = knot_node_get_rrset(*node, KNOT_RRTYPE_CNAME))
- != NULL) {
+ != NULL
+ && (knot_rrset_rdata(cname_rrset) != NULL)) {
/* put the CNAME record to answer, but replace the possible
wildcard name with qname */
assert(cname_rrset != NULL);
- dbg_ns("CNAME RRSet: %p, owner: %p\n", cname_rrset,
- cname_rrset->owner);
+ dbg_ns_detail("CNAME RRSet: %p, owner: %p\n", cname_rrset,
+ cname_rrset->owner);
knot_rrset_t *rrset = cname_rrset;
@@ -294,27 +316,67 @@ static void ns_follow_cname(const knot_node_t **node,
/* if wildcard node, we must copy the RRSet and
replace its owner */
rrset = ns_synth_from_wildcard(cname_rrset, *qname);
- knot_packet_add_tmp_rrset(resp, rrset);
- add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
- ns_add_rrsigs(cname_rrset, resp, *qname,
- add_rrset_to_resp, tc);
+ if (rrset == NULL) {
+ dbg_ns("Failed to synthetize RRSet from "
+ "wildcard RRSet followed from CNAME.\n");
+ return KNOT_ERROR; /*! \todo Better error. */
+ }
+
+ ret = knot_packet_add_tmp_rrset(resp, rrset);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add synthetized RRSet (CNAME "
+ "follow) to the tmp RRSets in response."
+ "\n");
+ knot_rrset_deep_free(&rrset, 1, 1, 1);
+ return ret;
+ }
+
+ ret = add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add synthetized RRSet (CNAME "
+ "follow) to the response.\n");
+ return ret;
+ }
+
+ ret = ns_add_rrsigs(cname_rrset, resp, *qname,
+ add_rrset_to_resp, tc);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add RRSIG for the synthetized"
+ "RRSet (CNAME follow) to the response."
+ "\n");
+ return ret;
+ }
int ret = knot_response_add_wildcard_node(
resp, *node, *qname);
-
- /*! \todo Fix when return values are handled! */
if (ret != KNOT_EOK) {
- assert(0);
+ dbg_ns("Failed to add wildcard node for later "
+ "processing.\n");
+ return ret;
}
} else {
- add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
- ns_add_rrsigs(rrset, resp, *qname, add_rrset_to_resp,
- tc);
+ ret = add_rrset_to_resp(resp, rrset, tc, 0, 0, 1);
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add followed RRSet into"
+ "the response.\n");
+ return ret;
+ }
+
+ ret = ns_add_rrsigs(rrset, resp, *qname,
+ add_rrset_to_resp, tc);
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add RRSIG for followed RRSet "
+ "into the response.\n");
+ return ret;
+ }
}
- dbg_ns("Using RRSet: %p, owner: %p\n", rrset, rrset->owner);
+ dbg_ns_detail("Using RRSet: %p, owner: %p\n", rrset,
+ rrset->owner);
-dbg_ns_exec(
+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);
free(name);
@@ -323,18 +385,16 @@ dbg_ns_exec(
// get the name from the CNAME RDATA
const knot_dname_t *cname = knot_rdata_cname_name(
knot_rrset_rdata(cname_rrset));
- dbg_ns("CNAME name from RDATA: %p\n", cname);
+ dbg_ns_detail("CNAME name from RDATA: %p\n", cname);
// change the node to the node of that name
*node = knot_dname_node(cname);
- dbg_ns("This name's node: %p\n", *node);
-// // it is not an old node and if yes, skip it
-// if (knot_node_is_old(*node)) {
-// *node = knot_node_new_node(*node);
-// }
+ dbg_ns_detail("This name's node: %p\n", *node);
// save the new name which should be used for replacing wildcard
*qname = cname;
- };
+ }
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -350,47 +410,70 @@ dbg_ns_exec(
*
* \return Number of RRSets added.
*/
-static int ns_put_answer(const knot_node_t *node, const knot_dname_t *name,
- uint16_t type, knot_packet_t *resp)
+static int ns_put_answer(const knot_node_t *node,
+ const knot_zone_contents_t *zone,
+ const knot_dname_t *name,
+ uint16_t type, knot_packet_t *resp, int *added,
+ int check_any)
{
- int added = 0;
-dbg_ns_exec(
+ *added = 0;
+dbg_ns_exec_verb(
char *name_str = knot_dname_to_str(node->owner);
- dbg_ns("Putting answers from node %s.\n", name_str);
+ dbg_ns_verb("Putting answers from node %s.\n", name_str);
free(name_str);
);
+ int ret = KNOT_EOK;
+
switch (type) {
case KNOT_RRTYPE_ANY: {
- dbg_ns("Returning all RRTYPES.\n");
+ dbg_ns_verb("Returning all RRTYPES.\n");
+
+ // if ANY not allowed, set TC bit
+ if (check_any && knot_zone_contents_any_disabled(zone)) {
+ knot_response_set_tc(resp);
+ break;
+ }
+
knot_rrset_t **rrsets = knot_node_get_rrsets(node);
if (rrsets == NULL) {
break;
}
int i = 0;
- int ret = 0;
knot_rrset_t *rrset;
while (i < knot_node_rrset_count(node)) {
assert(rrsets[i] != NULL);
rrset = rrsets[i];
- dbg_ns(" Type: %s\n",
+ dbg_ns_detail(" Type: %s\n",
knot_rrtype_to_string(knot_rrset_type(rrset)));
- ns_check_wildcard(name, resp, &rrset);
+ ret = ns_check_wildcard(name, resp, &rrset);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to process wildcard.\n");
+ break;
+ }
+
ret = knot_response_add_rrset_answer(resp, rrset, 1,
0, 0, 1);
- if (ret >= 0 && (added += 1)
- && (ret = ns_add_rrsigs(rrset, resp, name,
- knot_response_add_rrset_answer, 1))
- >=0 ) {
- added += 1;
- } else {
- free(rrsets);
- rrsets = NULL;
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed add Answer RRSet: %s\n",
+ knot_strerror(ret));
+ break;
+ }
+
+ *added += 1;
+
+ ret = ns_add_rrsigs(rrset, resp, name,
+ knot_response_add_rrset_answer, 1);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed add RRSIGs for Answer RRSet: %s"
+ "\n", knot_strerror(ret));
break;
}
+ *added += 1;
+
++i;
}
if (rrsets != NULL) {
@@ -399,7 +482,7 @@ dbg_ns_exec(
break;
}
case KNOT_RRTYPE_RRSIG: {
- dbg_ns("Returning all RRSIGs.\n");
+ dbg_ns_verb("Returning all RRSIGs.\n");
knot_rrset_t **rrsets = knot_node_get_rrsets(node);
if (rrsets == NULL) {
break;
@@ -416,15 +499,21 @@ dbg_ns_exec(
continue;
}
- ns_check_wildcard(name, resp, &rrset);
+ ret = ns_check_wildcard(name, resp, &rrset);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to process wildcard.\n");
+ break;
+ }
+
ret = knot_response_add_rrset_answer(resp, rrset, 1,
0, 0, 1);
-
- if (ret < 0) {
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed add Answer RRSet: %s\n",
+ knot_strerror(ret));
break;
}
- added += 1;
+ *added += 1;
++i;
}
free(rrsets);
@@ -434,23 +523,41 @@ dbg_ns_exec(
int ret = 0;
knot_rrset_t *rrset = knot_node_get_rrset(node, type);
knot_rrset_t *rrset2 = rrset;
- if (rrset != NULL) {
- dbg_ns("Found RRSet of type %s\n",
- knot_rrtype_to_string(type));
- ns_check_wildcard(name, resp, &rrset2);
+ if (rrset != NULL && knot_rrset_rdata(rrset) != NULL) {
+ dbg_ns_verb("Found RRSet of type %s\n",
+ knot_rrtype_to_string(type));
+
+ ret = ns_check_wildcard(name, resp, &rrset2);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to process wildcard.\n");
+ break;
+ }
+
ret = knot_response_add_rrset_answer(resp, rrset2, 1,
0, 0, 1);
- if (ret >= 0 && (added += 1)
- && (ret = ns_add_rrsigs(rrset, resp, name,
- knot_response_add_rrset_answer, 1)) > 0) {
- added += 1;
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed add Answer RRSet: %s\n",
+ knot_strerror(ret));
+ break;
}
+
+ *added += 1;
+
+ ret = ns_add_rrsigs(rrset, resp, name,
+ knot_response_add_rrset_answer, 1);
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed add RRSIGs for Answer RRSet: %s"
+ "\n", knot_strerror(ret));
+ break;
+ }
+
+ *added += 1;
}
}
}
- knot_response_set_rcode(resp, KNOT_RCODE_NOERROR);
- return added;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -471,34 +578,36 @@ dbg_ns_exec(
* \param resp Response where to add the Additional data.
* \param rrset RRSet to get the Additional data for.
*/
-static void ns_put_additional_for_rrset(knot_packet_t *resp,
- const knot_rrset_t *rrset)
+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("Getting name from RDATA, type %s..\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ 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));
+
+dbg_ns_exec_detail(
+ char *name = knot_dname_to_str(dname);
+ dbg_ns_detail("Name: %s\n", name);
+ free(name);
+);
assert(dname != NULL);
node = knot_dname_node(dname);
-// dbg_ns_detail("Node saved in RDATA dname: %p\n", node);
-// char *name = knot_dname_to_str(dname);
-// dbg_ns_detail("Owner of the node: %p, dname: %p (%s)\n",
-// node->owner, dname, name);
-// free(name);
-// knot_node_dump((knot_node_t *)node, (void *)1);
-
+ dbg_ns_detail("Node saved in RDATA dname: %p\n", node);
if (node != NULL && node->owner != dname) {
- // the stored node should be the closest encloser
- assert(knot_dname_is_subdomain(dname, node->owner));
- // try the wildcard child, if any
- node = knot_node_wildcard_child(node);
+ // the stored node should be the wildcard covering the
+ // name
+ dbg_ns_detail("Node is wildcard.\n");
+ assert(knot_dname_is_wildcard(knot_node_owner(node)));
}
knot_rrset_t *rrset_add;
@@ -506,43 +615,90 @@ static void ns_put_additional_for_rrset(knot_packet_t *resp,
if (node != NULL) {
dbg_ns_exec(
char *name = knot_dname_to_str(node->owner);
- dbg_ns("Putting additional from node %s\n", name);
+ dbg_ns_verb("Putting additional from node %s\n", name);
free(name);
);
- dbg_ns("Checking CNAMEs...\n");
- if (knot_node_rrset(node, KNOT_RRTYPE_CNAME)
- != NULL) {
- dbg_ns("Found CNAME in node, following...\n");
+ dbg_ns_detail("Checking CNAMEs...\n");
+ if (knot_node_rrset(node, KNOT_RRTYPE_CNAME) != NULL) {
+ dbg_ns_detail("Found CNAME in node.\n");
const knot_dname_t *dname
= knot_node_owner(node);
- ns_follow_cname(&node, &dname, resp,
+ ret = ns_follow_cname(&node, &dname, resp,
knot_response_add_rrset_additional, 0);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to follow CNAME.\n");
+ return ret;
+ }
}
// A RRSet
- dbg_ns("A RRSets...\n");
+ dbg_ns_detail("A RRSets...\n");
rrset_add = knot_node_get_rrset(node, KNOT_RRTYPE_A);
if (rrset_add != NULL) {
- dbg_ns("Found A RRsets.\n");
+ dbg_ns_detail("Found A RRsets.\n");
knot_rrset_t *rrset_add2 = rrset_add;
- ns_check_wildcard(dname, resp, &rrset_add2);
- knot_response_add_rrset_additional(
+ ret = ns_check_wildcard(dname, resp,
+ &rrset_add2);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to process wildcard for"
+ "Additional section: %s.\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+ ret = knot_response_add_rrset_additional(
resp, rrset_add2, 0, 1, 0, 1);
- ns_add_rrsigs(rrset_add, resp, dname,
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add A RRSet to "
+ "Additional section: %s.\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+ ret = ns_add_rrsigs(rrset_add, resp, dname,
knot_response_add_rrset_additional, 0);
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add RRSIGs for A RR"
+ "Set to Additional section: %s."
+ "\n", knot_strerror(ret));
+ return ret;
+ }
}
// AAAA RRSet
- dbg_ns("AAAA RRSets...\n");
+ dbg_ns_detail("AAAA RRSets...\n");
rrset_add = knot_node_get_rrset(node, KNOT_RRTYPE_AAAA);
if (rrset_add != NULL) {
- dbg_ns("Found AAAA RRsets.\n");
+ dbg_ns_detail("Found AAAA RRsets.\n");
knot_rrset_t *rrset_add2 = rrset_add;
- ns_check_wildcard(dname, resp, &rrset_add2);
- knot_response_add_rrset_additional(
+ ret = ns_check_wildcard(dname, resp,
+ &rrset_add2);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to process wildcard for"
+ "Additional section: %s.\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+ ret = knot_response_add_rrset_additional(
resp, rrset_add2, 0, 1, 0, 1);
- ns_add_rrsigs(rrset_add, resp, dname,
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add AAAA RRSet to "
+ "Additional section.\n");
+ return ret;
+ }
+
+ ret = ns_add_rrsigs(rrset_add, resp, dname,
knot_response_add_rrset_additional, 0);
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add RRSIG for AAAA RR"
+ "Set to Additional section.\n");
+ return ret;
+ }
}
}
@@ -550,6 +706,8 @@ dbg_ns_exec(
assert(rdata != NULL);
rdata = knot_rrset_rdata_next(rrset, rdata);
}
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -580,26 +738,37 @@ static int ns_additional_needed(uint16_t qtype)
*
* \param resp Response to process.
*/
-static void ns_put_additional(knot_packet_t *resp)
+static int ns_put_additional(knot_packet_t *resp)
{
- dbg_ns("ADDITIONAL SECTION PROCESSING\n");
+ dbg_ns_verb("ADDITIONAL SECTION PROCESSING\n");
const knot_rrset_t *rrset = NULL;
+ int ret = 0;
for (int i = 0; i < knot_packet_answer_rrset_count(resp); ++i) {
rrset = knot_packet_answer_rrset(resp, i);
assert(rrset != NULL);
if (ns_additional_needed(knot_rrset_type(rrset))) {
- ns_put_additional_for_rrset(resp, rrset);
+ ret = ns_put_additional_for_rrset(resp, rrset);
+ if (ret != KNOT_EOK) {
+ // if error, do not try to add other RRSets
+ return ret;
+ }
}
}
for (int i = 0; i < knot_packet_authority_rrset_count(resp); ++i) {
rrset = knot_packet_authority_rrset(resp, i);
if (ns_additional_needed(knot_rrset_type(rrset))) {
- ns_put_additional_for_rrset(resp, rrset);
+ ret = ns_put_additional_for_rrset(resp, rrset);
+ if (ret != KNOT_EOK) {
+ // if error, do not try to add other RRSets
+ return ret;
+ }
}
}
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -609,18 +778,35 @@ static void ns_put_additional(knot_packet_t *resp)
* \param zone Zone to take the authority NS RRSet from.
* \param resp Response where to add the RRSet.
*/
-static void ns_put_authority_ns(const knot_zone_contents_t *zone,
+static int ns_put_authority_ns(const knot_zone_contents_t *zone,
knot_packet_t *resp)
{
+ dbg_ns_verb("PUTTING AUTHORITY NS\n");
+
knot_rrset_t *ns_rrset = knot_node_get_rrset(
knot_zone_contents_apex(zone), KNOT_RRTYPE_NS);
if (ns_rrset != NULL) {
- knot_response_add_rrset_authority(resp, ns_rrset, 0, 1, 0, 1);
- ns_add_rrsigs(ns_rrset, resp, knot_node_owner(
+ int ret = knot_response_add_rrset_authority(resp, ns_rrset, 0,
+ 1, 0, 1);
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add Authority NSs to response.\n");
+ return ret;
+ }
+
+ ret = ns_add_rrsigs(ns_rrset, resp, knot_node_owner(
knot_zone_contents_apex(zone)),
- knot_response_add_rrset_authority, 1);
+ knot_response_add_rrset_authority, 1);
+
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add RRSIGs for Authority NSs to "
+ "response.\n");
+ return ret;
+ }
}
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -633,6 +819,8 @@ static void ns_put_authority_ns(const knot_zone_contents_t *zone,
static int ns_put_authority_soa(const knot_zone_contents_t *zone,
knot_packet_t *resp)
{
+ dbg_ns_verb("PUTTING AUTHORITY SOA\n");
+
int ret;
knot_rrset_t *soa_rrset = knot_node_get_rrset(
@@ -644,7 +832,7 @@ static int ns_put_authority_soa(const knot_zone_contents_t *zone,
uint32_t min = knot_rdata_soa_minimum(knot_rrset_rdata(soa_rrset));
if (min < knot_rrset_ttl(soa_rrset)) {
knot_rrset_t *soa_copy = NULL;
- ret = knot_rrset_deep_copy(soa_rrset, &soa_copy);
+ ret = knot_rrset_deep_copy(soa_rrset, &soa_copy, 0);
if (ret != KNOT_EOK) {
return ret;
@@ -655,7 +843,11 @@ static int ns_put_authority_soa(const knot_zone_contents_t *zone,
knot_rrset_set_ttl(soa_copy, min);
soa_rrset = soa_copy;
/* Need to add it as temporary, so it get's freed. */
- knot_packet_add_tmp_rrset(resp, soa_copy);
+ ret = knot_packet_add_tmp_rrset(resp, soa_copy);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&soa_copy, 1, 1, 1);
+ return ret;
+ }
}
assert(soa_rrset != NULL);
@@ -717,20 +909,36 @@ static knot_dname_t *ns_next_closer(const knot_dname_t *closest_encloser,
* \param node Node to get the NSEC3 RRSet from.
* \param resp Response where to add the RRSets.
*/
-static void ns_put_nsec3_from_node(const knot_node_t *node,
+static int ns_put_nsec3_from_node(const knot_node_t *node,
knot_packet_t *resp)
{
assert(DNSSEC_ENABLED
&& knot_query_dnssec_requested(knot_packet_query(resp)));
- knot_rrset_t *rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NSEC3);
- assert(rrset != NULL);
+ knot_rrset_t *rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NSEC3);
+ //assert(rrset != NULL);
- int res = knot_response_add_rrset_authority(resp, rrset, 1, 1, 0, 1);
+ if (rrset == NULL) {
+ // 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);
+ }
// add RRSIG for the RRSet
- if (res == 0 && (rrset = knot_rrset_get_rrsigs(rrset)) != NULL) {
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ 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);
}
+
+ /*! \note TC bit is already set, if something went wrong. */
+
+ // return the error code, so that other code may be skipped
+ return res;
}
/*----------------------------------------------------------------------------*/
@@ -753,31 +961,25 @@ static int ns_put_covering_nsec3(const knot_zone_contents_t *zone,
const knot_node_t *prev, *node;
/*! \todo Check version. */
int match = knot_zone_contents_find_nsec3_for_name(zone, name,
- &node, &prev);
- assert(match >= 0);
-// node = knot_node_current(node);
-// prev = knot_node_current(prev);
+ &node, &prev);
+ //assert(match >= 0);
+ if (match < 0) {
+ // ignoring, what can we do anyway?
+ return KNOT_EOK;
+ }
- if (match == KNOT_ZONE_NAME_FOUND){
- // run-time collision => SERVFAIL
+ if (match == KNOT_ZONE_NAME_FOUND || prev == NULL){
+ // if run-time collision => SERVFAIL
return KNOT_EOK;
}
-// // check if the prev node is not old and if yes, take the new one
-// if (knot_node_is_old(prev)) {
-// prev = knot_node_new_node(prev);
-// assert(prev != NULL);
-// }
-
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(prev->owner);
- dbg_ns("Covering NSEC3 node: %s\n", name);
+ dbg_ns_verb("Covering NSEC3 node: %s\n", name);
free(name);
);
- ns_put_nsec3_from_node(prev, resp);
-
- return KNOT_EOK;
+ return ns_put_nsec3_from_node(prev, resp);
}
/*----------------------------------------------------------------------------*/
@@ -812,19 +1014,24 @@ static int ns_put_nsec3_closest_encloser_proof(
assert(qname != NULL);
assert(resp != NULL);
+ // this function should be called only if NSEC3 is enabled in the zone
+ assert(knot_zone_contents_nsec3params(zone) != NULL);
+
+ dbg_ns_verb("Adding closest encloser proof\n");
+
if (knot_zone_contents_nsec3params(zone) == NULL) {
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(knot_node_owner(
knot_zone_contents_apex(zone)));
- dbg_ns("No NSEC3PARAM found in zone %s.\n", name);
+ dbg_ns_verb("No NSEC3PARAM found in zone %s.\n", name);
free(name);
);
return KNOT_EOK;
}
-dbg_ns_exec(
+dbg_ns_exec_detail(
char *name = knot_dname_to_str(knot_node_owner(*closest_encloser));
- dbg_ns("Closest encloser: %s\n", name);
+ dbg_ns_detail("Closest encloser: %s\n", name);
free(name);
);
@@ -845,28 +1052,30 @@ dbg_ns_exec(
assert(nsec3_node != NULL);
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(nsec3_node->owner);
- dbg_ns("NSEC3 node: %s\n", name);
+ dbg_ns_verb("NSEC3 node: %s\n", name);
free(name);
name = knot_dname_to_str((*closest_encloser)->owner);
- dbg_ns("Closest provable encloser: %s\n", name);
+ dbg_ns_verb("Closest provable encloser: %s\n", name);
free(name);
if (next_closer != NULL) {
name = knot_dname_to_str(next_closer);
- dbg_ns("Next closer name: %s\n", name);
+ dbg_ns_verb("Next closer name: %s\n", name);
free(name);
} else {
- dbg_ns("Next closer name: none\n");
+ dbg_ns_verb("Next closer name: none\n");
}
);
- ns_put_nsec3_from_node(nsec3_node, resp);
+ int ret = ns_put_nsec3_from_node(nsec3_node, resp);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
/*
* 2) NSEC3 that covers the "next closer" name.
*/
- int ret = 0;
if (next_closer == NULL) {
// create the "next closer" name by appending from qname
next_closer = ns_next_closer(
@@ -875,9 +1084,9 @@ dbg_ns_exec(
if (next_closer == NULL) {
return NS_ERR_SERVFAIL;
}
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(next_closer);
- dbg_ns("Next closer name: %s\n", name);
+ dbg_ns_verb("Next closer name: %s\n", name);
free(name);
);
ret = ns_put_covering_nsec3(zone, next_closer, resp);
@@ -914,9 +1123,9 @@ static knot_dname_t *ns_wildcard_child_name(const knot_dname_t *name)
return NULL;
}
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(wildcard);
- dbg_ns("Wildcard: %s\n", name);
+ dbg_ns_verb("Wildcard: %s\n", name);
free(name);
);
return wildcard;
@@ -971,26 +1180,55 @@ static int ns_put_nsec3_no_wildcard_child(const knot_zone_contents_t *zone,
* RRSets of the requested type).
* \param resp Response where to add the NSECs or NSEC3s.
*/
-static void ns_put_nsec_nsec3_nodata(const knot_node_t *node,
- knot_packet_t *resp)
+static int ns_put_nsec_nsec3_nodata(const knot_zone_contents_t *zone,
+ const knot_node_t *node,
+ knot_packet_t *resp)
{
if (!DNSSEC_ENABLED ||
!knot_query_dnssec_requested(knot_packet_query(resp))) {
- return;
+ return KNOT_EOK;
}
- knot_node_t *nsec3_node = knot_node_get_nsec3_node(node);
+ /*! \todo Maybe distinguish different errors. */
+ int ret = KNOT_ERROR;
+
knot_rrset_t *rrset = NULL;
- if ((rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NSEC)) != NULL
- || (nsec3_node != NULL && (rrset =
- knot_node_get_rrset(nsec3_node, KNOT_RRTYPE_NSEC3)) != NULL)) {
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
- // add RRSIG for the RRSet
- if ((rrset = knot_rrset_get_rrsigs(rrset)) != NULL) {
- knot_response_add_rrset_authority(resp, rrset, 1,
- 0, 0, 1);
+
+ if (knot_zone_contents_nsec3_enabled(zone)) {
+ knot_node_t *nsec3_node = knot_node_get_nsec3_node(node);
+ dbg_ns_verb("Adding NSEC3 for NODATA, NSEC3 node: %p\n",
+ nsec3_node);
+
+ if (nsec3_node != NULL
+ && (rrset = knot_node_get_rrset(nsec3_node,
+ KNOT_RRTYPE_NSEC3)) != NULL
+ && knot_rrset_rdata(rrset) != NULL) {
+ dbg_ns_detail("Putting the RRSet to Authority\n");
+ ret = knot_response_add_rrset_authority(resp, rrset, 1,
+ 0, 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) {
+ dbg_ns_detail("Putting the RRSet to Authority\n");
+ ret = knot_response_add_rrset_authority(resp, rrset, 1,
+ 0, 0, 1);
+ }
+ }
+
+ if (ret != KNOT_EOK) {
+ return ret;
}
+
+ 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);
+ }
+
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -1030,9 +1268,11 @@ static int ns_put_nsec_nxdomain(const knot_dname_t *qname,
}
}
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(previous->owner);
- dbg_ns("Previous node: %s\n", name);
+ dbg_ns_verb("Previous node: %s\n", name);
free(name);
+);
// 1) NSEC proving that there is no node with the searched name
rrset = knot_node_get_rrset(previous, KNOT_RRTYPE_NSEC);
@@ -1043,11 +1283,21 @@ static int ns_put_nsec_nxdomain(const knot_dname_t *qname,
}
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ int ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add NSEC for NXDOMAIN to response: %s\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
rrset = knot_rrset_get_rrsigs(rrset);
assert(rrset != NULL);
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
-
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add RRSIGs for NSEC for NXDOMAIN to response:"
+ "%s\n", knot_strerror(ret));
+ return ret;
+ }
// 2) NSEC proving that there is no wildcard covering the name
// this is only different from 1) if the wildcard would be
// before 'previous' in canonical order, i.e. we can
@@ -1064,9 +1314,9 @@ static int ns_put_nsec_nxdomain(const knot_dname_t *qname,
while (knot_dname_compare(knot_node_owner(prev_new),
wildcard) > 0) {
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(knot_node_owner(prev_new));
- dbg_ns("Previous node: %s\n", name);
+ dbg_ns_verb("Previous node: %s\n", name);
free(name);
);
assert(prev_new != knot_zone_contents_apex(zone));
@@ -1075,9 +1325,9 @@ dbg_ns_exec(
assert(knot_dname_compare(knot_node_owner(prev_new),
wildcard) < 0);
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(knot_node_owner(prev_new));
- dbg_ns("Previous node: %s\n", name);
+ dbg_ns_verb("Previous node: %s\n", name);
free(name);
);
@@ -1086,11 +1336,27 @@ dbg_ns_exec(
if (prev_new != previous) {
rrset = knot_node_get_rrset(prev_new, KNOT_RRTYPE_NSEC);
- assert(rrset != NULL);
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ if (rrset == NULL || knot_rrset_rdata(rrset) == NULL) {
+ // bad zone, ignore
+ return KNOT_EOK;
+ }
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 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);
- assert(rrset != NULL);
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ if (rrset == NULL || knot_rrset_rdata(rrset) == NULL) {
+ // bad zone, ignore
+ return KNOT_EOK;
+ }
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed to add RRSIGs for second NSEC for "
+ "NXDOMAIN to response: %s\n", knot_strerror(ret));
+ return ret;
+ }
}
return KNOT_EOK;
@@ -1118,13 +1384,12 @@ static int ns_put_nsec3_nxdomain(const knot_zone_contents_t *zone,
knot_packet_t *resp)
{
// 1) Closest encloser proof
- dbg_ns("Putting closest encloser proof.\n");
int ret = ns_put_nsec3_closest_encloser_proof(zone, &closest_encloser,
qname, resp);
// 2) NSEC3 covering non-existent wildcard
if (ret == KNOT_EOK && closest_encloser != NULL) {
- dbg_ns("Putting NSEC3 for no wildcard child of closest "
- "encloser.\n");
+ dbg_ns_verb("Putting NSEC3 for no wildcard child of closest "
+ "encloser.\n");
ret = ns_put_nsec3_no_wildcard_child(zone, closest_encloser,
resp);
}
@@ -1207,16 +1472,16 @@ static int ns_put_nsec3_wildcard(const knot_zone_contents_t *zone,
* NSEC3 that covers the "next closer" name.
*/
// create the "next closer" name by appending from qname
- dbg_ns("Finding next closer name for wildcard NSEC3.\n");
+ dbg_ns_verb("Finding next closer name for wildcard NSEC3.\n");
knot_dname_t *next_closer =
ns_next_closer(closest_encloser->owner, qname);
if (next_closer == NULL) {
return NS_ERR_SERVFAIL;
}
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(next_closer);
- dbg_ns("Next closer name: %s\n", name);
+ dbg_ns_verb("Next closer name: %s\n", name);
free(name);
);
int ret = ns_put_covering_nsec3(zone, next_closer, resp);
@@ -1241,10 +1506,10 @@ dbg_ns_exec(
* \param previous Previous node of \a qname in canonical order.
* \param resp Response to put the NSEC3s into.
*/
-static void ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
- const knot_dname_t *qname,
- const knot_node_t *previous,
- knot_packet_t *resp)
+static int ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
+ const knot_dname_t *qname,
+ const knot_node_t *previous,
+ knot_packet_t *resp)
{
assert(DNSSEC_ENABLED
&& knot_query_dnssec_requested(knot_packet_query(resp)));
@@ -1261,13 +1526,22 @@ static void ns_put_nsec_wildcard(const knot_zone_contents_t *zone,
knot_rrset_t *rrset =
knot_node_get_rrset(previous, KNOT_RRTYPE_NSEC);
- if (rrset != NULL) {
+
+ int ret = KNOT_EOK;
+
+ if (rrset != NULL && knot_rrset_rdata(rrset) != NULL) {
// NSEC proving that there is no node with the searched name
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
- rrset = knot_rrset_get_rrsigs(rrset);
- assert(rrset != NULL);
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0,
+ 0, 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);
+ }
}
+
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -1306,10 +1580,10 @@ static int ns_put_nsec_nsec3_wildcard_nodata(const knot_node_t *node,
if (ret == KNOT_EOK
&& (nsec3_node = knot_node_nsec3_node(node))
!= NULL) {
- ns_put_nsec3_from_node(nsec3_node, resp);
+ ret = ns_put_nsec3_from_node(nsec3_node, resp);
}
} else {
- ns_put_nsec_wildcard(zone, qname, previous, resp);
+ ret = ns_put_nsec_wildcard(zone, qname, previous, resp);
}
}
return ret;
@@ -1339,18 +1613,18 @@ static int ns_put_nsec_nsec3_wildcard_answer(const knot_node_t *node,
const knot_dname_t *qname,
knot_packet_t *resp)
{
- int r = KNOT_EOK;
+ int ret = KNOT_EOK;
if (DNSSEC_ENABLED
&& knot_query_dnssec_requested(knot_packet_query(resp))
&& knot_dname_is_wildcard(knot_node_owner(node))) {
if (knot_zone_contents_nsec3_enabled(zone)) {
- r = ns_put_nsec3_wildcard(zone, closest_encloser, qname,
- resp);
+ ret = ns_put_nsec3_wildcard(zone, closest_encloser,
+ qname, resp);
} else {
- ns_put_nsec_wildcard(zone, qname, previous, resp);
+ ret = ns_put_nsec_wildcard(zone, qname, previous, resp);
}
}
- return r;
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -1403,26 +1677,27 @@ static inline int ns_referral(const knot_node_t *node,
knot_packet_t *resp,
uint16_t qtype)
{
- dbg_ns("Referral response.\n");
+ dbg_ns_verb("Referral response.\n");
while (!knot_node_is_deleg_point(node)) {
assert(knot_node_parent(node) != NULL);
node = knot_node_parent(node);
}
+ int ret = KNOT_EOK;
+
// Special handling of DS queries
if (qtype == KNOT_RRTYPE_DS) {
knot_rrset_t *ds_rrset = knot_node_get_rrset(node,
KNOT_RRTYPE_DS);
- int ret = KNOT_EOK;
if (ds_rrset) {
- knot_response_add_rrset_answer(resp, ds_rrset, 1, 0,
- 0, 1);
- if (DNSSEC_ENABLED
+ ret = knot_response_add_rrset_answer(resp, ds_rrset, 1,
+ 0, 0, 1);
+ if (ret == KNOT_EOK && DNSSEC_ENABLED
&& knot_query_dnssec_requested(
knot_packet_query(resp))) {
- ns_add_rrsigs(ds_rrset, resp, node->owner,
+ ret = ns_add_rrsigs(ds_rrset, resp, node->owner,
knot_response_add_rrset_authority,
1);
}
@@ -1430,18 +1705,13 @@ static inline int ns_referral(const knot_node_t *node,
// normal NODATA response
/*! \todo Handle in some generic way. */
- dbg_ns("Adding NSEC/NSEC3 for NODATA.\n");
- ns_put_nsec_nsec3_nodata(node, resp);
+ dbg_ns_verb("Adding NSEC/NSEC3 for NODATA.\n");
+ ret = ns_put_nsec_nsec3_nodata(zone, node, resp);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
- // wildcard delegations not supported!
-// if (knot_dname_is_wildcard(node->owner)) {
-// dbg_ns("Putting NSEC/NSEC3 for wildcard"
-// " NODATA\n");
-// ret = ns_put_nsec_nsec3_wildcard_nodata(node,
-// closest_encloser, previous, zone, qname,
-// resp);
-// }
- ns_put_authority_soa(zone, resp);
+ ret = ns_put_authority_soa(zone, resp);
}
return ret;
@@ -1449,39 +1719,42 @@ static inline int ns_referral(const knot_node_t *node,
knot_rrset_t *rrset = knot_node_get_rrset(node, KNOT_RRTYPE_NS);
assert(rrset != NULL);
-
- // TODO: wildcards??
- //ns_check_wildcard(name, resp, &rrset);
- knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
- ns_add_rrsigs(rrset, resp, node->owner,
- knot_response_add_rrset_authority, 1);
+ ret = knot_response_add_rrset_authority(resp, rrset, 1, 0, 0, 1);
+ if (ret == KNOT_EOK) {
+ ret = ns_add_rrsigs(rrset, resp, node->owner,
+ knot_response_add_rrset_authority, 1);
+ }
- int ret = KNOT_EOK;
// add DS records
- dbg_ns("DNSSEC requested: %d\n",
+ dbg_ns_verb("DNSSEC requested: %d\n",
knot_query_dnssec_requested(knot_packet_query(resp)));
- dbg_ns("DS records: %p\n", knot_node_rrset(node, KNOT_RRTYPE_DS));
- if (DNSSEC_ENABLED
+ dbg_ns_verb("DS records: %p\n", knot_node_rrset(node, KNOT_RRTYPE_DS));
+ if (ret == KNOT_EOK && DNSSEC_ENABLED
&& knot_query_dnssec_requested(knot_packet_query(resp))) {
rrset = knot_node_get_rrset(node, KNOT_RRTYPE_DS);
if (rrset != NULL) {
- knot_response_add_rrset_authority(resp, rrset, 1, 0,
- 0, 1);
- ns_add_rrsigs(rrset, resp, node->owner,
- knot_response_add_rrset_authority, 1);
+ ret = knot_response_add_rrset_authority(resp, rrset, 1,
+ 0, 0, 1);
+ if (ret == KNOT_EOK) {
+ ret = ns_add_rrsigs(rrset, resp, node->owner,
+ knot_response_add_rrset_authority, 1);
+ }
} else {
// no DS, add NSEC3 or NSEC
// if NSEC3 enabled, search for NSEC3
if (knot_zone_contents_nsec3_enabled(zone)) {
const knot_node_t *nsec3_node =
knot_node_nsec3_node(node);
- dbg_ns("There is no DS, putting NSEC3s...\n");
+ dbg_ns_detail("There is no DS, putting NSEC3s."
+ "\n");
if (nsec3_node != NULL) {
- dbg_ns("Putting NSEC3s from the node.\n");
- ns_put_nsec3_from_node(nsec3_node, resp);
+ dbg_ns_detail("Putting NSEC3s from the node.\n");
+ ret = ns_put_nsec3_from_node(nsec3_node,
+ resp);
} else {
- dbg_ns("Putting Opt-Out NSEC3s.\n");
+ dbg_ns_detail("Putting Opt-Out NSEC3s."
+ "\n");
// no NSEC3 (probably Opt-Out)
// TODO: check if the zone is Opt-Out
ret = ns_put_nsec3_closest_encloser_proof(zone,
@@ -1492,10 +1765,11 @@ static inline int ns_referral(const knot_node_t *node,
node, KNOT_RRTYPE_NSEC);
if (nsec) {
/*! \todo Check return value? */
- knot_response_add_rrset_authority(
+ ret = knot_response_add_rrset_authority(
resp, nsec, 1, 1, 0, 1);
- if ((nsec = knot_rrset_get_rrsigs(nsec)) != NULL) {
- knot_response_add_rrset_authority(
+ if (ret == KNOT_EOK &&
+ (nsec = knot_rrset_get_rrsigs(nsec)) != NULL) {
+ ret = knot_response_add_rrset_authority(
resp, nsec, 1, 1, 0, 1);
}
}
@@ -1503,10 +1777,13 @@ static inline int ns_referral(const knot_node_t *node,
}
}
- if (ret == KNOT_EOK) {
-// ns_put_additional(resp);
+ if (ret == KNOT_ESPACE) {
+ knot_response_set_rcode(resp, KNOT_RCODE_NOERROR);
+ ret = KNOT_EOK;
+ } else if (ret == KNOT_EOK) {
knot_response_set_rcode(resp, KNOT_RCODE_NOERROR);
}
+
return ret;
}
@@ -1540,65 +1817,65 @@ static int ns_answer_from_node(const knot_node_t *node,
const knot_node_t *previous,
const knot_zone_contents_t *zone,
const knot_dname_t *qname, uint16_t qtype,
- knot_packet_t *resp)
+ knot_packet_t *resp, int check_any)
{
- dbg_ns("Putting answers from found node to the response...\n");
- int answers = ns_put_answer(node, qname, qtype, resp);
+ dbg_ns_verb("Putting answers from found node to the response...\n");
+ int answers = 0;
+
+ int ret = ns_put_answer(node, zone, qname, qtype, resp, &answers,
+ check_any);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ assert(ret == KNOT_EOK);
- int ret = KNOT_EOK;
if (answers == 0) { // if NODATA response, put SOA
+ ret = ns_put_authority_soa(zone, resp);
if (knot_node_rrset_count(node) == 0
&& !knot_zone_contents_nsec3_enabled(zone)) {
// node is an empty non-terminal => NSEC for NXDOMAIN
//assert(knot_node_rrset_count(closest_encloser) > 0);
- dbg_ns("Adding NSEC/NSEC3 for NXDOMAIN.\n");
+ dbg_ns_verb("Adding NSEC/NSEC3 for NXDOMAIN.\n");
ret = ns_put_nsec_nsec3_nxdomain(zone,
knot_node_previous(node), closest_encloser,
qname, resp);
} else {
- dbg_ns("Adding NSEC/NSEC3 for NODATA.\n");
- ns_put_nsec_nsec3_nodata(node, resp);
+ dbg_ns_verb("Adding NSEC/NSEC3 for NODATA.\n");
+ ret = ns_put_nsec_nsec3_nodata(zone, node, resp);
+ if (ret != KNOT_EOK) {
+ dbg_ns("Failed adding NSEC/NSEC3 for NODATA: %s"
+ "\n", knot_strerror(ret));
+ return ret;
+ }
+
if (knot_dname_is_wildcard(node->owner)) {
- dbg_ns("Putting NSEC/NSEC3 for wildcard"
- " NODATA\n");
+ dbg_ns_verb("Putting NSEC/NSEC3 for wildcard"
+ " NODATA\n");
ret = ns_put_nsec_nsec3_wildcard_nodata(node,
closest_encloser, previous, zone, qname,
resp);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
}
}
- ns_put_authority_soa(zone, resp);
} else { // else put authority NS
// if wildcard answer, add NSEC / NSEC3
- dbg_ns("Adding NSEC/NSEC3 for wildcard answer.\n");
-
-// char *n = knot_dname_to_str(knot_node_owner(node));
-// char *ce = (closest_encloser)
-// ? knot_dname_to_str(knot_node_owner(closest_encloser))
-// : "(nil)";
-// char *prev = (previous)
-// ? knot_dname_to_str(knot_node_owner(previous))
-// : "(nil)";
-// printf("Node: %s, closest encloser: %s, previous: %s\n",
-// n, ce, prev);
-// free(n);
-// if (closest_encloser) {
-// free(ce);
-// }
-// if (previous) {
-// free(prev);
-// }
+ dbg_ns_verb("Adding NSEC/NSEC3 for wildcard answer.\n");
+
assert(previous == NULL);
assert(closest_encloser == knot_node_parent(node)
|| !knot_dname_is_wildcard(knot_node_owner(node)));
ret = ns_put_nsec_nsec3_wildcard_answer(node, closest_encloser,
previous, zone, qname, resp);
- ns_put_authority_ns(zone, resp);
+
+ if (ret == KNOT_EOK) {
+ ret = ns_put_authority_ns(zone, resp);
+ }
}
-// if (ret == KNOT_EOK) {
-// ns_put_additional(resp);
-// }
return ret;
}
@@ -1617,7 +1894,7 @@ static int ns_answer_from_node(const knot_node_t *node,
static knot_rrset_t *ns_cname_from_dname(const knot_rrset_t *dname_rrset,
const knot_dname_t *qname)
{
- dbg_ns("Synthetizing CNAME from DNAME...\n");
+ dbg_ns_verb("Synthetizing CNAME from DNAME...\n");
// create new CNAME RRSet
@@ -1642,15 +1919,25 @@ static knot_rrset_t *ns_cname_from_dname(const knot_rrset_t *dname_rrset,
knot_rdata_get_item(knot_rrset_rdata(dname_rrset), 0)->dname);
dbg_ns_exec(
char *name = knot_dname_to_str(cname);
- dbg_ns("CNAME canonical name: %s.\n", name);
+ 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;
- knot_rdata_set_items(cname_rdata, &cname_rdata_item, 1);
+ 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);
+ return NULL;
+ }
- knot_rrset_add_rdata(cname_rrset, cname_rdata);
+ 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;
+ }
return cname_rrset;
}
@@ -1694,38 +1981,59 @@ static int ns_dname_is_too_long(const knot_rrset_t *dname_rrset,
* \param qname Searched name.
* \param resp Response.
*/
-static void ns_process_dname(knot_rrset_t *dname_rrset,
- const knot_dname_t *qname,
+static int ns_process_dname(knot_rrset_t *dname_rrset,
+ const knot_dname_t **qname,
knot_packet_t *resp)
{
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(dname_rrset));
- dbg_ns("Processing DNAME for owner %s...\n", name);
+ dbg_ns_verb("Processing DNAME for owner %s...\n", name);
free(name);
);
// TODO: check the number of RRs in the RRSet??
// put the DNAME RRSet into the answer
- knot_response_add_rrset_answer(resp, dname_rrset, 1, 0, 0, 1);
- ns_add_rrsigs(dname_rrset, resp, qname,
- knot_response_add_rrset_answer, 1);
+ int ret = knot_response_add_rrset_answer(resp, dname_rrset, 1, 0, 0, 1);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
- if (ns_dname_is_too_long(dname_rrset, qname)) {
+ ret = ns_add_rrsigs(dname_rrset, resp, *qname,
+ knot_response_add_rrset_answer, 1);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ if (ns_dname_is_too_long(dname_rrset, *qname)) {
knot_response_set_rcode(resp, KNOT_RCODE_YXDOMAIN);
- return;
+ return KNOT_EOK;
}
// synthetize CNAME (no way to tell that client supports DNAME)
- knot_rrset_t *synth_cname = ns_cname_from_dname(dname_rrset, qname);
+ knot_rrset_t *synth_cname = ns_cname_from_dname(dname_rrset, *qname);
// add the synthetized RRSet to the Answer
- knot_response_add_rrset_answer(resp, synth_cname, 1, 0, 0, 1);
+ ret = knot_response_add_rrset_answer(resp, synth_cname, 1, 0, 0, 1);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
// no RRSIGs for this RRSet
// add the synthetized RRSet into list of temporary RRSets of response
- knot_packet_add_tmp_rrset(resp, synth_cname);
+ ret = knot_packet_add_tmp_rrset(resp, synth_cname);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ // get the next SNAME from the CNAME RDATA
+ const knot_dname_t *cname = knot_rdata_cname_name(
+ knot_rrset_rdata(synth_cname));
+ dbg_ns_verb("CNAME name from RDATA: %p\n", cname);
- // do not search for the name in new zone (out-of-bailiwick)
+ // save the new name which should be used for replacing wildcard
+ *qname = cname;
+
+ return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
@@ -1735,15 +2043,23 @@ dbg_ns_exec(
* \param apex Zone apex node.
* \param resp Response.
*/
-static void ns_add_dnskey(const knot_node_t *apex, knot_packet_t *resp)
+static int ns_add_dnskey(const knot_node_t *apex, knot_packet_t *resp)
{
knot_rrset_t *rrset =
knot_node_get_rrset(apex, KNOT_RRTYPE_DNSKEY);
+
+ int ret = KNOT_EOK;
+
if (rrset != NULL) {
- knot_response_add_rrset_additional(resp, rrset, 0, 0, 0, 1);
- ns_add_rrsigs(rrset, resp, apex->owner,
- knot_response_add_rrset_additional, 0);
+ ret = knot_response_add_rrset_additional(resp, rrset, 0, 0,
+ 0, 1);
+ if (ret == KNOT_EOK) {
+ ret = ns_add_rrsigs(rrset, resp, apex->owner,
+ knot_response_add_rrset_additional, 0);
+ }
}
+
+ return ret;
}
/*----------------------------------------------------------------------------*/
@@ -1763,7 +2079,7 @@ static void ns_add_dnskey(const knot_node_t *apex, knot_packet_t *resp)
* \todo Describe the answering logic in detail.
*/
static int ns_answer_from_zone(const knot_zone_contents_t *zone,
- knot_packet_t *resp)
+ knot_packet_t *resp, int check_any)
{
const knot_node_t *node = NULL, *closest_encloser = NULL,
*previous = NULL;
@@ -1774,13 +2090,9 @@ static int ns_answer_from_zone(const knot_zone_contents_t *zone,
search:
#ifdef USE_HASH_TABLE
- /*! \todo Check version. */
find_ret = knot_zone_contents_find_dname_hash(zone, qname, &node,
&closest_encloser);
-// node = knot_node_current(node);
-// closest_encloser = knot_node_current(closest_encloser);
#else
- /*! \todo Check version. */
find_ret = knot_zone_contents_find_dname(zone, qname, &node,
&closest_encloser, &previous);
node = knot_node_current(node);
@@ -1791,33 +2103,33 @@ search:
return NS_ERR_SERVFAIL;
}
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name;
if (node) {
name = knot_dname_to_str(node->owner);
- dbg_ns("zone_find_dname() returned node %s \n", name);
+ dbg_ns_verb("zone_find_dname() returned node %s \n", name);
free(name);
} else {
- dbg_ns("zone_find_dname() returned no node,\n");
+ dbg_ns_verb("zone_find_dname() returned no node,\n");
}
if (closest_encloser != NULL) {
name = knot_dname_to_str(closest_encloser->owner);
- dbg_ns(" closest encloser %s.\n", name);
+ dbg_ns_verb(" closest encloser %s.\n", name);
free(name);
} else {
- dbg_ns(" closest encloser (nil).\n");
+ dbg_ns_verb(" closest encloser (nil).\n");
}
if (previous != NULL) {
name = knot_dname_to_str(previous->owner);
- dbg_ns(" and previous node: %s.\n", name);
+ dbg_ns_verb(" and previous node: %s.\n", name);
free(name);
} else {
- dbg_ns(" and previous node: (nil).\n");
+ dbg_ns_verb(" and previous node: (nil).\n");
}
);
if (find_ret == KNOT_EBADZONE) {
- // possible only if we followed cname
+ // possible only if we followed CNAME or DNAME
assert(cname != 0);
knot_response_set_rcode(resp, KNOT_RCODE_NOERROR);
auth_soa = 1;
@@ -1826,10 +2138,10 @@ dbg_ns_exec(
}
have_node:
- dbg_ns("Closest encloser is deleg. point? %s\n",
+ dbg_ns_verb("Closest encloser is deleg. point? %s\n",
(knot_node_is_deleg_point(closest_encloser)) ? "yes" : "no");
- dbg_ns("Closest encloser is non authoritative? %s\n",
+ dbg_ns_verb("Closest encloser is non authoritative? %s\n",
(knot_node_is_non_auth(closest_encloser)) ? "yes" : "no");
if (knot_node_is_deleg_point(closest_encloser)
@@ -1843,21 +2155,31 @@ have_node:
knot_rrset_t *dname_rrset = knot_node_get_rrset(
closest_encloser, KNOT_RRTYPE_DNAME);
if (dname_rrset != NULL) {
- ns_process_dname(dname_rrset, qname, resp);
- auth_soa = 1;
+ ret = ns_process_dname(dname_rrset, &qname, resp);
+
knot_response_set_aa(resp);
- goto finalize;
+
+ if (ret != KNOT_EOK) {
+ goto finalize;
+ }
+
+ // do not search for the name in new zone
+ // (out-of-bailiwick), just in the current zone if it
+ // belongs there
+
+ cname = 1;
+ goto search;
}
// else check for a wildcard child
const knot_node_t *wildcard_node =
knot_node_wildcard_child(closest_encloser);
if (wildcard_node == NULL) {
- dbg_ns("No wildcard node. (cname: %d)\n",
- cname);
+ dbg_ns_verb("No wildcard node. (cname: %d)\n",
+ cname);
auth_soa = 1;
if (cname == 0) {
- dbg_ns("Setting NXDOMAIN RCODE.\n");
+ dbg_ns_detail("Setting NXDOMAIN RCODE.\n");
// return NXDOMAIN
knot_response_set_rcode(resp,
KNOT_RCODE_NXDOMAIN);
@@ -1884,24 +2206,31 @@ have_node:
}
if (knot_node_rrset(node, KNOT_RRTYPE_CNAME) != NULL
- && qtype != KNOT_RRTYPE_CNAME) {
+ && qtype != KNOT_RRTYPE_CNAME && qtype != KNOT_RRTYPE_RRSIG) {
dbg_ns_exec(
char *name = knot_dname_to_str(node->owner);
- dbg_ns("Node %s has CNAME record, resolving...\n",
- name);
+ dbg_ns_verb("Node %s has CNAME record, resolving...\n", name);
free(name);
);
const knot_dname_t *act_name = qname;
- ns_follow_cname(&node, &act_name, resp,
- knot_response_add_rrset_answer, 1);
-dbg_ns_exec(
+ ret = ns_follow_cname(&node, &act_name, resp,
+ knot_response_add_rrset_answer, 1);
+
+ /*! \todo IS OK??? */
+ knot_response_set_aa(resp);
+
+ if (ret != KNOT_EOK) {
+ // KNOT_ESPACE case is handled there
+ goto finalize;
+ }
+dbg_ns_exec_verb(
char *name = (node != NULL) ? knot_dname_to_str(node->owner)
: "(nil)";
char *name2 = knot_dname_to_str(act_name);
- dbg_ns("Canonical name: %s (%p), node found: %p\n",
- name2, act_name, node);
- dbg_ns("The node's owner: %s (%p)\n", name, (node != NULL)
- ? node->owner : NULL);
+ dbg_ns_verb("Canonical name: %s (%p), node found: %p\n",
+ name2, act_name, node);
+ dbg_ns_verb("The node's owner: %s (%p)\n", name, (node != NULL)
+ ? node->owner : NULL);
if (node != NULL) {
free(name);
}
@@ -1913,25 +2242,33 @@ dbg_ns_exec(
// otherwise search for the new name
if (node == NULL) {
goto search;
- } else if (node->owner != act_name) {
- // the stored node is closest encloser
- find_ret = KNOT_ZONE_NAME_NOT_FOUND;
- closest_encloser = node;
- node = NULL;
- goto have_node;
- } // else do nothing, just continue
+ } else if (knot_node_owner(node) != act_name) {
+ if(knot_dname_is_wildcard(knot_node_owner(node))) {
+ // we must set the closest encloser to the
+ // parent of the node, to be right
+ closest_encloser = knot_node_parent(node);
+ assert(closest_encloser != NULL);
+ } else {
+ // the stored node is closest encloser
+ find_ret = KNOT_ZONE_NAME_NOT_FOUND;
+ closest_encloser = node;
+ node = NULL;
+ goto have_node;
+ }
+ }
}
ret = ns_answer_from_node(node, closest_encloser, previous, zone, qname,
- qtype, resp);
+ qtype, resp, check_any);
if (ret == NS_ERR_SERVFAIL) {
// in this case we should drop the response and send an error
// for now, just send the error code with a non-complete answer
-// knot_response_set_rcode(resp, KNOT_RCODE_SERVFAIL);
-// goto finalize;
return ret;
} else if (ret != KNOT_EOK) {
/*! \todo Handle RCODE return values!!! */
+ // In case ret == KNOT_ESPACE, this is later converted to EOK
+ // so it does not cause error response
+ knot_response_set_aa(resp);
goto finalize;
}
knot_response_set_aa(resp);
@@ -1940,16 +2277,21 @@ dbg_ns_exec(
// this is the only case when the servers answers from
// particular node, i.e. the only case when it may return SOA
// or NS records in Answer section
- if (DNSSEC_ENABLED
+ if (knot_packet_tc(resp) == 0 && DNSSEC_ENABLED
&& knot_query_dnssec_requested(knot_packet_query(resp))
&& node == knot_zone_contents_apex(zone)
&& (qtype == KNOT_RRTYPE_SOA || qtype == KNOT_RRTYPE_NS)) {
- ns_add_dnskey(node, resp);
+ ret = ns_add_dnskey(node, resp);
}
finalize:
- if (ret == KNOT_EOK && auth_soa) {
- ns_put_authority_soa(zone, resp);
+ if (ret == KNOT_EOK && knot_packet_tc(resp) == 0 && auth_soa) {
+ ret = ns_put_authority_soa(zone, resp);
+ }
+
+ if (ret == KNOT_ESPACE) {
+ knot_response_set_rcode(resp, KNOT_RCODE_NOERROR);
+ ret = KNOT_EOK;
}
// add all missing NSECs/NSEC3s for wildcard nodes
@@ -1976,20 +2318,9 @@ finalize:
* \retval KNOT_EOK
* \retval NS_ERR_SERVFAIL
*/
-static int ns_answer(const knot_zone_t *zone, knot_packet_t *resp)
-{
-// const knot_dname_t *qname = knot_packet_qname(resp);
-// assert(qname != NULL);
-
-// uint16_t qtype = knot_packet_qtype(resp);
-//dbg_ns_exec(
-// char *name_str = knot_dname_to_str(qname);
-// dbg_ns("Trying to find zone for QNAME %s\n", name_str);
-// free(name_str);
-//);
-// // find zone in which to search for the name
-// const knot_zone_t *zone =
-// ns_get_zone_for_qname(db, qname, qtype);
+static int ns_answer(const knot_zone_t *zone, knot_packet_t *resp,
+ int check_any)
+{
const knot_zone_contents_t *contents = knot_zone_contents(zone);
// if no zone found, return REFUSED
@@ -2012,9 +2343,7 @@ dbg_ns_exec(
// take the zone contents and use only them for answering
- return ns_answer_from_zone(contents, resp);
-
- //knot_dname_free(&qname);
+ return ns_answer_from_zone(contents, resp, check_any);
}
/*----------------------------------------------------------------------------*/
@@ -2026,10 +2355,9 @@ int ns_response_to_wire(knot_packet_t *resp, uint8_t *wire,
size_t rsize = 0;
int ret = 0;
- if ((ret = knot_packet_to_wire(resp, &rwire, &rsize))
- != KNOT_EOK) {
+ if ((ret = knot_packet_to_wire(resp, &rwire, &rsize)) != KNOT_EOK) {
dbg_ns("Error converting response packet "
- "to wire format (error %d).\n", ret);
+ "to wire format (error %d).\n", ret);
return NS_ERR_SERVFAIL;
}
@@ -2041,14 +2369,13 @@ int ns_response_to_wire(knot_packet_t *resp, uint8_t *wire,
if (rwire != wire) {
dbg_ns("Wire format reallocated, copying to place for "
- "wire.\n");
+ "wire.\n");
memcpy(wire, rwire, rsize);
} else {
dbg_ns("Using the same space or wire format.\n");
}
*wire_size = rsize;
- //free(rwire);
return KNOT_EOK;
}
@@ -2073,17 +2400,17 @@ static int ns_error_response_to_wire(knot_packet_t *resp, uint8_t *wire,
* wire format is assembled, but COUNTs in header are not set.
* This is ideal, we just truncate the packet after the question.
*/
- dbg_ns("Creating error response.\n");
+ dbg_ns_verb("Creating error response.\n");
size_t rsize = knot_packet_question_size(knot_packet_query(resp));
- dbg_ns("Error response (~ query) size: %zu\n", rsize);
+ dbg_ns_detail("Error response (~ query) size: %zu\n", rsize);
// take 'qsize' from the current wireformat of the response
// it is already assembled - Header and Question section are copied
const uint8_t *rwire = knot_packet_wireformat(resp);
if (rsize > *wire_size) {
dbg_ns("Reponse size (%zu) larger than allowed wire size"
- " (%zu).\n", rsize, *wire_size);
+ " (%zu).\n", rsize, *wire_size);
return NS_ERR_SERVFAIL;
}
@@ -2116,8 +2443,8 @@ typedef struct ns_axfr_params {
int knot_ns_tsig_required(int packet_nr)
{
- dbg_ns_detail("ns_tsig_required(%d): %d\n", packet_nr,
- (packet_nr % KNOT_NS_TSIG_FREQ == 0));
+ dbg_ns_verb("ns_tsig_required(%d): %d\n", packet_nr,
+ (packet_nr % KNOT_NS_TSIG_FREQ == 0));
return (packet_nr % KNOT_NS_TSIG_FREQ == 0);
}
@@ -2132,7 +2459,7 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
assert(xfr->send != NULL);
// Transform the packet into wire format
- dbg_ns("Converting response to wire format..\n");
+ dbg_ns_verb("Converting response to wire format..\n");
size_t real_size = xfr->wire_size;
if (ns_response_to_wire(xfr->response, xfr->wire, &real_size) != 0) {
return NS_ERR_SERVFAIL;
@@ -2154,15 +2481,14 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
xfr->tsig_data_size += real_size;
}
- /*! \note [TSIG] Generate TSIG if required (during XFR/IN). */
if (xfr->tsig_key && add_tsig) {
if (xfr->packet_nr == 0) {
/* Add key, digest and digest length. */
dbg_ns_detail("Calling tsig_sign(): %p, %zu, %zu, "
- "%p, %zu, %p, %zu, %p\n",
- xfr->wire, real_size, xfr->wire_size,
- xfr->digest, xfr->digest_size, xfr->digest,
- digest_real_size, xfr->tsig_key);
+ "%p, %zu, %p, %zu, %p\n",
+ xfr->wire, real_size, xfr->wire_size,
+ 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,
@@ -2182,8 +2508,7 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
xfr->tsig_data_size);
}
- dbg_ns_detail("Sign function returned: %s\n",
- knot_strerror(res));
+ dbg_ns_verb("Sign function returned: %s\n", knot_strerror(res));
dbg_ns_detail("Real size of digest: %zu\n", digest_real_size);
if (res != KNOT_EOK) {
@@ -2198,8 +2523,8 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
xfr->tsig_data_size = 0;
} else if (xfr->tsig_rcode != 0) {
- dbg_ns_detail("Adding TSIG without signing, TSIG RCODE: %d.\n",
- xfr->tsig_rcode);
+ dbg_ns_verb("Adding TSIG without signing, TSIG RCODE: %d.\n",
+ xfr->tsig_rcode);
assert(xfr->tsig_rcode != KNOT_TSIG_RCODE_BADTIME);
// add TSIG without signing
assert(xfr->query != NULL);
@@ -2225,12 +2550,11 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
return res;
} else if (res != real_size) {
dbg_ns("AXFR did not send right amount of bytes."
- " Transfer size: %zu, sent: %d\n",
- real_size, res);
+ " Transfer size: %zu, sent: %d\n", real_size, res);
}
// Clean the response structure
- dbg_ns("Clearing response structure..\n");
+ dbg_ns_verb("Clearing response structure..\n");
knot_response_clear(xfr->response, 0);
// increment the packet number
@@ -2243,8 +2567,10 @@ static int ns_xfr_send_and_clear(knot_ns_xfr_t *xfr, int add_tsig)
knot_packet_set_tsig_size(xfr->response, 0);
}
- dbg_ns("Response structure after clearing:\n");
+dbg_ns_exec_verb(
+ dbg_ns_verb("Response structure after clearing:\n");
knot_packet_dump(xfr->response);
+);
return KNOT_EOK;
}
@@ -2260,15 +2586,15 @@ static void ns_axfr_from_node(knot_node_t *node, void *data)
if (params->ret != KNOT_EOK) {
// just skip (will be called on next node with the same params
- dbg_ns("Params contain error: %s, skipping node...\n",
+ dbg_ns_detail("Params contain error: %s, skipping node...\n",
knot_strerror(params->ret));
return;
}
- dbg_ns("Params OK, answering AXFR from node %p.\n", node);
-dbg_ns_exec(
+ dbg_ns_detail("Params OK, answering AXFR from node %p.\n", node);
+dbg_ns_exec_verb(
char *name = knot_dname_to_str(knot_node_owner(node));
- dbg_ns("Node ownerr: %s\n", name);
+ dbg_ns_verb("Node owner: %s\n", name);
free(name);
);
@@ -2289,8 +2615,8 @@ dbg_ns_exec(
assert(rrsets[i] != NULL);
rrset = rrsets[i];
rrset:
- dbg_ns(" Type: %s\n",
- knot_rrtype_to_string(knot_rrset_type(rrset)));
+ dbg_ns_verb(" Type: %s\n",
+ knot_rrtype_to_string(knot_rrset_type(rrset)));
// do not add SOA
if (knot_rrset_type(rrset) == KNOT_RRTYPE_SOA) {
@@ -2477,9 +2803,7 @@ static int ns_ixfr_put_rrset(knot_ns_xfr_t *xfr, knot_rrset_t *rrset)
/*! \todo Probably send back AXFR instead. */
knot_response_set_rcode(xfr->response,
KNOT_RCODE_SERVFAIL);
- /*! \todo Probably rename the function. */
ns_xfr_send_and_clear(xfr, 1);
- //socket_close(xfr->session); /*! \todo Remove for UDP.*/
return res;
}
@@ -2546,12 +2870,10 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
0, 0, 0);
if (res != KNOT_EOK) {
dbg_ns("IXFR query cannot be answered: %s.\n",
- knot_strerror(res));
+ knot_strerror(res));
knot_response_set_rcode(xfr->response,
KNOT_RCODE_SERVFAIL);
- /*! \todo Probably rename the function. */
ns_xfr_send_and_clear(xfr, 1);
-// socket_close(xfr->session); /*! \todo Remove for UDP.*/
rcu_read_unlock();
return res;
}
@@ -2571,10 +2893,7 @@ static int ns_ixfr_from_zone(knot_ns_xfr_t *xfr)
}
if (res == KNOT_EOK) {
- /*! \todo Probably rename the function. */
ns_xfr_send_and_clear(xfr, 1);
- //socket_close(xfr->session); /*! \todo Remove for UDP.*/
-// return 1;
}
rcu_read_unlock();
@@ -2596,7 +2915,6 @@ static int ns_ixfr(knot_ns_xfr_t *xfr)
// malformed packet
dbg_ns("IXFR query does not contain authority record.\n");
knot_response_set_rcode(xfr->response, KNOT_RCODE_FORMERR);
- /*! \todo Probably rename the function. */
if (ns_xfr_send_and_clear(xfr, 1) == KNOT_ECONN) {
return KNOT_ECONN;
}
@@ -2614,11 +2932,9 @@ static int ns_ixfr(knot_ns_xfr_t *xfr)
// malformed packet
dbg_ns("IXFR query is malformed.\n");
knot_response_set_rcode(xfr->response, KNOT_RCODE_FORMERR);
- /*! \todo Probably rename the function. */
if (ns_xfr_send_and_clear(xfr, 1) == KNOT_ECONN) {
return KNOT_ECONN;
}
- //socket_close(xfr->session); /*! \todo Remove for UDP. */
return KNOT_EMALF;
}
@@ -2627,8 +2943,7 @@ static int ns_ixfr(knot_ns_xfr_t *xfr)
/*----------------------------------------------------------------------------*/
-static int knot_ns_prepare_response(knot_nameserver_t *nameserver,
- knot_packet_t *query, knot_packet_t **resp,
+static int knot_ns_prepare_response(knot_packet_t *query, knot_packet_t **resp,
size_t max_size)
{
assert(max_size >= 500);
@@ -2641,8 +2956,6 @@ static int knot_ns_prepare_response(knot_nameserver_t *nameserver,
}
int ret = knot_packet_set_max_size(*resp, max_size);
- //(*resp)->wireformat = response_wire;;
- //(*resp)->max_size = max_size;
if (ret != KNOT_EOK) {
dbg_ns("Failed to init response structure.\n");
@@ -2827,14 +3140,12 @@ void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid, size_t le
int ret = knot_ns_replace_nsid(nameserver->opt_rr, nsid, len);
-// int ret = knot_edns_add_option(nameserver->opt_rr, EDNS_OPTION_NSID,
-// len, (const uint8_t *)nsid);
if (ret != KNOT_EOK) {
dbg_ns("NS: set_nsid: could not add EDNS option.\n");
return;
}
- dbg_ns("NS: set_nsid: added successfully.\n");
+ dbg_ns_verb("NS: set_nsid: added successfully.\n");
}
/*----------------------------------------------------------------------------*/
@@ -2847,28 +3158,21 @@ int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
return KNOT_EBADARG;
}
- dbg_ns("ns_parse_packet() called with query size %zu.\n", qsize);
- //dbg_ns_hex((char *)query_wire, qsize);
-
- if (qsize < 2) {
- return KNOT_EMALF;
- }
+ dbg_ns_verb("ns_parse_packet() called with query size %zu.\n", qsize);
// 1) create empty response
- dbg_ns("Parsing packet...\n");
- //parsed = knot_response_new_empty(NULL);
+ dbg_ns_verb("Parsing packet...\n");
int ret = 0;
if ((ret = knot_packet_parse_from_wire(packet, query_wire,
qsize, 1)) != 0) {
dbg_ns("Error while parsing packet, "
- "libknot error '%s'.\n", knot_strerror(ret));
-// knot_response_free(&parsed);
+ "libknot error '%s'.\n", knot_strerror(ret));
return KNOT_RCODE_FORMERR;
}
- dbg_ns("Parsed packet header and Question:\n");
+ dbg_ns_verb("Parsed packet header and Question:\n");
knot_packet_dump(packet);
// 3) determine the query type
@@ -2904,17 +3208,15 @@ int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
return KNOT_RCODE_NOTIMPL;
}
-// knot_packet_free(&packet);
-
return KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
-void knot_ns_error_response(const knot_nameserver_t *nameserver,
- uint16_t query_id, uint8_t *flags1_query,
- uint8_t rcode, uint8_t *response_wire,
- size_t *rsize)
+static void knot_ns_error_response(const knot_nameserver_t *nameserver,
+ uint16_t query_id, uint8_t *flags1_query,
+ uint8_t rcode, uint8_t *response_wire,
+ size_t *rsize)
{
memcpy(response_wire, nameserver->err_response,
nameserver->err_resp_size);
@@ -2927,7 +3229,7 @@ void knot_ns_error_response(const knot_nameserver_t *nameserver,
knot_wire_set_rd(response_wire);
}
knot_wire_set_opcode(response_wire,
- knot_wire_flags_get_opcode(*flags1_query));
+ knot_wire_flags_get_opcode(*flags1_query));
}
// set the RCODE
@@ -2937,10 +3239,10 @@ void knot_ns_error_response(const knot_nameserver_t *nameserver,
/*----------------------------------------------------------------------------*/
-int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver,
- const uint8_t *query, size_t size,
- uint8_t rcode, uint8_t *response_wire,
- size_t *rsize)
+int knot_ns_error_response_from_query_wire(const knot_nameserver_t *nameserver,
+ const uint8_t *query, size_t size,
+ uint8_t rcode,
+ uint8_t *response_wire, size_t *rsize)
{
if (size < 2) {
// ignore packet
@@ -2964,6 +3266,63 @@ int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver,
/*----------------------------------------------------------------------------*/
+int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver,
+ const knot_packet_t *query,
+ uint8_t rcode, uint8_t *response_wire,
+ size_t *rsize)
+{
+ if (query->parsed < 2) {
+ // ignore packet
+ return KNOT_EFEWDATA;
+ }
+
+ if (query->parsed < KNOT_WIRE_HEADER_SIZE) {
+ return knot_ns_error_response_from_query_wire(nameserver,
+ query->wireformat, query->size, rcode, response_wire,
+ rsize);
+ }
+
+ size_t max_size = *rsize;
+ uint8_t flags1 = knot_wire_get_flags1(knot_packet_wireformat(query));
+
+ // prepare the generic error response
+ knot_ns_error_response(nameserver, knot_packet_id(query),
+ &flags1, rcode, response_wire,
+ rsize);
+
+ if (query->parsed > KNOT_WIRE_HEADER_SIZE
+ + KNOT_WIRE_QUESTION_MIN_SIZE) {
+ // in this case the whole question was parsed, append it
+ size_t question_size = 4 + knot_dname_size(
+ knot_packet_qname(query));
+
+ if (max_size > KNOT_WIRE_HEADER_SIZE + question_size) {
+ /*
+ * 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
+ * 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
+ * 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_WIRE_HEADER_SIZE, question_size);
+ }
+ *rsize += question_size;
+
+ // adjust QDCOUNT
+ knot_wire_set_qdcount(response_wire, 1);
+ }
+ }
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
void knot_ns_error_response_full(knot_nameserver_t *nameserver,
knot_packet_t *response, uint8_t rcode,
uint8_t *response_wire, size_t *rsize)
@@ -2971,11 +3330,10 @@ void knot_ns_error_response_full(knot_nameserver_t *nameserver,
knot_response_set_rcode(response, rcode);
if (ns_error_response_to_wire(response, response_wire, rsize) != 0) {
- knot_ns_error_response(nameserver, knot_packet_id(
- knot_packet_query(response)),
- &response->header.flags1,
- KNOT_RCODE_SERVFAIL, response_wire,
- rsize);
+ knot_ns_error_response_from_query(nameserver,
+ knot_packet_query(response),
+ KNOT_RCODE_SERVFAIL,
+ response_wire, rsize);
}
}
@@ -2985,7 +3343,7 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
knot_packet_t *query, knot_packet_t **resp,
const knot_zone_t **zone, size_t max_size)
{
- dbg_ns("knot_ns_prep_normal_response()\n");
+ dbg_ns_verb("knot_ns_prep_normal_response()\n");
if (nameserver == NULL || query == NULL || resp == NULL
|| zone == NULL) {
@@ -2994,8 +3352,8 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
// first, parse the rest of the packet
assert(knot_packet_is_query(query));
- dbg_ns("Query - parsed: %zu, total wire size: %zu\n",
- knot_packet_parsed(query), knot_packet_size(query));
+ dbg_ns_verb("Query - parsed: %zu, total wire size: %zu\n",
+ knot_packet_parsed(query), knot_packet_size(query));
int ret;
ret = knot_packet_parse_rest(query);
@@ -3017,10 +3375,38 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
if (knot_packet_ancount(query) > 0
|| knot_packet_nscount(query) > 0
|| knot_packet_qdcount(query) != 1) {
- dbg_ns("ANCOUNT or NSCOUNT not 0 in query, reply FORMERR.\n");
+ dbg_ns("ANCOUNT or NSCOUNT not 0 in query, "
+ "or QDCOUNT != 1. Reply FORMERR.\n");
return KNOT_EMALF;
}
+ /*
+ * Check what is in the Additional section. Only OPT and TSIG are
+ * allowed. TSIG must be the last record if present.
+ */
+ if (knot_packet_arcount(query) > 0) {
+ int ok = 0;
+ const knot_rrset_t *add1 =
+ knot_packet_additional_rrset(query, 0);
+ if (knot_packet_additional_rrset_count(query) == 1
+ && (knot_rrset_type(add1) == KNOT_RRTYPE_OPT
+ || knot_rrset_type(add1) == KNOT_RRTYPE_TSIG)) {
+ ok = 1;
+ } else if (knot_packet_additional_rrset_count(query) == 2) {
+ const knot_rrset_t *add2 =
+ knot_packet_additional_rrset(query, 1);
+ if (knot_rrset_type(add1) == KNOT_RRTYPE_OPT
+ && knot_rrset_type(add2) == KNOT_RRTYPE_TSIG) {
+ ok = 1;
+ }
+ }
+
+ if (!ok) {
+ dbg_ns("Additional section malformed. Reply FORMERR\n");
+ return KNOT_EMALF;
+ }
+ }
+
size_t resp_max_size = 0;
knot_packet_dump(query);
@@ -3044,22 +3430,21 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
resp_max_size = MAX_UDP_PAYLOAD;
}
- ret = knot_ns_prepare_response(nameserver, query, resp,
- resp_max_size);
+ ret = knot_ns_prepare_response(query, resp, resp_max_size);
if (ret != KNOT_EOK) {
return KNOT_ERROR;
}
- dbg_ns("Query - parsed: %zu, total wire size: %zu\n",
- query->parsed, query->size);
- dbg_ns("Opt RR: version: %d, payload: %d\n",
+ dbg_ns_verb("Query - parsed: %zu, total wire size: %zu\n",
+ 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("EDNS supported in query: %d\n",
- knot_query_edns_supported(query));
+ dbg_ns_detail("EDNS supported in query: %d\n",
+ knot_query_edns_supported(query));
// set the OPT RR to the response
if (knot_query_edns_supported(query)) {
@@ -3067,25 +3452,24 @@ int knot_ns_prep_normal_response(knot_nameserver_t *nameserver,
knot_query_nsid_requested(query));
if (ret != KNOT_EOK) {
dbg_ns("Failed to set OPT RR to the response"
- ": %s\n", knot_strerror(ret));
+ ": %s\n", knot_strerror(ret));
} else {
// copy the DO bit from the query
if (knot_query_dnssec_requested(query)) {
- /*! \todo API for this. */
knot_edns_set_do(&(*resp)->opt_rr);
}
}
}
- dbg_ns("Response max size: %zu\n", (*resp)->max_size);
+ dbg_ns_verb("Response max size: %zu\n", (*resp)->max_size);
const knot_dname_t *qname = knot_packet_qname(*resp);
assert(qname != NULL);
uint16_t qtype = knot_packet_qtype(*resp);
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name_str = knot_dname_to_str(qname);
- dbg_ns("Trying to find zone for QNAME %s\n", name_str);
+ dbg_ns_verb("Trying to find zone for QNAME %s\n", name_str);
free(name_str);
);
// find zone in which to search for the name
@@ -3098,11 +3482,11 @@ dbg_ns_exec(
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)
+ uint8_t *response_wire, size_t *rsize, int check_any)
{
- dbg_ns("ns_answer_normal()\n");
+ dbg_ns_verb("ns_answer_normal()\n");
- int ret = ns_answer(zone, resp);
+ int ret = ns_answer(zone, resp, check_any);
if (ret != 0) {
// now only one type of error (SERVFAIL), later maybe more
@@ -3110,7 +3494,7 @@ int knot_ns_answer_normal(knot_nameserver_t *nameserver,
KNOT_RCODE_SERVFAIL,
response_wire, rsize);
} else {
- dbg_ns("Created response packet.\n");
+ dbg_ns_verb("Created response packet.\n");
//knot_response_dump(resp);
knot_packet_dump(resp);
@@ -3123,6 +3507,55 @@ int knot_ns_answer_normal(knot_nameserver_t *nameserver,
}
}
+ dbg_ns_verb("Returning response with wire size %zu\n", *rsize);
+
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int knot_ns_answer_ixfr_udp(knot_nameserver_t *nameserver,
+ const knot_zone_t *zone, knot_packet_t *resp,
+ uint8_t *response_wire, size_t *rsize)
+{
+ dbg_ns("ns_answer_ixfr_udp()\n");
+
+ const knot_zone_contents_t *contents = knot_zone_contents(zone);
+
+ // if no zone found, return REFUSED
+ if (zone == NULL) {
+ dbg_ns("No zone found.\n");
+ knot_response_set_rcode(resp, KNOT_RCODE_REFUSED);
+ return KNOT_EOK;
+ } else if (contents == NULL) {
+ dbg_ns("Zone expired or not bootstrapped. Reply SERVFAIL.\n");
+ knot_response_set_rcode(resp, KNOT_RCODE_SERVFAIL);
+ return KNOT_EOK;
+ }
+
+ const knot_node_t *apex = knot_zone_contents_apex(contents);
+ assert(apex != NULL);
+ 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);
+ if (ret != KNOT_EOK) {
+ knot_ns_error_response_full(nameserver, resp,
+ KNOT_RCODE_SERVFAIL,
+ response_wire, rsize);
+ }
+
+ dbg_ns("Created response packet.\n");
+ knot_packet_dump(resp);
+
+ // Transform the packet into wire format
+ if (ns_response_to_wire(resp, response_wire, rsize) != 0) {
+ // send back SERVFAIL (as this is our problem)
+ knot_ns_error_response_full(nameserver, resp,
+ KNOT_RCODE_SERVFAIL,
+ response_wire, rsize);
+ }
+
dbg_ns("Returning response with wire size %zu\n", *rsize);
return KNOT_EOK;
@@ -3134,18 +3567,21 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
{
dbg_ns("knot_ns_init_xfr()\n");
+ int ret = 0;
+
if (nameserver == NULL || xfr == NULL) {
- return KNOT_EBADARG;
+ dbg_ns("Wrong parameters given to function ns_init_xfr()\n");
+ /* Sending error was totally wrong. If nameserver or xfr were
+ * NULL, the ns_error_response() function would crash.
+ */
+ return ret;
}
- // no need to parse rest of the packet
- /*! \todo Parse rest of packet because of EDNS. */
- int ret = knot_packet_parse_rest(xfr->query);
+ ret = knot_packet_parse_rest(xfr->query);
if (ret != KNOT_EOK) {
dbg_ns("Failed to parse rest of the query: %s\n",
knot_strerror(ret));
- knot_ns_error_response(nameserver, xfr->query->header.id,
- &xfr->query->header.flags1,
+ knot_ns_error_response_from_query(nameserver, xfr->query,
(ret == KNOT_EMALF) ? KNOT_RCODE_FORMERR
: KNOT_RCODE_SERVFAIL,
xfr->wire, &xfr->wire_size);
@@ -3154,8 +3590,10 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
return ret;
}
- dbg_packet("Parsed XFR query:\n");
+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(
@@ -3163,41 +3601,25 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
if (response == NULL) {
dbg_ns("Failed to create packet structure.\n");
/*! \todo xfr->wire is not NULL, will fail on assert! */
- knot_ns_error_response(nameserver, xfr->query->header.id,
- &xfr->query->header.flags1,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ 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);
- knot_packet_free(&response);
return ret;
}
- //int ret = knot_packet_set_max_size(response, xfr->wire_size);
response->wireformat = xfr->wire;
response->max_size = xfr->wire_size;
-// if (ret != KNOT_EOK) {
-// dbg_ns("Failed to init response structure.\n");
-// /*! \todo xfr->wire is not NULL, will fail on assert! */
-// knot_ns_error_response(nameserver, xfr->query->header.id,
-// KNOT_RCODE_SERVFAIL, xfr->wire,
-// &xfr->wire_size);
-// int res = xfr->send(xfr->session, &xfr->addr, xfr->wire,
-// xfr->wire_size);
-// knot_packet_free(&response);
-// return res;
-// }
-
ret = knot_response_init_from_query(response, xfr->query);
if (ret != KNOT_EOK) {
dbg_ns("Failed to init response structure.\n");
/*! \todo xfr->wire is not NULL, will fail on assert! */
- knot_ns_error_response(nameserver, xfr->query->header.id,
- &xfr->query->header.flags1,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ 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,
xfr->wire_size);
knot_packet_free(&response);
@@ -3213,9 +3635,9 @@ int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
assert(knot_packet_qtype(xfr->response) == KNOT_RRTYPE_AXFR ||
knot_packet_qtype(xfr->response) == KNOT_RRTYPE_IXFR);
-dbg_ns_exec(
+dbg_ns_exec_verb(
char *name_str = knot_dname_to_str(qname);
- dbg_ns("Trying to find zone with name %s\n", name_str);
+ 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
@@ -3258,20 +3680,20 @@ int ns_ixfr_load_serials(const knot_ns_xfr_t *xfr, uint32_t *serial_from,
{
if (xfr == NULL || xfr->zone == NULL || serial_from == NULL
|| serial_to == NULL) {
- dbg_ns_detail("Wrong parameters: xfr=%p,"
- " xfr->zone = %p\n", xfr, xfr->zone);
+ dbg_ns("Wrong parameters: xfr=%p,"
+ " xfr->zone = %p\n", xfr, xfr->zone);
return KNOT_EBADARG;
}
const knot_zone_t *zone = xfr->zone;
const knot_zone_contents_t *contents = knot_zone_contents(zone);
if (!contents) {
- dbg_ns_detail("Missing contents\n");
+ dbg_ns("Missing contents\n");
return KNOT_EBADARG;
}
if (knot_zone_contents_apex(contents) == NULL) {
- dbg_ns_detail("No apex.\n");
+ dbg_ns("No apex.\n");
return KNOT_EBADARG;
}
@@ -3279,17 +3701,17 @@ int ns_ixfr_load_serials(const knot_ns_xfr_t *xfr, uint32_t *serial_from,
knot_node_rrset(knot_zone_contents_apex(contents),
KNOT_RRTYPE_SOA);
if (zone_soa == NULL) {
- dbg_ns_verb("No SOA.\n");
+ dbg_ns("No SOA.\n");
return KNOT_EBADARG;
}
if (knot_packet_nscount(xfr->query) < 1) {
- dbg_ns_verb("No Authority record.\n");
+ dbg_ns("No Authority record.\n");
return KNOT_EMALF;
}
if (knot_packet_authority_rrset(xfr->query, 0) == NULL) {
- dbg_ns_verb("Authority record missing.\n");
+ dbg_ns("Authority record missing.\n");
return KNOT_ERROR;
}
@@ -3309,13 +3731,13 @@ int knot_ns_xfr_send_error(const knot_nameserver_t *nameserver,
/*! \todo Handle TSIG errors differently. */
knot_response_set_rcode(xfr->response, rcode);
- /*! \todo Probably rename the function. */
int ret = 0;
- if ((ret = ns_xfr_send_and_clear(xfr, 1)) != KNOT_EOK) {
+ if ((ret = ns_xfr_send_and_clear(xfr, 1)) != KNOT_EOK
+ || xfr->response == NULL) {
size_t size = 0;
- knot_ns_error_response(nameserver, xfr->query->header.id,
- &xfr->query->header.flags1,
- KNOT_RCODE_SERVFAIL, xfr->wire, &size);
+ knot_ns_error_response_from_query(nameserver, xfr->query,
+ KNOT_RCODE_SERVFAIL,
+ xfr->wire, &size);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire, size);
}
@@ -3337,11 +3759,7 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
knot_zone_contents_t *contents = knot_zone_get_contents(xfr->zone);
if (!contents) {
dbg_ns("AXFR failed on stub zone\n");
- /*! \todo replace with knot_ns_xfr_send_error() */
- knot_ns_error_response(nameserver, xfr->query->header.id,
- &xfr->query->header.flags1,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ knot_ns_xfr_send_error(nameserver, xfr, KNOT_RCODE_SERVFAIL);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
rcu_read_unlock();
@@ -3349,16 +3767,16 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
return ret;
}
- /*!
- * \todo [TSIG] 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.
+ /*
+ * 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_detail("Setting TSIG size in packet: %zu\n",
- xfr->tsig_size);
+ dbg_ns_verb("Setting TSIG size in packet: %zu\n",
+ xfr->tsig_size);
knot_packet_set_tsig_size(xfr->response, xfr->tsig_size);
}
@@ -3372,11 +3790,7 @@ int knot_ns_answer_axfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
dbg_ns("AXFR failed, sending SERVFAIL.\n");
// now only one type of error (SERVFAIL), later maybe more
/*! \todo xfr->wire is not NULL, will fail on assert! */
- /*! \todo replace with knot_ns_xfr_send_error() */
- knot_ns_error_response(nameserver, xfr->query->header.id,
- &xfr->query->header.flags1,
- KNOT_RCODE_SERVFAIL, xfr->wire,
- &xfr->wire_size);
+ knot_ns_xfr_send_error(nameserver, xfr, KNOT_RCODE_SERVFAIL);
ret = xfr->send(xfr->session, &xfr->addr, xfr->wire,
xfr->wire_size);
} else if (ret > 0) {
@@ -3398,14 +3812,12 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
|| xfr->response == NULL) {
return KNOT_EBADARG;
}
-
- //uint8_t *wire = NULL;
- //size_t size = xfr->wire_size;
// parse rest of the packet (we need the Authority record)
int ret = knot_packet_parse_rest(xfr->query);
if (ret != KNOT_EOK) {
- dbg_ns("Failed to parse rest of the packet. Reply FORMERR.\n");
+ dbg_ns("Failed to parse rest of the packet: %s. "
+ "Reply FORMERR.\n", knot_strerror(ret));
knot_ns_xfr_send_error(nameserver, xfr, KNOT_RCODE_FORMERR);
knot_packet_free(&xfr->response);
return ret;
@@ -3419,11 +3831,11 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
return ret;
}
- /*!
- * \todo [TSIG] 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'.
+ /*
+ * 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. */
@@ -3433,16 +3845,6 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
ret = ns_ixfr(xfr);
-// /*! \todo Somehow distinguish when it makes sense to send the SERVFAIL
-// * and when it does not. E.g. if there was problem in sending
-// * packet, it will probably fail when sending the SERVFAIL also.
-// */
-// if (ret < 0) {
-// dbg_ns("IXFR failed, sending SERVFAIL.\n");
-// // now only one type of error (SERVFAIL), later maybe more
-// knot_ns_xfr_send_error(nameserver, xfr, KNOT_RCODE_SERVFAIL);
-// }
-
knot_packet_free(&xfr->response);
return ret;
@@ -3452,18 +3854,16 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
{
- /*!
- * \todo [TSIG] Here we assume that 'xfr' contains TSIG information
- * and the digest of the query sent to the master or the previous
- * digest.
+ /*
+ * Here we assume that 'xfr' contains TSIG information
+ * 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);
+ xfr->wire_size);
- int ret = xfrin_process_axfr_packet(/*xfr->wire, xfr->wire_size,*/
- /*(xfrin_constructed_zone_t **)(&xfr->data)*/
- xfr);
+ int ret = xfrin_process_axfr_packet(xfr);
if (ret > 0) { // transfer finished
dbg_ns("ns_process_axfrin: AXFR finished, zone created.\n");
@@ -3477,19 +3877,19 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
assert(zone != NULL);
/* Create and fill hash table */
- dbg_ns("ns_process_axfrin: filling hash table.\n");
+ 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
}
- dbg_ns("ns_process_axfrin: adjusting zone.\n");
+ dbg_ns_verb("ns_process_axfrin: adjusting zone.\n");
rc = knot_zone_contents_adjust(zone);
if (rc != KNOT_EOK) {
return rc;
}
- dbg_ns("ns_process_axfrin: checking loops.\n");
+ dbg_ns_verb("ns_process_axfrin: checking loops.\n");
rc = knot_zone_contents_check_loops(zone);
if (rc != KNOT_EOK) {
return rc;
@@ -3508,15 +3908,13 @@ int knot_ns_process_axfrin(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr)
//knot_zone_contents_dump(zone, 0);
// check zone integrity
-dbg_xfrin_exec(
+dbg_ns_exec_verb(
int errs = knot_zone_contents_integrity_check(zone);
- dbg_xfrin("Zone integrity check: %d errors.\n", errs);
+ dbg_ns_verb("Zone integrity check: %d errors.\n", errs);
);
}
- /*!
- * \todo In case of error, shouldn't the zone be destroyed here?
- */
+ /*! \todo In case of error, shouldn't the zone be destroyed here? */
return ret;
}
@@ -3538,14 +3936,14 @@ int knot_ns_switch_zone(knot_nameserver_t *nameserver,
return KNOT_ENOZONE;
}
- // find the zone in the zone db
- knot_zone_t *z = knot_zonedb_find_zone(nameserver->zone_db,
- knot_node_owner(knot_zone_contents_apex(zone)));
+ /* Zone must not be looked-up from server, as it may be a different zone if
+ * a reload occurs when transfer is pending. */
+ knot_zone_t *z = xfr->zone;
if (z == NULL) {
char *name = knot_dname_to_str(knot_node_owner(
knot_zone_contents_apex(zone)));
dbg_ns("Failed to replace zone %s, old zone "
- "not found\n", name);
+ "not found\n", name);
free(name);
return KNOT_ENOZONE;
@@ -3555,16 +3953,18 @@ int knot_ns_switch_zone(knot_nameserver_t *nameserver,
int ret = xfrin_switch_zone(z, zone, xfr->type);
-dbg_ns_exec(
- dbg_ns("Zone db contents: (zone count: %zu)\n",
- nameserver->zone_db->zone_count);
+dbg_ns_exec_verb(
+ dbg_ns_verb("Zone db contents: (zone count: %zu)\n",
+ nameserver->zone_db->zone_count);
+ /* Warning: may not show updated zone if updated zone that is already
+ * discarded from zone db (reload with pending transfer). */
const knot_zone_t **zones = knot_zonedb_zones(nameserver->zone_db);
for (int i = 0; i < knot_zonedb_zone_count
(nameserver->zone_db); i++) {
- dbg_ns("%d. zone: %p", i, zones[i]);
+ dbg_ns_verb("%d. zone: %p\n", i, zones[i]);
char *name = knot_dname_to_str(zones[i]->name);
- dbg_ns(" zone name: %s\n", name);
+ dbg_ns_verb(" zone name: %s\n", name);
free(name);
}
free(zones);
@@ -3574,18 +3974,16 @@ dbg_ns_exec(
}
/*----------------------------------------------------------------------------*/
-/*! \todo In this function, xfr->zone is properly set. If this is so, we do not
- * have to search for the zone after the transfer has finished.
- */
+
int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
knot_ns_xfr_t *xfr)
{
dbg_ns("ns_process_ixfrin: incoming packet\n");
- /*!
- * \todo [TSIG] Here we assume that 'xfr' contains TSIG information
- * and the digest of the query sent to the master or the previous
- * digest.
+ /*
+ * [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);
@@ -3608,19 +4006,18 @@ int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
}
// find zone associated with the changesets
- knot_zone_t *zone = knot_zonedb_find_zone(
- nameserver->zone_db,
- knot_rrset_owner(chgsets->first_soa));
+ /* Must not search for the zone in zonedb as it may fetch a
+ * different zone than the one the transfer started on. */
+ knot_zone_t *zone = xfr->zone;
if (zone == NULL) {
dbg_ns("No zone found for incoming IXFR!\n");
knot_free_changesets(
(knot_changesets_t **)(&xfr->data));
- return KNOT_ENOZONE; /*! \todo Other error code? */
+ return KNOT_ENOZONE;
}
switch (ret) {
case XFRIN_RES_COMPLETE:
- xfr->zone = zone;
break;
case XFRIN_RES_SOA_ONLY: {
// compare the SERIAL from the changeset with the zone's
@@ -3666,9 +4063,7 @@ int knot_ns_process_ixfrin(knot_nameserver_t *nameserver,
}
}
- /*!
- * \todo In case of error, shouldn't the zone be destroyed here?
- */
+ /*! \todo In case of error, shouldn't the zone be destroyed here? */
return ret;
}
@@ -3684,26 +4079,24 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
knot_packet_t *response;
assert(*rsize >= MAX_UDP_PAYLOAD);
- int ret = knot_ns_prepare_response(nameserver, query, &response,
- MAX_UDP_PAYLOAD);
+ int ret = knot_ns_prepare_response(query, &response, MAX_UDP_PAYLOAD);
if (ret != KNOT_EOK) {
- knot_ns_error_response(nameserver, knot_packet_id(query),
- &query->header.flags1,
- KNOT_RCODE_SERVFAIL, response_wire,
- rsize);
+ knot_ns_error_response_from_query(nameserver, query,
+ KNOT_RCODE_SERVFAIL,
+ response_wire, rsize);
return KNOT_EOK;
}
assert(response != NULL);
- dbg_ns("Query - parsed: %zu, total wire size: %zu\n",
- query->parsed, query->size);
+ dbg_ns_verb("Query - parsed: %zu, total wire size: %zu\n",
+ query->parsed, query->size);
if (knot_packet_parsed(query) < knot_packet_size(query)) {
ret = knot_packet_parse_rest(query);
if (ret != KNOT_EOK) {
dbg_ns("Failed to parse rest of the query: "
- "%s.\n", knot_strerror(ret));
+ "%s.\n", knot_strerror(ret));
knot_ns_error_response_full(nameserver, response,
(ret == KNOT_EMALF)
? KNOT_RCODE_FORMERR
@@ -3714,17 +4107,16 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
}
}
- dbg_ns("Query - parsed: %zu, total wire size: %zu\n",
- knot_packet_parsed(query), knot_packet_size(query));
+ dbg_ns_verb("Query - parsed: %zu, total wire size: %zu\n",
+ knot_packet_parsed(query), knot_packet_size(query));
/*! \todo API for EDNS values. */
- dbg_ns("Opt RR: version: %d, payload: %d\n",
- query->opt_rr.version, query->opt_rr.payload);
+ dbg_ns_verb("Opt RR: version: %d, payload: %d\n",
+ query->opt_rr.version, query->opt_rr.payload);
// 2) Find zone for the query
// we do not check if there is only one entry in the Question section
// because the packet structure does not allow it
- /*! \todo Check number of Question entries while parsing. */
if (knot_packet_qtype(query) != KNOT_RRTYPE_SOA) {
dbg_ns("Question is not of type SOA.\n");
knot_ns_error_response_full(nameserver, response,
@@ -3754,7 +4146,7 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
return KNOT_EBADZONE;
} else if (ret != KNOT_EOK) {
dbg_ns("Failed to check zone for update: "
- "%s.\n", knot_strerror(ret));
+ "%s.\n", knot_strerror(ret));
knot_ns_error_response_full(nameserver, response, rcode,
response_wire, rsize);
knot_packet_free(&response);
@@ -3766,7 +4158,7 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
ret = knot_ddns_process_prereqs(query, &prereqs, &rcode);
if (ret != KNOT_EOK) {
dbg_ns("Failed to check zone for update: "
- "%s.\n", knot_strerror(ret));
+ "%s.\n", knot_strerror(ret));
knot_ns_error_response_full(nameserver, response, rcode,
response_wire, rsize);
knot_packet_free(&response);
@@ -3783,7 +4175,7 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
&rcode);
if (ret != KNOT_EOK) {
dbg_ns("Failed to check zone for update: "
- "%s.\n", knot_strerror(ret));
+ "%s.\n", knot_strerror(ret));
knot_ns_error_response_full(nameserver, response, rcode,
response_wire, rsize);
knot_ddns_prereqs_free(&prereqs);
@@ -3795,7 +4187,7 @@ int knot_ns_process_update(knot_nameserver_t *nameserver, knot_packet_t *query,
ret = knot_ddns_process_update(query, changeset, &rcode);
if (ret != KNOT_EOK) {
dbg_ns("Failed to check zone for update: "
- "%s.\n", knot_strerror(ret));
+ "%s.\n", knot_strerror(ret));
knot_ns_error_response_full(nameserver, response, rcode,
response_wire, rsize);
knot_ddns_prereqs_free(&prereqs);
diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h
index da19f49..3fe1210 100644..100755
--- a/src/libknot/nameserver/name-server.h
+++ b/src/libknot/nameserver/name-server.h
@@ -115,8 +115,6 @@ typedef struct knot_ns_xfr {
*/
uint8_t *tsig_data;
size_t tsig_data_size; /*!< Size of the message(s) in bytes */
-// const knot_rrset_t *tsig; /*!< Response TSIG.
-// \todo [TSIG] Replace with separate data. */
size_t tsig_size; /*!< Size of the TSIG RR wireformat in bytes.*/
knot_key_t *tsig_key; /*!< Associated TSIG key for signing. */
@@ -127,13 +125,6 @@ typedef struct knot_ns_xfr {
uint16_t tsig_rcode;
uint64_t tsig_prev_time_signed;
- /*! \brief Previous digest or request digest.
- *
- * Should be allocated before the transfer (known size).
- */
-// uint8_t *prev_digest;
-// size_t prev_digest_size; /*!< Size of previous digest in bytes. */
-
/*!
* \brief Number of the packet currently assembled.
*
@@ -154,7 +145,7 @@ static const size_t KNOT_NS_TSIG_DATA_MAX_SIZE = 100 * 64 * 1024;
enum knot_ns_xfr_flag_t {
XFR_FLAG_TCP = 1 << 0, /*!< XFR request is on TCP. */
XFR_FLAG_UDP = 1 << 1, /*!< XFR request is on UDP. */
- XFR_FLAG_AXFR_FINISHED = 1 << 2
+ XFR_FLAG_AXFR_FINISHED = 1 << 2 /*!< Transfer is finished. */
};
typedef enum knot_ns_transport {
@@ -218,26 +209,13 @@ void knot_ns_set_nsid(knot_nameserver_t *nameserver, const char *nsid,
int knot_ns_parse_packet(const uint8_t *query_wire, size_t qsize,
knot_packet_t *packet, knot_packet_type_t *type);
-/*!
- * \brief Prepares wire format of an error response using generic error template
- * stored in the nameserver structure.
- *
- * The error response will not contain the Question section from the query, just
- * a header with ID copied from the query and the given RCODE.
- *
- * \param nameserver Nameserver structure containing the error template.
- * \param query_id ID of the query.
- * \param rcode RCODE to set in the response.
- * \param response_wire Place for wire format of the response.
- * \param rsize Size of the error response will be stored here.
- */
-void knot_ns_error_response(const knot_nameserver_t *nameserver,
- uint16_t query_id, uint8_t *flags1_query,
- uint8_t rcode, uint8_t *response_wire,
- size_t *rsize);
+int knot_ns_error_response_from_query_wire(const knot_nameserver_t *nameserver,
+ const uint8_t *query, size_t size,
+ uint8_t rcode, uint8_t *response_wire,
+ size_t *rsize);
int knot_ns_error_response_from_query(const knot_nameserver_t *nameserver,
- const uint8_t *query, size_t size,
+ const knot_packet_t *query,
uint8_t rcode, uint8_t *response_wire,
size_t *rsize);
@@ -264,7 +242,11 @@ int knot_ns_prep_normal_response(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);
+ uint8_t *response_wire, size_t *rsize, int check_any);
+
+int knot_ns_answer_ixfr_udp(knot_nameserver_t *nameserver,
+ const knot_zone_t *zone, knot_packet_t *resp,
+ uint8_t *response_wire, size_t *rsize);
int knot_ns_init_xfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr);
@@ -322,11 +304,11 @@ int knot_ns_answer_ixfr(knot_nameserver_t *nameserver, knot_ns_xfr_t *xfr);
* \param nameserver Name server structure to provide the data for answering.
* \param xfr Persistent transfer-specific data.
*
- * \todo Document me.
*/
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,
knot_ns_xfr_t *xfr);
diff --git a/src/libknot/nsec3.c b/src/libknot/nsec3.c
index 1414e7e..9cab4be 100644..100755
--- a/src/libknot/nsec3.c
+++ b/src/libknot/nsec3.c
@@ -74,7 +74,7 @@ int knot_nsec3_params_from_wire(knot_nsec3_params_t *params,
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("Salt: ");
+ dbg_nsec3("Salt: \n");
if (params->salt != NULL) {
dbg_nsec3_hex((char *)params->salt,
params->salt_length);
@@ -171,8 +171,8 @@ int knot_nsec3_sha1(const knot_nsec3_params_t *params,
EVP_MD_CTX_cleanup(&mdctx);
- dbg_nsec3("NSEC3 hashing: calls: %lu, avg time per call: %f."
- "\n", calls, (double)(total_time) / calls);
+ dbg_nsec3_verb("NSEC3 hashing: calls: %lu, avg time per call: %f."
+ "\n", calls, (double)(total_time) / calls);
free(data_low);
return 0;
@@ -194,17 +194,17 @@ int knot_nsec3_sha1(const knot_nsec3_params_t *params,
uint8_t salt_length = params->salt_length;
uint16_t iterations = params->iterations;
- dbg_nsec3("Hashing: \n");
- dbg_nsec3(" Data: %.*s \n", size, data);
- dbg_nsec3_hex((const char *)data, size);
- dbg_nsec3(" (size %d)\n Iterations: %u\n", (int)size, iterations);
- dbg_nsec3(" Salt length: %u\n", salt_length);
- dbg_nsec3(" Salt: ");
+ dbg_nsec3_verb("Hashing: \n");
+ dbg_nsec3_verb(" Data: %.*s \n", 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);
+ dbg_nsec3_verb(" Salt: \n");
if (salt_length > 0) {
- dbg_nsec3_hex((char *)salt, salt_length);
- dbg_nsec3("\n");
+ dbg_nsec3_hex_verb((char *)salt, salt_length);
+ dbg_nsec3_verb("\n");
} else {
- dbg_nsec3("none\n");
+ dbg_nsec3_verb("none\n");
}
SHA_CTX ctx;
@@ -251,9 +251,9 @@ int knot_nsec3_sha1(const knot_nsec3_params_t *params,
*digest_size = SHA_DIGEST_LENGTH;
- dbg_nsec3("Hash: %.*s\n", *digest_size, *digest);
- dbg_nsec3_hex((const char *)*digest, *digest_size);
- dbg_nsec3("\n");
+ dbg_nsec3_verb("Hash: %.*s\n", *digest_size, *digest);
+ dbg_nsec3_hex_verb((const char *)*digest, *digest_size);
+ dbg_nsec3_verb("\n");
free(data_low);
return KNOT_EOK;
diff --git a/src/libknot/nsec3.h b/src/libknot/nsec3.h
index 0ce6899..0ce6899 100644..100755
--- a/src/libknot/nsec3.h
+++ b/src/libknot/nsec3.h
diff --git a/src/libknot/packet/packet.c b/src/libknot/packet/packet.c
index 82b65c6..6c7fd02 100644..100755
--- a/src/libknot/packet/packet.c
+++ b/src/libknot/packet/packet.c
@@ -22,6 +22,7 @@
#include "common.h"
#include "util/descriptor.h"
#include "util/wire.h"
+#include "tsig.h"
/*----------------------------------------------------------------------------*/
@@ -51,7 +52,7 @@ typedef enum {
*/
static void knot_packet_init_pointers_response(knot_packet_t *pkt)
{
- dbg_packet("Packet pointer: %p\n", pkt);
+ dbg_packet_detail("Packet pointer: %p\n", pkt);
char *pos = (char *)pkt + PREALLOC_PACKET;
@@ -59,7 +60,7 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->question.qname = (knot_dname_t *)pos;
pos += PREALLOC_QNAME_DNAME;
- dbg_packet("QNAME: %p\n", pkt->question.qname);
+ dbg_packet_detail("QNAME: %p\n", pkt->question.qname);
pkt->question.qname->name = (uint8_t *)pos;
pos += PREALLOC_QNAME_NAME;
@@ -67,7 +68,7 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pos += PREALLOC_QNAME_LABELS;
pkt->owner_tmp = (uint8_t *)pos;
- dbg_packet("Tmp owner: %p\n", pkt->owner_tmp);
+ dbg_packet_detail("Tmp owner: %p\n", pkt->owner_tmp);
pos += PREALLOC_RR_OWNER;
// then answer, authority and additional sections
@@ -92,9 +93,9 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pos += DEFAULT_ARCOUNT * sizeof(const knot_rrset_t *);
}
- dbg_packet("Answer section: %p\n", pkt->answer);
- dbg_packet("Authority section: %p\n", pkt->authority);
- dbg_packet("Additional section: %p\n", pkt->additional);
+ dbg_packet_detail("Answer section: %p\n", pkt->answer);
+ dbg_packet_detail("Authority section: %p\n", pkt->authority);
+ dbg_packet_detail("Additional section: %p\n", pkt->additional);
pkt->max_an_rrsets = DEFAULT_ANCOUNT;
pkt->max_ns_rrsets = DEFAULT_NSCOUNT;
@@ -106,8 +107,8 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->compression.offsets = (size_t *)pos;
pos += DEFAULT_DOMAINS_IN_RESPONSE * sizeof(size_t);
- dbg_packet("Compression dnames: %p\n", pkt->compression.dnames);
- dbg_packet("Compression offsets: %p\n", pkt->compression.offsets);
+ dbg_packet_detail("Compression dnames: %p\n", pkt->compression.dnames);
+ dbg_packet_detail("Compression offsets: %p\n", pkt->compression.offsets);
pkt->compression.max = DEFAULT_DOMAINS_IN_RESPONSE;
pkt->compression.default_count = DEFAULT_DOMAINS_IN_RESPONSE;
@@ -118,8 +119,8 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->wildcard_nodes.snames = (const knot_dname_t **)pos;
pos += DEFAULT_WILDCARD_NODES * sizeof(knot_dname_t *);
- dbg_packet("Wildcard nodes: %p\n", pkt->wildcard_nodes.nodes);
- dbg_packet("Wildcard SNAMEs: %p\n", pkt->wildcard_nodes.snames);
+ dbg_packet_detail("Wildcard nodes: %p\n", pkt->wildcard_nodes.nodes);
+ dbg_packet_detail("Wildcard SNAMEs: %p\n", pkt->wildcard_nodes.snames);
pkt->wildcard_nodes.default_count = DEFAULT_WILDCARD_NODES;
pkt->wildcard_nodes.max = DEFAULT_WILDCARD_NODES;
@@ -127,7 +128,7 @@ static void knot_packet_init_pointers_response(knot_packet_t *pkt)
pkt->tmp_rrsets = (const knot_rrset_t **)pos;
pos += DEFAULT_TMP_RRSETS * sizeof(const knot_rrset_t *);
- dbg_packet("Tmp rrsets: %p\n", pkt->tmp_rrsets);
+ dbg_packet_detail("Tmp rrsets: %p\n", pkt->tmp_rrsets);
pkt->tmp_rrsets_max = DEFAULT_TMP_RRSETS;
@@ -141,7 +142,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("Packet pointer: %p\n", pkt);
+ dbg_packet_detail("Packet pointer: %p\n", pkt);
char *pos = (char *)pkt + PREALLOC_PACKET;
@@ -149,17 +150,15 @@ static void knot_packet_init_pointers_query(knot_packet_t *pkt)
pkt->question.qname = (knot_dname_t *)pos;
pos += PREALLOC_QNAME_DNAME;
- dbg_packet("QNAME: %p (%zu after start of packet)\n",
- pkt->question.qname,
- (void *)pkt->question.qname - (void *)pkt);
+ dbg_packet_detail("QNAME: %p (%zu after start of packet)\n",
+ pkt->question.qname,
+ (void *)pkt->question.qname - (void *)pkt);
pkt->question.qname->name = (uint8_t *)pos;
pos += PREALLOC_QNAME_NAME;
pkt->question.qname->labels = (uint8_t *)pos;
pos += PREALLOC_QNAME_LABELS;
-// pkt->owner_tmp = (uint8_t *)((char *)pkt->question.qname->labels
-// + PREALLOC_QNAME_LABELS);
// then answer, authority and additional sections
if (DEFAULT_ANCOUNT_QUERY == 0) {
@@ -183,9 +182,9 @@ static void knot_packet_init_pointers_query(knot_packet_t *pkt)
pos += DEFAULT_ARCOUNT_QUERY * sizeof(const knot_rrset_t *);
}
- dbg_packet("Answer section: %p\n", pkt->answer);
- dbg_packet("Authority section: %p\n", pkt->authority);
- dbg_packet("Additional section: %p\n", pkt->additional);
+ dbg_packet_detail("Answer section: %p\n", pkt->answer);
+ dbg_packet_detail("Authority section: %p\n", pkt->authority);
+ dbg_packet_detail("Additional section: %p\n", pkt->additional);
pkt->max_an_rrsets = DEFAULT_ANCOUNT_QUERY;
pkt->max_ns_rrsets = DEFAULT_NSCOUNT_QUERY;
@@ -194,15 +193,11 @@ static void knot_packet_init_pointers_query(knot_packet_t *pkt)
pkt->tmp_rrsets = (const knot_rrset_t **)pos;
pos += DEFAULT_TMP_RRSETS_QUERY * sizeof(const knot_rrset_t *);
- dbg_packet("Tmp rrsets: %p\n", pkt->tmp_rrsets);
+ dbg_packet_detail("Tmp rrsets: %p\n", pkt->tmp_rrsets);
pkt->tmp_rrsets_max = DEFAULT_TMP_RRSETS_QUERY;
-// dbg_packet("End of data: %p (%zu after start of packet)\n",
-// pkt->tmp_rrsets + DEFAULT_TMP_RRSETS_QUERY,
-// (void *)(pkt->tmp_rrsets + DEFAULT_TMP_RRSETS_QUERY)
-// - (void *)pkt);
- dbg_packet("Allocated total: %u\n", PREALLOC_QUERY);
+ dbg_packet_detail("Allocated total: %u\n", PREALLOC_QUERY);
assert(pos == (char *)pkt + PREALLOC_QUERY);
}
@@ -230,7 +225,7 @@ static int knot_packet_parse_header(const uint8_t *wire, size_t *pos,
assert(header != NULL);
if (size - *pos < KNOT_WIRE_HEADER_SIZE) {
- dbg_response("Not enough data to parse header.\n");
+ dbg_packet("Not enough data to parse header.\n");
return KNOT_EFEWDATA;
}
@@ -238,10 +233,8 @@ static int knot_packet_parse_header(const uint8_t *wire, size_t *pos,
// 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);
-// knot_wire_flags_set_qr(&header->flags1);
-// knot_wire_flags_clear_aa(&header->flags1);
-// knot_wire_flags_clear_tc(&header->flags1);
// do not copy flags2 (all set by server)
+
header->qdcount = knot_wire_get_qdcount(wire);
header->ancount = knot_wire_get_ancount(wire);
header->nscount = knot_wire_get_nscount(wire);
@@ -276,12 +269,11 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos,
assert(question != NULL);
if (size - *pos < KNOT_WIRE_QUESTION_MIN_SIZE) {
- dbg_response("Not enough data to parse question.\n");
+ dbg_packet("Not enough data to parse question.\n");
return KNOT_EFEWDATA; // malformed
}
- dbg_response("Parsing Question starting on position %zu.\n",
- *pos);
+ dbg_packet("Parsing Question starting on position %zu.\n", *pos);
// domain name must end with 0, so just search for 0
int i = *pos;
@@ -290,13 +282,13 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos,
}
if (size - i - 1 < 4) {
- dbg_response("Not enough data to parse question.\n");
+ dbg_packet("Not enough data to parse question.\n");
return KNOT_EFEWDATA; // no 0 found or not enough data left
}
- dbg_response("Parsing dname starting on position %zu and "
+ dbg_packet_verb("Parsing dname starting on position %zu and "
"%zu bytes long.\n", *pos, i - *pos + 1);
- dbg_response("Alloc: %d\n", alloc);
+ dbg_packet_verb("Alloc: %d\n", alloc);
if (alloc) {
question->qname = knot_dname_new_from_wire(
wire + *pos, i - *pos + 1, NULL);
@@ -314,10 +306,7 @@ static int knot_packet_parse_question(const uint8_t *wire, size_t *pos,
*pos = i + 1;
question->qtype = knot_wire_read_u16(wire + i + 1);
- //*pos += 2;
question->qclass = knot_wire_read_u16(wire + i + 3);
- //*pos += 2;
-
*pos += 4;
return KNOT_EOK;
@@ -340,7 +329,7 @@ static int knot_packet_realloc_rrsets(const knot_rrset_t ***rrsets,
short *max_count,
short default_max_count, short step)
{
- dbg_packet("Max count: %d, default max count: %d\n",
+ dbg_packet_verb("Max count: %d, default max count: %d\n",
*max_count, default_max_count);
int free_old = (*max_count) != default_max_count;
const knot_rrset_t **old = *rrsets;
@@ -368,11 +357,6 @@ 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)
{
-// if (desc->type == 0) {
-// dbg_packet("Unknown RR type.\n");
-// return NULL;
-// }
-
knot_rdata_t *rdata = knot_rdata_new();
if (rdata == NULL) {
return NULL;
@@ -383,7 +367,7 @@ static knot_rdata_t *knot_packet_parse_rdata(const uint8_t *wire,
if (rc != KNOT_EOK) {
dbg_packet("rdata_from_wire() returned: %s\n",
- knot_strerror(rc));
+ knot_strerror(rc));
knot_rdata_free(&rdata);
return NULL;
}
@@ -396,38 +380,32 @@ static knot_rdata_t *knot_packet_parse_rdata(const uint8_t *wire,
static knot_rrset_t *knot_packet_parse_rr(const uint8_t *wire, size_t *pos,
size_t size)
{
-// knot_rrset_t *rrset =
-// (knot_rrset_t *)malloc(sizeof(knot_rrset_t));
-// CHECK_ALLOC_LOG(rrset, NULL);
-
dbg_packet("Parsing RR from position: %zu, total size: %zu\n",
- *pos, size);
+ *pos, size);
knot_dname_t *owner = knot_dname_parse_from_wire(wire, pos, size,
NULL);
- dbg_packet("Created owner: %p, actual position: %zu\n", owner,
+ dbg_packet_detail("Created owner: %p, actual position: %zu\n", owner,
*pos);
if (owner == NULL) {
return NULL;
}
-dbg_packet_exec(
+dbg_packet_exec_verb(
char *name = knot_dname_to_str(owner);
- dbg_packet("Parsed name: %s\n", name);
+ dbg_packet_verb("Parsed name: %s\n", name);
free(name);
);
- //*remaining -= knot_dname_size(rrset->owner);
-
/*! @todo Get rid of the numerical constant. */
if (size - *pos < 10) {
dbg_packet("Malformed RR: Not enough data to parse RR"
- " header.\n");
+ " header.\n");
knot_dname_release(owner);
return NULL;
}
- dbg_packet("Reading type from position %zu\n", *pos);
+ dbg_packet_detail("Reading type from position %zu\n", *pos);
uint16_t type = knot_wire_read_u16(wire + *pos);
uint16_t rclass = knot_wire_read_u16(wire + *pos + 2);
@@ -445,7 +423,7 @@ dbg_packet_exec(
uint16_t rdlength = knot_wire_read_u16(wire + *pos + 8);
- dbg_packet("Read RR header: type %u, class %u, ttl %u, "
+ dbg_packet_detail("Read RR header: type %u, class %u, ttl %u, "
"rdlength %u\n", rrset->type, rrset->rclass,
rrset->ttl, rdlength);
@@ -453,10 +431,8 @@ dbg_packet_exec(
if (size - *pos < rdlength) {
dbg_packet("Malformed RR: Not enough data to parse RR"
- " RDATA (size: %zu, position: %zu).\n",
- size, *pos);
+ " RDATA (size: %zu, position: %zu).\n", size, *pos);
knot_rrset_deep_free(&rrset, 1, 1, 0);
-// free(rrset);
return NULL;
}
@@ -473,16 +449,13 @@ dbg_packet_exec(
if (rdata == NULL) {
dbg_packet("Malformed RR: Could not parse RDATA.\n");
knot_rrset_deep_free(&rrset, 1, 1, 0);
-// free(rrset);
return NULL;
}
if (knot_rrset_add_rdata(rrset, rdata) != KNOT_EOK) {
- dbg_packet("Malformed RR: Could not add RDATA to RRSet"
- ".\n");
+ dbg_packet("Malformed RR: Could not add RDATA to RRSet.\n");
knot_rdata_free(&rdata);
knot_rrset_deep_free(&rrset, 1, 1, 0);
-// free(rrset);
return NULL;
}
@@ -492,23 +465,22 @@ dbg_packet_exec(
/*----------------------------------------------------------------------------*/
static int knot_packet_add_rrset(knot_rrset_t *rrset,
- const knot_rrset_t ***rrsets,
- short *rrset_count,
- short *max_rrsets,
- short default_rrsets,
- const knot_packet_t *packet,
- knot_packet_duplicate_handling_t dupl)
+ const knot_rrset_t ***rrsets,
+ short *rrset_count,
+ short *max_rrsets,
+ short default_rrsets,
+ const knot_packet_t *packet,
+ knot_packet_duplicate_handling_t dupl)
{
-
assert(rrset != NULL);
assert(rrsets != NULL);
assert(rrset_count != NULL);
assert(max_rrsets != NULL);
-dbg_packet_exec(
+dbg_packet_exec_verb(
char *name = knot_dname_to_str(rrset->owner);
- dbg_packet("packet_add_rrset(), owner: %s, type: %s\n",
- name, knot_rrtype_to_string(rrset->type));
+ dbg_packet_verb("packet_add_rrset(), owner: %s, type: %s\n",
+ name, knot_rrtype_to_string(rrset->type));
free(name);
);
@@ -529,19 +501,20 @@ dbg_packet_exec(
// try to find the RRSet in this array of RRSets
for (int i = 0; i < *rrset_count; ++i) {
-dbg_packet_exec(
+dbg_packet_exec_detail(
char *name = knot_dname_to_str((*rrsets)[i]->owner);
- dbg_packet("Comparing to RRSet: owner: %s, "
- "type: %s\n", name,
- knot_rrtype_to_string(
- (*rrsets)[i]->type));
+ dbg_packet_detail("Comparing to RRSet: owner: %s, "
+ "type: %s\n", name,
+ knot_rrtype_to_string(
+ (*rrsets)[i]->type));
free(name);
);
if (knot_rrset_compare((*rrsets)[i], rrset,
KNOT_RRSET_COMPARE_HEADER)) {
- //const knot_rrset_t *r = (*rrsets)
/*! \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);
if (rc != KNOT_EOK) {
@@ -561,11 +534,12 @@ dbg_packet_exec(
/*----------------------------------------------------------------------------*/
static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
- size_t size, uint16_t rr_count,
- const knot_rrset_t ***rrsets,
- short *rrset_count, short *max_rrsets,
- short default_rrsets,
- knot_packet_t *packet)
+ size_t size, uint16_t rr_count,
+ uint16_t *parsed_rrs,
+ const knot_rrset_t ***rrsets,
+ short *rrset_count, short *max_rrsets,
+ short default_rrsets,
+ knot_packet_t *packet)
{
assert(pos != NULL);
assert(wire != NULL);
@@ -574,12 +548,7 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
assert(max_rrsets != NULL);
assert(packet != NULL);
- dbg_packet("Parsing RRSets starting on position: %zu\n",
- *pos);
-
-// if (*rrsets == NULL) {
-// knot_packet_realloc_rrsets(rrsets, max_rrsets, 0, 1);
-// }
+ dbg_packet("Parsing RRSets starting on position: %zu\n", *pos);
/*
* The RRs from one RRSet may be scattered in the current section.
@@ -589,7 +558,8 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
int err = KNOT_EOK;
knot_rrset_t *rrset = NULL;
- for (int i = 0; i < rr_count; ++i) {
+ /* Start parsing from the first RR not parsed. */
+ for (int i = *parsed_rrs; i < rr_count; ++i) {
rrset = knot_packet_parse_rr(wire, pos, size);
if (rrset == NULL) {
dbg_packet("Failed to parse RR!\n");
@@ -597,13 +567,15 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
break;
}
+ ++(*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,
+ KNOT_PACKET_DUPL_MERGE);
if (err < 0) {
break;
} else if (err > 0) { // merged
- dbg_packet("RRSet merged, freeing.\n");
+ dbg_packet_detail("RRSet merged, freeing.\n");
knot_rrset_deep_free(&rrset, 1, 0, 0); // TODO: ok??
continue;
}
@@ -616,6 +588,23 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
knot_rrset_deep_free(&rrset, 1, 1, 1);
break;
}
+
+ if (knot_rrset_type(rrset) == KNOT_RRTYPE_TSIG) {
+ // if there is some TSIG already, treat as malformed
+ if (knot_packet_tsig(packet) != NULL) {
+ err = KNOT_EMALF;
+ break;
+ }
+
+ // First check the format of the TSIG RR
+ if (!tsig_rdata_is_ok(rrset)) {
+ err = KNOT_EMALF;
+ break;
+ }
+
+ // store the TSIG into the packet
+ knot_packet_set_tsig(packet, rrset);
+ }
}
return (err < 0) ? err : KNOT_EOK;
@@ -630,9 +619,9 @@ static int knot_packet_parse_rrs(const uint8_t *wire, size_t *pos,
*/
static void knot_packet_free_allocated_space(knot_packet_t *pkt)
{
- dbg_packet("Freeing additional space in packet.\n");
+ dbg_packet_verb("Freeing additional space in packet.\n");
if (pkt->prealloc_type == KNOT_PACKET_PREALLOC_NONE) {
- dbg_packet("Freeing QNAME.\n");
+ dbg_packet_detail("Freeing QNAME.\n");
knot_dname_release(pkt->question.qname);
}
@@ -674,37 +663,55 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet,
int err;
- dbg_packet("Parsing Answer RRs...\n");
+ assert(packet->tsig_rr == NULL);
+
+ dbg_packet_verb("Parsing Answer RRs...\n");
if ((err = knot_packet_parse_rrs(packet->wireformat, pos,
- packet->size, packet->header.ancount, &packet->answer,
- &packet->an_rrsets, &packet->max_an_rrsets,
+ 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) {
return err;
}
- dbg_packet("Parsing Authority RRs...\n");
+ if (packet->tsig_rr != NULL) {
+ dbg_packet("TSIG in Answer section.\n");
+ return KNOT_EMALF;
+ }
+
+ dbg_packet_verb("Parsing Authority RRs...\n");
if ((err = knot_packet_parse_rrs(packet->wireformat, pos,
- packet->size, packet->header.nscount, &packet->authority,
- &packet->ns_rrsets, &packet->max_ns_rrsets,
+ 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) {
return err;
}
- dbg_packet("Parsing Additional RRs...\n");
+ if (packet->tsig_rr != NULL) {
+ dbg_packet("TSIG in Authority section.\n");
+ return KNOT_EMALF;
+ }
+
+ dbg_packet_verb("Parsing Additional RRs...\n");
if ((err = knot_packet_parse_rrs(packet->wireformat, pos,
- packet->size, packet->header.arcount, &packet->additional,
- &packet->ar_rrsets, &packet->max_ar_rrsets,
+ 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) {
return err;
}
- dbg_packet("Trying to find OPT RR in the packet.\n");
+ // If TSIG is not the last record
+ if (packet->tsig_rr != NULL
+ && packet->ar_rrsets[packet->additional - 1] != packet->tsig_rr) {
+ dbg_packet("TSIG in Additonal section but not last.\n");
+ return KNOT_EMALF;
+ }
+
+ dbg_packet_verb("Trying to find OPT RR in the packet.\n");
for (int i = 0; i < packet->ar_rrsets; ++i) {
assert(packet->additional[i] != NULL);
- if (knot_rrset_type(packet->additional[i])
- == KNOT_RRTYPE_OPT) {
- dbg_packet("Found OPT RR, filling.\n");
+ if (knot_rrset_type(packet->additional[i]) == KNOT_RRTYPE_OPT) {
+ dbg_packet_detail("Found OPT RR, filling.\n");
err = knot_edns_new_from_rr(&packet->opt_rr,
packet->additional[i]);
if (err != KNOT_EOK) {
@@ -717,9 +724,10 @@ static int knot_packet_parse_rr_sections(knot_packet_t *packet,
packet->parsed = *pos;
if (*pos < packet->size) {
- // some trailing garbage; ignore, but log
- dbg_response("Packet: %zu bytes of trailing garbage "
- "in packet.\n", packet->size - (*pos));
+ // If there is some trailing garbage, treat the packet as
+ // malformed
+ dbg_packet_verb("Packet: %zu bytes of trailing garbage "
+ "in packet.\n", packet->size - (*pos));
return KNOT_EMALF;
}
@@ -784,12 +792,14 @@ int knot_packet_parse_from_wire(knot_packet_t *packet,
packet->size = size;
packet->free_wireformat = 0;
- //uint8_t *pos = wireformat;
+ if (size < 2) {
+ return KNOT_EMALF;
+ }
+
size_t pos = 0;
- //size_t remaining = size;
- dbg_packet("Parsing wire format of packet (size %zu).\nHeader\n",
- size);
+ dbg_packet_verb("Parsing wire format of packet (size %zu).\nHeader\n",
+ size);
if ((err = knot_packet_parse_header(wireformat, &pos, size,
&packet->header)) != KNOT_EOK) {
return err;
@@ -797,15 +807,14 @@ int knot_packet_parse_from_wire(knot_packet_t *packet,
packet->parsed = pos;
- dbg_packet("Question (prealloc type: %d)...\n", packet->prealloc_type);
+ dbg_packet_verb("Question (prealloc type: %d)...\n",
+ packet->prealloc_type);
if (packet->header.qdcount > 1) {
dbg_packet("QDCOUNT larger than 1, FORMERR.\n");
return KNOT_EMALF;
}
- knot_packet_dump(packet);
-
if (packet->header.qdcount == 1) {
if ((err = knot_packet_parse_question(wireformat, &pos, size,
&packet->question, packet->prealloc_type
@@ -816,18 +825,20 @@ int knot_packet_parse_from_wire(knot_packet_t *packet,
packet->parsed = pos;
}
+dbg_packet_exec_detail(
knot_packet_dump(packet);
+);
if (question_only) {
return KNOT_EOK;
}
/*! \todo Replace by call to parse_rest()? */
- err = knot_packet_parse_rr_sections(packet, &pos);
+ err = knot_packet_parse_rest(packet);
-#ifdef KNOT_PACKET_DEBUG
+dbg_packet_exec_detail(
knot_packet_dump(packet);
-#endif /* KNOT_RESPONSE_DEBUG */
+);
return err;
}
@@ -840,16 +851,21 @@ int knot_packet_parse_rest(knot_packet_t *packet)
return KNOT_EBADARG;
}
-// if (packet->parsed >= packet->size) {
-// return KNOT_EOK;
-// }
-
- if (packet->parsed == packet->size) {
+ if (packet->header.ancount == packet->parsed_an
+ && packet->header.nscount == packet->parsed_ns
+ && packet->header.arcount == packet->parsed_ar
+ && packet->parsed == packet->size) {
return KNOT_EOK;
}
+
+ // 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);
}
@@ -866,16 +882,16 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet,
if (packet->parsed >= packet->size) {
assert(packet->an_rrsets <= packet->header.ancount);
- if (packet->an_rrsets != packet->header.ancount) {
+ if (packet->parsed_an != packet->header.ancount) {
dbg_packet("Parsed less RRs than expected.\n");
return KNOT_EMALF;
} else {
- dbg_packet("Whole packet parsed\n");
+ dbg_packet_detail("Whole packet parsed\n");
return KNOT_EOK;
}
}
- if (packet->an_rrsets == packet->header.ancount) {
+ 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
@@ -885,19 +901,20 @@ int knot_packet_parse_next_rr_answer(knot_packet_t *packet,
size_t pos = packet->parsed;
- dbg_packet("Parsing next Answer RR (pos: %zu)...\n", pos);
+ dbg_packet_verb("Parsing next Answer RR (pos: %zu)...\n", pos);
*rr = knot_packet_parse_rr(packet->wireformat, &pos, packet->size);
if (*rr == NULL) {
- dbg_packet("Failed to parse RR!\n");
+ dbg_packet_verb("Failed to parse RR!\n");
return KNOT_EMALF;
}
- dbg_packet("Parsed. Pos: %zu.\n", pos);
+ dbg_packet_detail("Parsed. Pos: %zu.\n", pos);
packet->parsed = pos;
// increment the number of answer RRSets, though there are no saved
// in the packet; it is OK, because packet->answer is NULL
++packet->an_rrsets;
+ ++packet->parsed_an;
return KNOT_EOK;
}
@@ -916,37 +933,37 @@ int knot_packet_parse_next_rr_additional(knot_packet_t *packet,
if (packet->parsed >= packet->size) {
assert(packet->ar_rrsets <= packet->header.arcount);
- if (packet->ar_rrsets != packet->header.arcount) {
+ if (packet->parsed_ar != packet->header.arcount) {
dbg_packet("Parsed less RRs than expected.\n");
return KNOT_EMALF;
} else {
- dbg_packet("Whole packet parsed\n");
+ dbg_packet_detail("Whole packet parsed\n");
return KNOT_EOK;
}
}
- if (packet->ar_rrsets == packet->header.arcount) {
+ if (packet->parsed_ar == packet->header.arcount) {
assert(packet->parsed < packet->size);
- dbg_packet("Trailing garbage, ignoring...\n");
- /*! \todo Do not ignore. */
- return KNOT_EOK;
+ dbg_packet_verb("Trailing garbage, treating as malformed...\n");
+ return KNOT_EMALF;
}
size_t pos = packet->parsed;
- dbg_packet("Parsing next Additional RR (pos: %zu)...\n", pos);
+ dbg_packet_verb("Parsing next Additional RR (pos: %zu)...\n", pos);
*rr = knot_packet_parse_rr(packet->wireformat, &pos, packet->size);
if (*rr == NULL) {
- dbg_packet("Failed to parse RR!\n");
+ dbg_packet_verb("Failed to parse RR!\n");
return KNOT_EMALF;
}
- dbg_packet("Parsed. Pos: %zu.\n", pos);
+ dbg_packet_detail("Parsed. Pos: %zu.\n", pos);
packet->parsed = pos;
// increment the number of answer RRSets, though there are no saved
// in the packet; it is OK, because packet->answer is NULL
++packet->ar_rrsets;
+ ++packet->parsed_ar;
return KNOT_EOK;
}
@@ -1186,7 +1203,7 @@ const knot_rrset_t *knot_packet_tsig(const knot_packet_t *packet)
void knot_packet_set_tsig(knot_packet_t *packet, const knot_rrset_t *tsig_rr)
{
- packet->tsig_rr = (knot_rrset_t *)tsig_rr;
+ packet->tsig_rr = (knot_rrset_t *)tsig_rr;
}
/*----------------------------------------------------------------------------*/
@@ -1268,19 +1285,19 @@ int knot_packet_contains(const knot_packet_t *packet,
return KNOT_EBADARG;
}
- for (int i = 0; i < packet->header.ancount; ++i) {
+ for (int i = 0; i < packet->an_rrsets; ++i) {
if (knot_rrset_compare(packet->answer[i], rrset, cmp)) {
return 1;
}
}
- for (int i = 0; i < packet->header.nscount; ++i) {
+ for (int i = 0; i < packet->ns_rrsets; ++i) {
if (knot_rrset_compare(packet->authority[i], rrset, cmp)) {
return 1;
}
}
- for (int i = 0; i < packet->header.arcount; ++i) {
+ for (int i = 0; i < packet->ar_rrsets; ++i) {
if (knot_rrset_compare(packet->additional[i], rrset, cmp)) {
return 1;
}
@@ -1307,8 +1324,8 @@ int knot_packet_add_tmp_rrset(knot_packet_t *packet,
}
packet->tmp_rrsets[packet->tmp_rrsets_count++] = tmp_rrset;
- dbg_packet("Current tmp RRSets count: %d, max count: %d\n",
- packet->tmp_rrsets_count, packet->tmp_rrsets_max);
+ dbg_packet_detail("Current tmp RRSets count: %d, max count: %d\n",
+ packet->tmp_rrsets_count, packet->tmp_rrsets_max);
return KNOT_EOK;
}
@@ -1329,7 +1346,7 @@ void knot_packet_free_tmp_rrsets(knot_packet_t *pkt)
dbg_packet_exec(
char *name = knot_dname_to_str(
(((knot_rrset_t **)(pkt->tmp_rrsets))[i])->owner);
- dbg_packet("Freeing tmp RRSet on ptr: %p (ptr to ptr:"
+ dbg_packet_verb("Freeing tmp RRSet on ptr: %p (ptr to ptr:"
" %p, type: %s, owner: %s)\n",
(((knot_rrset_t **)(pkt->tmp_rrsets))[i]),
&(((knot_rrset_t **)(pkt->tmp_rrsets))[i]),
@@ -1394,14 +1411,6 @@ int knot_packet_question_to_wire(knot_packet_t *packet)
pos += 2;
knot_wire_write_u16(pos, packet->question.qclass);
-// int err = 0;
- // TODO: put the qname into the compression table
-// // TODO: get rid of the numeric constants
-// if ((err = knot_response_store_dname_pos(&packet->compression,
-// packet->question.qname,0, 12, 12)) != KNOT_EOK) {
-// return err;
-// }
-
packet->size += knot_dname_size(packet->question.qname) + 4;
return KNOT_EOK;
@@ -1486,8 +1495,6 @@ void knot_packet_free(knot_packet_t **packet)
knot_packet_free_allocated_space(*packet);
// free the space for wireformat
-// assert((*packet)->wireformat != NULL);
-// free((*packet)->wireformat);
if ((*packet)->wireformat != NULL && (*packet)->free_wireformat) {
free((*packet)->wireformat);
}
diff --git a/src/libknot/packet/packet.h b/src/libknot/packet/packet.h
index 9e37c12..d76209a 100644..100755
--- a/src/libknot/packet/packet.h
+++ b/src/libknot/packet/packet.h
@@ -138,6 +138,9 @@ struct knot_packet {
short free_wireformat;
size_t parsed;
+ uint16_t parsed_an;
+ uint16_t parsed_ns;
+ uint16_t parsed_ar;
size_t size; /*!< Current wire size of the packet. */
size_t max_size; /*!< Maximum allowed size of the packet. */
diff --git a/src/libknot/packet/query.c b/src/libknot/packet/query.c
index b76059b..bc3a4db 100644..100755
--- a/src/libknot/packet/query.c
+++ b/src/libknot/packet/query.c
@@ -209,7 +209,7 @@ int knot_query_add_rrset_authority(knot_packet_t *query,
// reserve space for OPT RR
/*! \todo Why here??? */
endp -= query->opt_rr.size;
- /*! \note [TSIG] reserve space for TSIG RR */
+ /* Reserve space for TSIG RR */
endp -= query->tsig_size;
uint8_t *pos = startp;
diff --git a/src/libknot/packet/query.h b/src/libknot/packet/query.h
index a979641..cda72b9 100644..100755
--- a/src/libknot/packet/query.h
+++ b/src/libknot/packet/query.h
@@ -61,12 +61,6 @@ int knot_query_nsid_requested(const knot_packet_t *query);
int knot_query_edns_supported(const knot_packet_t *query);
-//int knot_query_set_qname(knot_packet_t *query, const knot_dname_t *qname);
-
-//int knot_query_set_qtype(knot_packet_t *query, uint16_t qtype);
-
-//int knot_query_set_qclass(knot_packet_t *query, uint16_t qclass);
-
int knot_query_init(knot_packet_t *query);
int knot_query_set_question(knot_packet_t *query,
diff --git a/src/libknot/packet/response.c b/src/libknot/packet/response.c
index 9f6277c..bb4d0f2 100644..100755
--- a/src/libknot/packet/response.c
+++ b/src/libknot/packet/response.c
@@ -164,15 +164,14 @@ static int knot_response_store_dname_pos(knot_compressed_dnames_t *table,
{
dbg_response_exec(
char *name = knot_dname_to_str(dname);
- dbg_response("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);
+ 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");
+ dbg_response("Pointer larger than it can be, not saving\n");
return KNOT_EDNAMEPTR;
}
@@ -181,11 +180,6 @@ dbg_response_exec(
return KNOT_ENOMEM;
}
- // store the position of the name
-// table->dnames[table->count] = dname;
-// table->offsets[table->count] = pos;
-// ++table->count;
-
/*
* Store positions of ancestors if more than 1 label was not matched.
*
@@ -210,11 +204,11 @@ dbg_response_exec(
parent_pos = unmatched_offset;
}
-dbg_response_exec(
+dbg_response_exec_detail(
char *name = knot_dname_to_str(to_save);
- dbg_response("Putting dname %s into compression table."
- " Position: %zu, pointer: %p\n",
- name, parent_pos, to_save);
+ dbg_response_detail("Putting dname %s into compression table."
+ " Position: %zu, pointer: %p\n",
+ name, parent_pos, to_save);
free(name);
);
@@ -224,7 +218,6 @@ dbg_response_exec(
return KNOT_ENOMEM;
}
-// dbg_response("Saving..\n");
knot_response_compr_save(table, to_save, parent_pos);
/*! \todo Remove '!compr_cs'. */
@@ -234,16 +227,23 @@ dbg_response_exec(
// If case-sensitive search is in place, we should not save the
// node's parent's positions.
- to_save = !compr_cs && (knot_dname_node(to_save) != NULL
- && knot_node_parent(knot_dname_node(to_save))
- != NULL) ? knot_node_owner(knot_node_parent(
+ // 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!
+ */
+ to_save = (!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;
+ : NULL;
dbg_response("i: %d\n", i);
parent_pos += knot_dname_label_size(dname, i) + 1;
-// parent_pos += (i > 0)
-// ? knot_dname_label_size(dname, i - 1) + 1 : 0;
++i;
}
@@ -267,22 +267,12 @@ static size_t knot_response_find_dname_pos(
const knot_dname_t *dname, int compr_cs)
{
for (int i = 0; i < table->count; ++i) {
-// dbg_response("Comparing dnames %p and %p\n",
-// dname, table->dnames[i]);
-//dbg_response_exec(
-// char *name = knot_dname_to_str(dname);
-// dbg_response("(%s and ", name);
-// name = knot_dname_to_str(table->dnames[i]);
-// dbg_response("%s)\n", name);
-// free(name);
-//);
- //if (table->dnames[i] == dname) {
int ret = (compr_cs)
? knot_dname_compare_cs(table->dnames[i], dname)
: knot_dname_compare(table->dnames[i], dname);
if (ret == 0) {
- dbg_response("Found offset: %zu\n",
- table->offsets[i]);
+ dbg_response_detail("Found offset: %zu\n",
+ table->offsets[i]);
return table->offsets[i];
}
}
@@ -319,7 +309,7 @@ static int knot_response_put_dname_ptr(const knot_dname_t *dname,
memcpy(wire, knot_dname_name(dname), size);
knot_wire_put_pointer(wire + size, offset);
- dbg_response("Size of the dname with ptr: %d\n", size + 2);
+ dbg_response_detail("Size of the dname with ptr: %d\n", size + 2);
return size + 2;
}
@@ -343,15 +333,9 @@ 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 size = 0;
- /*!
- * \todo Compress!!
- *
- * if pos == 0, do not store the position!
- */
// try to find the name or one of its ancestors in the compr. table
#ifdef COMPRESSION_PEDANTIC
- //knot_dname_t *to_find = knot_dname_copy(dname);
knot_dname_t *to_find = (knot_dname_t *)dname;
int copied = 0;
#else
@@ -361,11 +345,11 @@ static int knot_response_compress_dname(const knot_dname_t *dname,
int not_matched = 0;
while (to_find != NULL && knot_dname_label_count(to_find) != 0) {
-dbg_response_exec(
+dbg_response_exec_detail(
char *name = knot_dname_to_str(to_find);
- dbg_response("Searching for name %s in the compression"
- " table, not matched labels: %d\n", name,
- not_matched);
+ 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,
@@ -396,17 +380,17 @@ dbg_response_exec(
|| knot_node_owner(knot_dname_node(to_find)) != to_find
|| knot_node_parent(knot_dname_node(to_find))
== NULL) {
- dbg_response("compr_cs: %d\n", compr_cs);
- dbg_response("knot_dname_node(to_find, 1) == %p"
+ 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("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("knot_node_parent(knot_dname_node("
- "to_find, 1), 1) = %p\n",
+ 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;
@@ -417,7 +401,7 @@ dbg_response_exec(
knot_node_parent(knot_dname_node(to_find))));
to_find = knot_node_owner(
knot_node_parent(knot_dname_node(to_find)));
- dbg_response("New to_find: %p\n", to_find);
+ dbg_response_detail("New to_find: %p\n", to_find);
}
#endif
}
@@ -428,10 +412,10 @@ dbg_response_exec(
}
#endif
- dbg_response("Max size available for domain name: %zu\n", max);
+ dbg_response_detail("Max size available for domain name: %zu\n", max);
if (offset > 0) { // found such dname somewhere in the packet
- dbg_response("Found name in the compression table.\n");
+ 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);
@@ -439,7 +423,7 @@ dbg_response_exec(
return KNOT_ESPACE;
}
} else {
- dbg_response("Not found, putting whole name.\n");
+ dbg_response_detail("Not found, putting whole name.\n");
// now just copy the dname without compressing
if (dname->size > max) {
return KNOT_ESPACE;
@@ -458,8 +442,7 @@ dbg_response_exec(
if (knot_response_store_dname_pos(compr->table, dname, not_matched,
compr->wire_pos, offset, compr_cs)
!= 0) {
- dbg_response("Compression info could not be stored."
- "\n");
+ dbg_response_detail("Compression info could not be stored.\n");
}
return size;
@@ -488,7 +471,7 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
{
int size = 0;
- dbg_response("Max size: %zu, owner pos: %zu, owner size: %d\n",
+ 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
@@ -498,7 +481,7 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
return KNOT_ESPACE;
}
- dbg_response("Owner position: %zu\n", compr->owner.pos);
+ 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) {
@@ -507,28 +490,28 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
*rrset_wire += compr->owner.size;
size += compr->owner.size;
} else {
- dbg_response("Putting pointer: %zu\n",
- compr->owner.pos);
+ 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("Max size: %zu, size: %d\n", max_size, size);
+ dbg_response_detail("Max size: %zu, size: %d\n", max_size, size);
- dbg_response("Wire format:\n");
+ dbg_response_detail("Wire format:\n");
// put rest of RR 'header'
knot_wire_write_u16(*rrset_wire, rrset->type);
- dbg_response(" Type: %u\n", rrset->type);
+ dbg_response_detail(" Type: %u\n", rrset->type);
*rrset_wire += 2;
knot_wire_write_u16(*rrset_wire, rrset->rclass);
- dbg_response(" Class: %u\n", rrset->rclass);
+ dbg_response_detail(" Class: %u\n", rrset->rclass);
*rrset_wire += 2;
knot_wire_write_u32(*rrset_wire, rrset->ttl);
- dbg_response(" TTL: %u\n", rrset->ttl);
+ dbg_response_detail(" TTL: %u\n", rrset->ttl);
*rrset_wire += 4;
// save space for RDLENGTH
@@ -538,7 +521,7 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
size += 10;
compr->wire_pos += size;
- dbg_response("Max size: %zu, size: %d\n", max_size, 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);
@@ -561,8 +544,7 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
return KNOT_ESPACE;
}
- dbg_response("Compressed dname size: %d\n",
- ret);
+ dbg_response_detail("Compressed dname size: %d\n", ret);
*rrset_wire += ret;
rdlength += ret;
compr->wire_pos += ret;
@@ -579,8 +561,8 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
// save whole domain name
memcpy(*rrset_wire, dname->name, dname->size);
- dbg_response("Uncompressed dname size: %d\n",
- dname->size);
+ dbg_response_detail("Uncompressed dname size: %d\n",
+ dname->size);
*rrset_wire += dname->size;
rdlength += dname->size;
compr->wire_pos += dname->size;
@@ -596,8 +578,8 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
// copy just the rdata item data (without size)
memcpy(*rrset_wire, raw_data + 1, raw_data[0]);
- dbg_response("Raw data size: %d\n",
- 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];
@@ -606,7 +588,7 @@ static int knot_response_rr_to_wire(const knot_rrset_t *rrset,
}
}
- dbg_response("Max size: %zu, size: %d\n", max_size, size);
+ dbg_response_detail("Max size: %zu, size: %d\n", max_size, size);
assert(size + rdlength <= max_size);
size += rdlength;
@@ -639,12 +621,12 @@ static int knot_response_rrset_to_wire(const knot_rrset_t *rrset,
knot_compressed_dnames_t *compr,
int compr_cs)
{
-dbg_response_exec(
+dbg_response_exec_verb(
char *name = knot_dname_to_str(rrset->owner);
- dbg_response("Converting RRSet with owner %s, type %s\n",
- name, knot_rrtype_to_string(rrset->type));
+ dbg_response_verb("Converting RRSet with owner %s, type %s\n",
+ name, knot_rrtype_to_string(rrset->type));
free(name);
- dbg_response(" Size before: %zu\n", *size);
+ dbg_response_verb(" Size before: %zu\n", *size);
);
// if no RDATA in RRSet, return
@@ -652,10 +634,6 @@ dbg_response_exec(
return KNOT_EOK;
}
- //uint8_t *rrset_wire = (uint8_t *)malloc(PREALLOC_RRSET_WIRE);
- //short rrset_size = 0;
-
- //uint8_t *owner_wire = (uint8_t *)malloc(rrset->owner->size);
/*
* We may pass the current position to the compression function
* because if the owner will be put somewhere, it will be on the
@@ -665,7 +643,6 @@ dbg_response_exec(
*/
knot_compr_t compr_info;
- //compr_info.new_entries = 0;
compr_info.table = compr;
compr_info.wire_pos = wire_pos;
compr_info.owner.pos = 0;
@@ -674,8 +651,8 @@ dbg_response_exec(
knot_response_compress_dname(rrset->owner, &compr_info,
owner_tmp, max_size, compr_cs);
- dbg_response(" Owner size: %d, position: %zu\n",
- compr_info.owner.size, compr_info.owner.pos);
+ 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;
}
@@ -698,20 +675,17 @@ dbg_response_exec(
return KNOT_ESPACE;
}
- dbg_response("RR of size %d added.\n", ret);
+ dbg_response_verb("RR of size %d added.\n", ret);
rrset_size += ret;
++rrs;
} while ((rdata = knot_rrset_rdata_next(rrset, rdata)) != NULL);
- //memcpy(*pos, rrset_wire, rrset_size);
- //*size += rrset_size;
- //*pos += rrset_size;
// the whole RRSet did fit in
assert (rrset_size <= max_size);
*size += rrset_size;
- dbg_response(" Size after: %zu\n", *size);
+ dbg_response_verb(" Size after: %zu\n", *size);
return rrs;
}
@@ -750,8 +724,8 @@ static int knot_response_try_add_rrset(const knot_rrset_t **rrsets,
dbg_response_exec(
char *name = knot_dname_to_str(rrset->owner);
- dbg_response("\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 %s: \n",
+ name, knot_rrtype_to_string(rrset->type));
free(name);
);
@@ -764,11 +738,11 @@ dbg_response_exec(
if (rrs >= 0) {
rrsets[(*rrset_count)++] = rrset;
resp->size += size;
- dbg_response("RRset added, size: %zu, RRs: %d, total "
- "size of response: %zu\n\n", size, rrs,
- resp->size);
+ dbg_response_verb("RRset added, size: %zu, RRs: %d, total "
+ "size of response: %zu\n\n", size, rrs,
+ resp->size);
} else if (tc) {
- dbg_response("Setting TC bit.\n");
+ dbg_response_verb("Setting TC bit.\n");
knot_wire_flags_set_tc(&resp->header.flags1);
knot_wire_set_tc(resp->wireformat);
}
@@ -825,8 +799,8 @@ static int knot_response_realloc_wc_nodes(const knot_node_t ***nodes,
short *max_count,
short default_max_count, short step)
{
- dbg_packet("Max count: %d, default max count: %d\n",
- *max_count, default_max_count);
+ dbg_packet_detail("Max count: %d, default max count: %d\n",
+ *max_count, default_max_count);
int free_old = (*max_count) != default_max_count;
const knot_node_t **old_nodes = *nodes;
@@ -896,13 +870,10 @@ 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));
-// memmove(&response->header, &query->header, sizeof(knot_header_t));
// copy the Question section (but do not copy the QNAME)
memcpy(&response->question, &query->question,
sizeof(knot_question_t));
-// memmove(&response->question, &query->question,
-// sizeof(knot_question_t));
int err = 0;
// put the qname into the compression table
@@ -917,18 +888,16 @@ int knot_response_init_from_query(knot_packet_t *response,
size_t to_copy = 12 + 4 + knot_dname_size(response->question.qname);
assert(response->max_size >= to_copy);
-// printf("Resp init from query: Copying from: %p to: %p size: %d\n",
-// response->wireformat, query->wireformat,
-// to_copy);
-// printf("Resp init from query: Question name size: %d Query name size: %d\n",
-// knot_dname_size(response->question.qname),
-// knot_dname_size(query->question.qname));
memcpy(response->wireformat, query->wireformat, to_copy);
response->size = to_copy;
// set the qr bit to 1
knot_wire_flags_set_qr(&response->header.flags1);
knot_wire_set_qr(response->wireformat);
+
+ // 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);
@@ -940,8 +909,11 @@ int knot_response_init_from_query(knot_packet_t *response,
// set counts to 0
response->header.ancount = 0;
+ knot_wire_set_ancount(response->wireformat, 0);
response->header.nscount = 0;
+ knot_wire_set_nscount(response->wireformat, 0);
response->header.arcount = 0;
+ knot_wire_set_arcount(response->wireformat, 0);
response->query = query;
@@ -1039,16 +1011,14 @@ int knot_response_add_opt(knot_packet_t *resp,
if (override_max_size && resp->max_size > 0
&& resp->max_size < opt_rr->payload) {
-// return KNOT_EPAYLOAD;
return KNOT_EOK;
}
// set max size (less is OK)
if (override_max_size) {
dbg_response("Overriding max size to: %u\n",
- resp->opt_rr.payload);
+ resp->opt_rr.payload);
return knot_packet_set_max_size(resp, resp->opt_rr.payload);
- //resp->max_size = resp->opt_rr.payload;
}
return KNOT_EOK;
@@ -1065,7 +1035,7 @@ int knot_response_add_rrset_answer(knot_packet_t *response,
return KNOT_EBADARG;
}
- dbg_response("add_rrset_answer()\n");
+ dbg_response_verb("add_rrset_answer()\n");
assert(response->header.arcount == 0);
assert(response->header.nscount == 0);
@@ -1081,9 +1051,9 @@ int knot_response_add_rrset_answer(knot_packet_t *response,
return KNOT_EOK;
}
- dbg_response("Trying to add RRSet to Answer section.\n");
- dbg_response("RRset: %p\n", rrset);
- dbg_response("Owner: %p\n", rrset->owner);
+ dbg_response_verb("Trying to add RRSet to Answer section.\n");
+ dbg_response_detail("RRset: %p\n", rrset);
+ dbg_response_detail("Owner: %p\n", rrset->owner);
int rrs = knot_response_try_add_rrset(response->answer,
&response->an_rrsets, response,
@@ -1132,7 +1102,7 @@ int knot_response_add_rrset_authority(knot_packet_t *response,
return KNOT_EOK;
}
- dbg_response("Trying to add RRSet to Authority section.\n");
+ dbg_response_verb("Trying to add RRSet to Authority section.\n");
int rrs = knot_response_try_add_rrset(response->authority,
&response->ns_rrsets, response,
@@ -1188,7 +1158,7 @@ int knot_response_add_rrset_additional(knot_packet_t *response,
return KNOT_EOK;
}
- dbg_response("Trying to add RRSet to Additional section.\n");
+ dbg_response_verb("Trying to add RRSet to Additional section.\n");
int rrs = knot_response_try_add_rrset(response->additional,
&response->ar_rrsets, response,
@@ -1283,7 +1253,7 @@ int knot_response_add_wildcard_node(knot_packet_t *response,
response->wildcard_nodes.snames[response->wildcard_nodes.count] = sname;
++response->wildcard_nodes.count;
- dbg_response("Current wildcard nodes count: %d, max count: %d\n",
+ dbg_response_verb("Current wildcard nodes count: %d, max count: %d\n",
response->wildcard_nodes.count,
response->wildcard_nodes.max);
diff --git a/src/libknot/packet/response.h b/src/libknot/packet/response.h
index d3e66f3..d3e66f3 100644..100755
--- a/src/libknot/packet/response.h
+++ b/src/libknot/packet/response.h
diff --git a/src/libknot/rdata.c b/src/libknot/rdata.c
index 8e9e8c1..1cdd339 100644..100755
--- a/src/libknot/rdata.c
+++ b/src/libknot/rdata.c
@@ -210,8 +210,8 @@ knot_rdata_t *knot_rdata_new()
/*----------------------------------------------------------------------------*/
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)
+ size_t *pos, size_t total_size, size_t rdlength,
+ const knot_rrtype_descriptor_t *desc)
{
int i = 0;
uint8_t item_type;
@@ -249,7 +249,6 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
return KNOT_ERROR;
}
items[i].dname = dname;
- //*pos += dname->size;
parsed += pos2 - *pos;
*pos = pos2;
dname = 0;
@@ -309,7 +308,6 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
break;
case 3:
pos2 = *pos;
- //fprintf(stderr, "reading dname from pos: %zu\n", pos2);
dname = knot_dname_parse_from_wire(
wire, &pos2, total_size, NULL);
if (dname == NULL) {
@@ -331,12 +329,9 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
memcpy((uint8_t *)(items[i].raw_data + 1),
knot_dname_name(dname),
knot_dname_size(dname));
-
-// items[i].dname = dname;
- //*pos += dname->size;
+
parsed += pos2 - *pos;
-
- //fprintf(stderr, "read %zu bytes.\n", parsed);
+
*pos = pos2;
knot_dname_free(&dname);
@@ -374,9 +369,7 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
memcpy(items[i].raw_data + 1, wire + *pos, item_size);
*pos += item_size;
parsed += item_size;
- } else if (item_type == KNOT_RDATA_WF_BINARY/*
- || item_type == KNOT_RDATA_WF_IPSECGATEWAY*/) {
-// fprintf(stderr, "item_size was 0, creating empty rdata item.\n");
+ } 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);
@@ -389,8 +382,6 @@ int knot_rdata_from_wire(knot_rdata_t *rdata, const uint8_t *wire,
} else if (item_type != KNOT_RDATA_WF_COMPRESSED_DNAME
&& item_type != KNOT_RDATA_WF_UNCOMPRESSED_DNAME
&& item_type != KNOT_RDATA_WF_LITERAL_DNAME) {
-// fprintf(stderr, "RDATA item not set (i: %d), type: %u"
-// " RDATA item type: %d\n", i, desc->type ,item_type);
assert(0);
}
@@ -519,6 +510,25 @@ int knot_rdata_item_set_raw_data(knot_rdata_t *rdata, uint pos,
/*----------------------------------------------------------------------------*/
+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) {
@@ -541,134 +551,16 @@ void knot_rdata_deep_free(knot_rdata_t **rdata, uint type,
return;
}
- knot_rdata_free_items((*rdata)->items, (*rdata)->count, type,
- free_all_dnames);
+ if ((*rdata)->items != NULL) {
+ knot_rdata_free_items((*rdata)->items, (*rdata)->count, type,
+ free_all_dnames);
+ }
free(*rdata);
*rdata = NULL;
}
/*----------------------------------------------------------------------------*/
-/* CLEANUP */
-//uint knot_rdata_wire_size(const knot_rdata_t *rdata,
-// const uint8_t *format)
-//{
-// uint size = 0;
-
-// for (int i = 0; i < rdata->count; ++i) {
-// switch (format[i]) {
-// case KNOT_RDATA_WF_COMPRESSED_DNAME:
-// case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
-// case KNOT_RDATA_WF_LITERAL_DNAME:
-// size += knot_dname_size(rdata->items[i].dname);
-// break;
-// case KNOT_RDATA_WF_BYTE:
-// size += 1;
-// break;
-// case KNOT_RDATA_WF_SHORT:
-// size += 2;
-// break;
-// case KNOT_RDATA_WF_LONG:
-// size += 4;
-// break;
-// case KNOT_RDATA_WF_A:
-// size += 4;
-// break;
-// case KNOT_RDATA_WF_AAAA:
-// size += 16;
-// break;
-// case KNOT_RDATA_WF_BINARY:
-// case KNOT_RDATA_WF_APL: // saved as binary
-// case KNOT_RDATA_WF_IPSECGATEWAY: // saved as binary
-// size += rdata->items[i].raw_data[0];
-// break;
-// case KNOT_RDATA_WF_TEXT:
-// case KNOT_RDATA_WF_BINARYWITHLENGTH:
-// size += rdata->items[i].raw_data[0] + 1;
-// break;
-// default:
-// assert(0);
-// }
-// }
-// return size;
-//}
-
-/*----------------------------------------------------------------------------*/
-
-//int knot_rdata_to_wire(const knot_rdata_t *rdata, const uint8_t *format,
-// uint8_t *buffer, uint buf_size)
-//{
-// uint copied = 0;
-// uint8_t tmp[KNOT_MAX_RDATA_WIRE_SIZE];
-// uint8_t *to = tmp;
-
-// for (int i = 0; i < rdata->count; ++i) {
-// assert(copied < KNOT_MAX_RDATA_WIRE_SIZE);
-
-// const uint8_t *from = (uint8_t *)rdata->items[i].raw_data;
-// uint size = 0;
-
-// switch (format[i]) {
-// case KNOT_RDATA_WF_COMPRESSED_DNAME:
-// case KNOT_RDATA_WF_UNCOMPRESSED_DNAME:
-// case KNOT_RDATA_WF_LITERAL_DNAME:
-// size = knot_dname_size(rdata->items[i].dname);
-// from = knot_dname_name(rdata->items[i].dname);
-
-// break;
-// case KNOT_RDATA_WF_BYTE:
-// size = 1;
-// break;
-// case KNOT_RDATA_WF_SHORT:
-// size = 2;
-// break;
-// case KNOT_RDATA_WF_LONG:
-// size = 4;
-// break;
-// case KNOT_RDATA_WF_A:
-// size = 4;
-// break;
-// case KNOT_RDATA_WF_AAAA:
-// size = 16;
-// break;
-// case KNOT_RDATA_WF_TEXT:
-// case KNOT_RDATA_WF_BINARYWITHLENGTH:
-// // size stored in the first two bytes, but in little
-// // endian and we need only the lower byte from it
-// *to = *from; // lower byte is the first in little endian
-// to += 1;
-// case KNOT_RDATA_WF_BINARY:
-// case KNOT_RDATA_WF_APL: // saved as binary
-// case KNOT_RDATA_WF_IPSECGATEWAY: // saved as binary
-// // size stored in the first two bytes, those bytes
-// // must not be copied
-// size = rdata->items[i].raw_data[0];
-// from += 2; // skip the first two bytes
-// break;
-// default:
-// assert(0);
-// }
-
-// assert(size != 0);
-// assert(copied + size < KNOT_MAX_RDATA_WIRE_SIZE);
-
-// memcpy(to, from, size);
-// to += size;
-// copied += size;
-// }
-
-// if (copied > buf_size) {
-// dbg_rdata("Not enough place allocated for function "
-// "knot_rdata_to_wire(). Allocated %u, need %u\n",
-// buf_size, copied);
-// return -1;
-// }
-
-// memcpy(buffer, tmp, copied);
-// return 0;
-//}
-
-/*----------------------------------------------------------------------------*/
knot_rdata_t *knot_rdata_deep_copy(const knot_rdata_t *rdata,
uint16_t type, int copy_dnames)
@@ -728,33 +620,19 @@ int knot_rdata_compare(const knot_rdata_t *r1, const knot_rdata_t *r2,
int cmp = 0;
for (int i = 0; i < count; ++i) {
- /* CLEANUP */
-// const uint8_t *data1, *data2;
-// int size1, size2;
-
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);
-// data1 = knot_dname_name(r1->items[i].dname);
-// data2 = knot_dname_name(r2->items[i].dname);
-// size1 = knot_dname_size(r2->items[i].dname);
-// size2 = knot_dname_size(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]);
-// data1 = (uint8_t *)(r1->items[i].raw_data + 1);
-// data2 = (uint8_t *)(r2->items[i].raw_data + 1);
-// size1 = r1->items[i].raw_data[0];
-// size2 = r1->items[i].raw_data[0];
}
-// cmp =
-
if (cmp != 0) {
return cmp;
}
@@ -894,3 +772,48 @@ uint16_t knot_rdata_rrsig_type_covered(const knot_rdata_t *rdata)
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;
+}
diff --git a/src/libknot/rdata.h b/src/libknot/rdata.h
index bb45f50..acd678f 100644..100755
--- a/src/libknot/rdata.h
+++ b/src/libknot/rdata.h
@@ -220,6 +220,8 @@ int knot_rdata_item_set_dname(knot_rdata_t *rdata, unsigned int pos,
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.
*
@@ -335,6 +337,11 @@ 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);
+
#endif /* _KNOT_RDATA_H */
/*! @} */
diff --git a/src/libknot/rrset.c b/src/libknot/rrset.c
index d665c63..ef7fce8 100644..100755
--- a/src/libknot/rrset.c
+++ b/src/libknot/rrset.c
@@ -32,7 +32,7 @@
/*----------------------------------------------------------------------------*/
static void knot_rrset_disconnect_rdata(knot_rrset_t *rrset,
- knot_rdata_t *prev, knot_rdata_t *rdata)
+ knot_rdata_t *prev, knot_rdata_t *rdata)
{
if (prev == NULL) {
// find the previous RDATA in the series, as its pointer must
@@ -113,6 +113,53 @@ int knot_rrset_add_rdata(knot_rrset_t *rrset, knot_rdata_t *rdata)
/*----------------------------------------------------------------------------*/
+int knot_rrset_add_rdata_order(knot_rrset_t *rrset, knot_rdata_t *rdata)
+{
+ if (rrset == NULL || rdata == NULL) {
+ dbg_rrset("rrset: add_rdata_order: NULL arguments.\n");
+ return KNOT_EBADARG;
+ }
+
+ if (rrset->rdata == NULL) {
+ /* Easy peasy, just insert the first item. */
+ rrset->rdata = rdata;
+ rrset->rdata->next = rrset->rdata;
+ } 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. */
+ }
+ }
+ return KNOT_EOK;
+}
+
+/*----------------------------------------------------------------------------*/
+
knot_rdata_t *knot_rrset_remove_rdata(knot_rrset_t *rrset,
const knot_rdata_t *rdata)
{
@@ -167,19 +214,30 @@ int knot_rrset_add_rrsigs(knot_rrset_t *rrset, knot_rrset_t *rrsigs,
int rc;
if (rrset->rrsigs != NULL) {
if (dupl == KNOT_RRSET_DUPL_MERGE) {
- rc = knot_rrset_merge((void **)&rrset->rrsigs,
- (void **)&rrsigs);
+ rc = knot_rrset_merge_no_dupl((void **)&rrset->rrsigs,
+ (void **)&rrsigs);
if (rc != KNOT_EOK) {
return rc;
} else {
return 1;
}
} 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;
}
} else {
+ if (rrset->ttl != rrsigs->ttl) {
+ rrsigs->ttl = rrset->ttl;
+ }
+
rrset->rrsigs = rrsigs;
}
@@ -291,6 +349,10 @@ knot_rdata_t *knot_rrset_rdata_get_next(knot_rrset_t *rrset,
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;
@@ -341,7 +403,7 @@ int knot_rrset_compare_rdata(const knot_rrset_t *r1, const knot_rrset_t *r2)
}
// compare RDATA sets (order is not significant)
- const knot_rdata_t *rdata1= knot_rrset_rdata(r1);
+ const knot_rdata_t *rdata1 = knot_rrset_rdata(r1);
const knot_rdata_t *rdata2;
// find all RDATA from r1 in r2
@@ -434,7 +496,6 @@ static int knot_rrset_rr_to_wire(const knot_rrset_t *rrset,
*pos += 2;
size += 10;
-// compr->wire_pos += size;
dbg_rrset_detail("Max size: %zu, size: %d\n", max_size, size);
@@ -465,7 +526,6 @@ static int knot_rrset_rr_to_wire(const knot_rrset_t *rrset,
knot_dname_size(dname));
*pos += knot_dname_size(dname);
rdlength += knot_dname_size(dname);
-// compr->wire_pos += dname->size;
break;
}
default: {
@@ -481,7 +541,6 @@ static int knot_rrset_rr_to_wire(const knot_rrset_t *rrset,
dbg_rrset_detail("Raw data size: %d\n", raw_data[0]);
*pos += raw_data[0];
rdlength += raw_data[0];
-// compr->wire_pos += raw_data[0];
break;
}
}
@@ -523,11 +582,11 @@ int knot_rrset_to_wire(const knot_rrset_t *rrset, uint8_t *wire, size_t *size,
if (ret < 0) {
// some RR didn't fit in, so no RRs should be used
// TODO: remove last entries from compression table
- dbg_rrset_detail("Some RR didn't fit in.\n");
+ dbg_rrset_verb("Some RR didn't fit in.\n");
return KNOT_ESPACE;
}
- dbg_rrset_detail("RR of size %d added.\n", ret);
+ dbg_rrset_verb("RR of size %d added.\n", ret);
rrset_size += ret;
++rrs;
} while ((rdata = knot_rrset_rdata_next(rrset, rdata)) != NULL);
@@ -556,7 +615,7 @@ int knot_rrset_compare(const knot_rrset_t *r1,
int res = ((r1->rclass == r2->rclass)
&& (r1->type == r2->type)
- && (r1->ttl == r2->ttl)
+// && (r1->ttl == r2->ttl)
&& knot_dname_compare(r1->owner, r2->owner) == 0);
if (cmp == KNOT_RRSET_COMPARE_WHOLE && res) {
@@ -571,7 +630,8 @@ int knot_rrset_compare(const knot_rrset_t *r1,
/*----------------------------------------------------------------------------*/
-int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to)
+int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to,
+ int copy_rdata_dnames)
{
if (from == NULL || to == NULL) {
return KNOT_EBADARG;
@@ -582,14 +642,14 @@ int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to)
*to = (knot_rrset_t *)calloc(1, sizeof(knot_rrset_t));
CHECK_ALLOC_LOG(*to, KNOT_ENOMEM);
- //(*to)->owner = knot_dname_deep_copy(from->owner);
(*to)->owner = from->owner;
knot_dname_retain((*to)->owner);
(*to)->rclass = from->rclass;
(*to)->ttl = from->ttl;
(*to)->type = from->type;
if (from->rrsigs != NULL) {
- ret = knot_rrset_deep_copy(from->rrsigs, &(*to)->rrsigs);
+ ret = knot_rrset_deep_copy(from->rrsigs, &(*to)->rrsigs,
+ copy_rdata_dnames);
if (ret != KNOT_EOK) {
knot_rrset_deep_free(to, 1, 0, 0);
return ret;
@@ -601,8 +661,19 @@ int knot_rrset_deep_copy(const knot_rrset_t *from, knot_rrset_t **to)
/*! \note Order of RDATA will be reversed. */
while (rdata != NULL) {
- ret = knot_rrset_add_rdata(*to, knot_rdata_deep_copy(rdata,
- knot_rrset_type(from), 1));
+ knot_rdata_t *rdata_copy = knot_rdata_deep_copy(rdata,
+ knot_rrset_type(from),
+ copy_rdata_dnames);
+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);
+);
+ ret = knot_rrset_add_rdata(*to, rdata_copy);
if (ret != KNOT_EOK) {
knot_rrset_deep_free(to, 1, 1, 1);
return ret;
@@ -632,6 +703,7 @@ int knot_rrset_shallow_copy(const knot_rrset_t *from, knot_rrset_t **to)
void knot_rrset_rotate(knot_rrset_t *rrset)
{
+ /*! \todo Maybe implement properly one day. */
//rrset->rdata = rrset->rdata->next;
}
@@ -659,12 +731,6 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
return;
}
-// char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
-// char *type = knot_rrtype_to_string(knot_rrset_type(*rrset));
-// fprintf(stderr, "Deleting RRSet (%p) %s, type %s, rdata: %p\n",
-// *rrset, name, type, (*rrset)->rdata);
-// free(name);
-
if (free_rdata) {
knot_rdata_t *tmp_rdata;
knot_rdata_t *next_rdata;
@@ -679,7 +745,6 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
tmp_rdata = next_rdata;
}
-// printf("test: %p\n", tmp_rdata->next->next);
assert(tmp_rdata == NULL
|| tmp_rdata->next == (*rrset)->rdata);
@@ -693,10 +758,7 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
free_rdata_dnames);
}
- /*! \todo Release owner every time? */
- //if (free_owner) {
- knot_dname_release((*rrset)->owner);
- //}
+ knot_dname_release((*rrset)->owner);
free(*rrset);
*rrset = NULL;
@@ -711,8 +773,7 @@ int knot_rrset_merge(void **r1, void **r2)
if ((knot_dname_compare(rrset1->owner, rrset2->owner) != 0)
|| rrset1->rclass != rrset2->rclass
- || rrset1->type != rrset2->type
- || rrset1->ttl != rrset2->ttl) {
+ || rrset1->type != rrset2->type) {
return KNOT_EBADARG;
}
@@ -744,6 +805,155 @@ int knot_rrset_merge(void **r1, void **r2)
}
tmp_rdata->next = rrset1->rdata;
+ rrset2->rdata = rrset1->rdata;
+
+ return KNOT_EOK;
+}
+
+int knot_rrset_merge_no_dupl(void **r1, void **r2)
+{
+ if (r1 == NULL || r2 == NULL) {
+ dbg_rrset("rrset: merge_no_dupl: NULL arguments.");
+ return KNOT_EBADARG;
+ }
+
+ 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_EBADARG;
+ }
+
+dbg_rrset_exec_detail(
+ char *name = knot_dname_to_str(rrset1->owner);
+ dbg_rrset_detail("rrset: merge_no_dupl: Merging %s.\n", name);
+ free(name);
+);
+
+ if ((knot_dname_compare(rrset1->owner, rrset2->owner) != 0)
+ || rrset1->rclass != rrset2->rclass
+ || rrset1->type != rrset2->type) {
+ dbg_rrset("rrset: merge_no_dupl: Trying to merge "
+ "different RRs.\n");
+ return KNOT_EBADARG;
+ }
+
+ knot_rdata_t *walk2 = rrset2->rdata;
+
+ // 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
+ */
+
+ // 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);
+
+ // 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;
+ }
+
+ /*
+ * 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.
+ */
+ 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);
+ } 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. */
+ }
+ }
+
+ assert(walk2 == NULL);
+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);
+);
+ /*
+ * 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.
+ */
+ rrset2->rdata = NULL;
return KNOT_EOK;
}
diff --git a/src/libknot/rrset.h b/src/libknot/rrset.h
index b5c11dc..36d8da5 100644..100755
--- a/src/libknot/rrset.h
+++ b/src/libknot/rrset.h
@@ -105,6 +105,21 @@ knot_rrset_t *knot_rrset_new(knot_dname_t *owner, uint16_t type,
*/
int knot_rrset_add_rdata(knot_rrset_t *rrset, knot_rdata_t *rdata);
+/*!
+ * \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)
+ *
+ * \param rrset RRSet to add the RDATA to.
+ * \param rdata RDATA to add to the RRSet.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_EBADARG
+ *
+ * \todo Provide some function for comparing RDATAs.
+ */
+int knot_rrset_add_rdata_order(knot_rrset_t *rrset, knot_rdata_t *rdata);
+
knot_rdata_t * knot_rrset_remove_rdata(knot_rrset_t *rrset,
const knot_rdata_t *rdata);
@@ -249,7 +264,8 @@ int knot_rrset_compare(const knot_rrset_t *r1,
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 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);
@@ -296,9 +312,9 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
* \brief Merges two RRSets.
*
* Merges \a r1 into \a r2 by concatenating the list of RDATAs in \a r2 after
- * the list of RDATAs in \a r1. \a r2 is unaffected by this, though you must not
- * destroy the RDATAs in \a r2 as they are now also in \a r1. (You may use
- * function knot_rrset_free() though, as it does not touch RDATAs).
+ * 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.
*
@@ -311,6 +327,26 @@ void knot_rrset_deep_free(knot_rrset_t **rrset, int free_owner,
*/
int knot_rrset_merge(void **r1, void **r2);
+
+/*!
+ * \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.
+ *
+ * \param r1 Pointer to RRSet to be merged into.
+ * \param r2 Poitner to RRSet to be merged.
+ *
+ * \retval KNOT_EOK
+ * \retval KNOT_EBADARG if the RRSets could not be merged, because their
+ * Owner, Type, Class or TTL does not match.
+ */
+int knot_rrset_merge_no_dupl(void **r1, void **r2);
+
#endif /* _KNOT_RRSET_H_ */
/*! @} */
diff --git a/src/libknot/tsig-op.c b/src/libknot/tsig-op.c
index 148fc87..173538c 100644..100755
--- a/src/libknot/tsig-op.c
+++ b/src/libknot/tsig-op.c
@@ -21,20 +21,27 @@
#include <time.h>
#include "common.h"
+#include "common/base64.h"
#include "tsig.h"
#include "tsig-op.h"
#include "util/wire.h"
-#include "libknot/util/conv.h"
#include "util/error.h"
#include "util/debug.h"
#include "consts.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_EBADARG;
+ }
+
const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig_rr);
if (!alg_name) {
return KNOT_EMALF;
@@ -53,6 +60,10 @@ 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)
{
+ if (tsig_rr == NULL || tsig_key == NULL) {
+ return KNOT_EBADARG;
+ }
+
const knot_dname_t *tsig_name = knot_rrset_owner(tsig_rr);
if (!tsig_name) {
return KNOT_EMALF;
@@ -94,28 +105,25 @@ static int knot_tsig_compute_digest(const uint8_t *wire, size_t wire_len,
return KNOT_TSIG_EBADSIG;
}
- /* Create digest, using length of the algorithm. */
-// *digest = malloc(sizeof(uint8_t) * tsig_alg_digest_length(tsig_alg));
-// if (!digest) {
-// ERR_ALLOC_FAILED;
-// return KNOT_ENOMEM;
-// }
-
/* Decode key from Base64. */
char decoded_key[B64BUFSIZE];
-
- int decoded_key_size = b64_pton(key->secret, (uint8_t *)decoded_key,
- B64BUFSIZE);
+
+ size_t decoded_key_size = B64BUFSIZE;
+ int ret = base64_decode(key->secret, strlen(key->secret),
+ decoded_key,
+ &decoded_key_size);
+ if (ret != 1) {
+ dbg_tsig("TSIG: New decode function failed! (%d)\n", ret);
+ return KNOT_ERROR;
+ }
+
if (decoded_key_size < 0) {
dbg_tsig("TSIG: Could not decode Base64\n");
return KNOT_ERROR;
}
-
+
dbg_tsig_detail("TSIG: decoded key size: %d\n", decoded_key_size);
dbg_tsig_detail("TSIG: decoded key: '%*s'\n", decoded_key_size, decoded_key);
-
-// dbg_tsig_detail("TSIG: using this wire for digest calculation\n");
-// dbg_tsig_hex_detail(wire, wire_len);
dbg_tsig_detail("Wire for signing is %zu bytes long.\n", wire_len);
/* Compute digest. */
@@ -152,6 +160,7 @@ static int knot_tsig_check_time_signed(const knot_rrset_t *tsig_rr,
uint64_t prev_time_signed)
{
if (!tsig_rr) {
+ dbg_tsig("TSIG: check_time_signed: NULL argument.\n");
return KNOT_EBADARG;
}
@@ -184,21 +193,14 @@ static int knot_tsig_check_time_signed(const knot_rrset_t *tsig_rr,
return KNOT_EOK;
}
-static int knot_tsig_write_tsig_timers(uint8_t *wire,
- const knot_rrset_t *tsig_rr)
-{
- // put time signed
- knot_wire_write_u48(wire, tsig_rdata_time_signed(tsig_rr));
-
- // put fudge
- knot_wire_write_u16(wire + 6, tsig_rdata_fudge(tsig_rr));
-
- return KNOT_EOK;
-}
-
static int knot_tsig_write_tsig_variables(uint8_t *wire,
const knot_rrset_t *tsig_rr)
{
+ if (wire == NULL || tsig_rr == NULL) {
+ dbg_tsig("TSIG: write tsig variables: NULL arguments.\n");
+ return KNOT_EBADARG;
+ }
+
/* Copy TSIG variables - starting with key name. */
const knot_dname_t *tsig_owner = knot_rrset_owner(tsig_rr);
if (!tsig_owner) {
@@ -210,24 +212,23 @@ 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("TSIG: write variables: written owner (tsig alg): \n");
- /*knot_rrset_class(tsig_rr));*/
- dbg_tsig_hex_detail(wire + offset, 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));
offset += knot_dname_size(tsig_owner);
/*!< \todo which order? */
/* Copy class. */
knot_wire_write_u16(wire + offset, knot_rrset_class(tsig_rr));
- dbg_tsig("TSIG: write variables: written CLASS: %u - ",
- knot_rrset_class(tsig_rr));
+ dbg_tsig_verb("TSIG: write variables: written CLASS: %u - ",
+ knot_rrset_class(tsig_rr));
dbg_tsig_hex_detail(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("TSIG: write variables: written TTL: %u - ",
- knot_rrset_ttl(tsig_rr));
+ dbg_tsig_verb("TSIG: write variables: written TTL: %u - ",
+ knot_rrset_ttl(tsig_rr));
dbg_tsig_hex_detail(wire + offset, sizeof(uint32_t));
offset += sizeof(uint32_t);
@@ -237,28 +238,25 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
dbg_tsig("TSIG: write variables: no algorithm name.\n");
return KNOT_EBADARG;
}
-// alg_name = knot_dname_new_from_str("HMAC-MD5.SIG-ALG.REG.INT.",
- //strlen("HMAC-MD5.SIG-ALG.REG.INT."),
- //NULL);
memcpy(wire + offset, knot_dname_name(alg_name),
sizeof(uint8_t) * knot_dname_size(alg_name));
offset += knot_dname_size(alg_name);
- dbg_tsig_detail("TSIG: write variables: written alg name: %s\n",
- knot_dname_to_str(alg_name));
+ dbg_tsig_verb("TSIG: write variables: written alg name: %s\n",
+ knot_dname_to_str(alg_name));
/* Following data are written in network order. */
/* Time signed. */
knot_wire_write_u48(wire + offset, tsig_rdata_time_signed(tsig_rr));
offset += 6;
- dbg_tsig_detail("TSIG: write variables: time signed: %llu - ",
- tsig_rdata_time_signed(tsig_rr));
+ dbg_tsig_verb("TSIG: write variables: time signed: %llu - ",
+ tsig_rdata_time_signed(tsig_rr));
dbg_tsig_hex_detail(wire + offset - 6, 6);
/* Fudge. */
knot_wire_write_u16(wire + offset, tsig_rdata_fudge(tsig_rr));
offset += sizeof(uint16_t);
- dbg_tsig_detail("TSIG: write variables: fudge: %hu\n",
- tsig_rdata_fudge(tsig_rr));
+ dbg_tsig_verb("TSIG: write variables: fudge: %hu\n",
+ tsig_rdata_fudge(tsig_rr));
/* TSIG error. */
knot_wire_write_u16(wire + offset, tsig_rdata_error(tsig_rr));
offset += sizeof(uint16_t);
@@ -279,7 +277,7 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
offset += sizeof(uint16_t);
/* Skip the length. */
- dbg_tsig_detail("Copying other data.\n");
+ dbg_tsig_verb("Copying other data.\n");
memcpy(wire + offset, other_data, other_data_length);
return KNOT_EOK;
@@ -288,7 +286,14 @@ static int knot_tsig_write_tsig_variables(uint8_t *wire,
static int knot_tsig_wire_write_timers(uint8_t *wire,
const knot_rrset_t *tsig_rr)
{
+ if (wire == NULL || tsig_rr == NULL) {
+ dbg_tsig("TSIG: write timers: NULL arguments.\n");
+ return KNOT_EBADARG;
+ }
+
+ //write time signed
knot_wire_write_u48(wire, tsig_rdata_time_signed(tsig_rr));
+ //write fudge
knot_wire_write_u16(wire + 6, tsig_rdata_fudge(tsig_rr));
return KNOT_EOK;
@@ -308,21 +313,14 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
/* Create tmp TSIG. */
int ret = KNOT_EOK;
-// knot_rrset_t *tmp_tsig =
-// knot_rrset_new(key->name, KNOT_RRTYPE_TSIG, KNOT_CLASS_ANY, 0);
-// if (!tmp_tsig) {
-// return KNOT_ENOMEM;
-// }
-
-// tsig_rdata_store_current_time(tmp_tsig);
/*
* Create tmp wire, it should contain message
* plus request mac plus tsig varibles.
*/
- dbg_tsig("Counting wire size: %zu, %zu, %zu.\n",
- msg_len, request_mac_len,
- tsig_rdata_tsig_variables_length(tmp_tsig));
+ dbg_tsig_verb("Counting wire size: %zu, %zu, %zu.\n",
+ msg_len, request_mac_len,
+ tsig_rdata_tsig_variables_length(tmp_tsig));
size_t wire_len = sizeof(uint8_t) *
(msg_len + request_mac_len + ((request_mac_len > 0)
? 2 : 0) +
@@ -339,23 +337,21 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
/* Copy the request MAC - should work even if NULL. */
if (request_mac_len > 0) {
- dbg_tsig_detail("Copying request MAC size\n");
+ dbg_tsig_verb("Copying request MAC size\n");
knot_wire_write_u16(pos, request_mac_len);
pos += 2;
}
- dbg_tsig("Copying request mac.\n");
+ 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: ");
dbg_tsig_hex_detail(pos, request_mac_len);
pos += request_mac_len;
/* Copy the original message. */
- dbg_tsig("Copying original message.\n");
+ dbg_tsig_verb("Copying original message.\n");
memcpy(pos, msg, msg_len);
- dbg_tsig_detail("TSIG: create wire: original message: \n");
- //dbg_tsig_hex_detail(pos, msg_len);
pos += msg_len;
/* Copy TSIG variables. */
- dbg_tsig("Writing TSIG variables.\n");
+ dbg_tsig_verb("Writing TSIG variables.\n");
ret = knot_tsig_write_tsig_variables(pos, tmp_tsig);
if (ret != KNOT_EOK) {
dbg_tsig("TSIG: create wire: failed to write TSIG "
@@ -375,20 +371,8 @@ static int knot_tsig_create_sign_wire(const uint8_t *msg, size_t msg_len,
return ret;
}
-// assert(digest_tmp_len > 0);
free(wire);
-// if (digest_tmp_len > *digest_len) {
-// *digest_len = 0;
-// return KNOT_ESPACE;
-// }
-
-// knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
-
- // everything went ok, save the digest to the output parameter
-// memcpy(digest, digest_tmp, digest_tmp_len);
-// *digest_len = digest_tmp_len;
-
return KNOT_EOK;
}
@@ -411,9 +395,9 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
* Create tmp wire, it should contain message
* plus request mac plus tsig varibles.
*/
- dbg_tsig("Counting wire size: %zu, %zu, %zu.\n",
- msg_len, prev_mac_len,
- tsig_rdata_tsig_timers_length());
+ dbg_tsig_verb("Counting wire size: %zu, %zu, %zu.\n",
+ msg_len, prev_mac_len,
+ tsig_rdata_tsig_timers_length());
size_t wire_len = sizeof(uint8_t) *
(msg_len + prev_mac_len +
tsig_rdata_tsig_timers_length() + 2);
@@ -426,27 +410,24 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
memset(wire, 0, wire_len);
/* Copy the request MAC - should work even if NULL. */
- dbg_tsig("Copying request mac size.\n");
+ dbg_tsig_verb("Copying request mac size.\n");
knot_wire_write_u16(wire, prev_mac_len);
- dbg_tsig("Copying request mac.\n");
+ 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: ");
dbg_tsig_hex_detail(wire + 2, prev_mac_len);
/* Copy the original message. */
- dbg_tsig("Copying original message.\n");
+ dbg_tsig_verb("Copying original message.\n");
memcpy(wire + prev_mac_len + 2, msg, msg_len);
- dbg_tsig_detail("TSIG: create wire: original message: \n");
- //dbg_tsig_hex_detail(wire + prev_mac_len, msg_len);
/* Copy TSIG variables. */
- dbg_tsig("Writing TSIG timers.\n");
- ret = knot_tsig_write_tsig_timers(wire + prev_mac_len + msg_len + 2,
+ dbg_tsig_verb("Writing TSIG timers.\n");
+ ret = knot_tsig_wire_write_timers(wire + prev_mac_len + msg_len + 2,
tmp_tsig);
-// ret = knot_tsig_write_tsig_variables(wire + prev_mac_len + msg_len,
-// tmp_tsig);
if (ret != KNOT_EOK) {
dbg_tsig("TSIG: create wire: failed to write TSIG "
"timers: %s\n", knot_strerror(ret));
+ free(wire);
return ret;
}
@@ -457,6 +438,7 @@ static int knot_tsig_create_sign_wire_next(const uint8_t *msg, size_t msg_len,
dbg_tsig("TSIG: create wire: failed to compute digest: %s\n",
knot_strerror(ret));
*digest_len = 0;
+ free(wire);
return ret;
}
@@ -478,7 +460,7 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
knot_dname_t *key_name_copy = knot_dname_deep_copy(key->name);
if (!key_name_copy) {
- dbg_tsig_detail("TSIG: key_name_copy = NULL\n");
+ dbg_tsig("TSIG: key_name_copy = NULL\n");
return KNOT_ENOMEM;
}
@@ -488,14 +470,14 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
/* Should be retained by rrsig or freed, release. */
knot_dname_release(key_name_copy);
if (!tmp_tsig) {
- dbg_tsig_detail("TSIG: tmp_tsig = NULL\n");
+ dbg_tsig("TSIG: tmp_tsig = NULL\n");
return KNOT_ENOMEM;
}
/* Create rdata for TSIG RR. */
knot_rdata_t *rdata = knot_rdata_new();
if (!rdata) {
- dbg_tsig_detail("TSIG: rdata = NULL\n");
+ dbg_tsig("TSIG: rdata = NULL\n");
knot_rrset_free(&tmp_tsig);
return KNOT_ENOMEM;
}
@@ -510,7 +492,7 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
knot_rdata_item_t *items =
malloc(sizeof(knot_rdata_item_t) * desc->length);
if (!items) {
- dbg_tsig_detail("TSIG: items = NULL\n");
+ dbg_tsig("TSIG: items = NULL\n");
ERR_ALLOC_FAILED;
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
@@ -521,7 +503,8 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
int ret = knot_rdata_set_items(rdata, items, desc->length);
if (ret != KNOT_EOK) {
- dbg_tsig_detail("TSIG: rdata_set_items returned %s\n", knot_strerror(ret));
+ dbg_tsig("TSIG: rdata_set_items returned %s\n",
+ knot_strerror(ret));
free(items);
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
@@ -554,7 +537,7 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
tsig_rdata_set_other_data(tmp_tsig, 0, 0);
}
- tsig_rdata_set_fudge(tmp_tsig, 300); /*! \todo Bleeding eyes :-) */
+ tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
/* Set original ID */
tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
@@ -583,13 +566,11 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
int rr_count = 0;
tsig_rdata_set_mac(tmp_tsig, digest_tmp_len, digest_tmp);
- //knot_rrset_dump(tmp_tsig, 1);
-
/* Write RRSet to wire */
ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len,
&tsig_wire_len, &rr_count);
if (ret != KNOT_EOK) {
- dbg_tsig_detail("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
+ dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
*digest_len = 0;
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
@@ -633,7 +614,7 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
/* Create rdata for TSIG RR. */
knot_rdata_t *rdata = knot_rdata_new();
if (!rdata) {
- dbg_tsig_detail("TSIG: rdata = NULL\n");
+ dbg_tsig("TSIG: rdata = NULL\n");
knot_rrset_free(&tmp_tsig);
return KNOT_ENOMEM;
}
@@ -642,7 +623,7 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
ret = knot_rrset_add_rdata(tmp_tsig, rdata);
if (ret != KNOT_EOK) {
- dbg_tsig_detail("TSIG: could not add rdata\n");
+ dbg_tsig("TSIG: could not add rdata\n");
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
return ret;
@@ -656,7 +637,7 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
knot_rdata_item_t *items =
malloc(sizeof(knot_rdata_item_t) * desc->length);
if (!items) {
- dbg_tsig_detail("TSIG: items = NULL\n");
+ dbg_tsig("TSIG: items = NULL\n");
ERR_ALLOC_FAILED;
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
@@ -667,7 +648,8 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
ret = knot_rdata_set_items(rdata, items, desc->length);
if (ret != KNOT_EOK) {
- dbg_tsig_detail("TSIG: rdata_set_items returned %s\n", knot_strerror(ret));
+ dbg_tsig("TSIG: rdata_set_items returned %s\n",
+ knot_strerror(ret));
knot_rrset_free(&tmp_tsig);
knot_rdata_free(&rdata);
free(items);
@@ -676,7 +658,7 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
free(items);
tsig_rdata_store_current_time(tmp_tsig);
- tsig_rdata_set_fudge(tmp_tsig, 300);
+ 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
@@ -739,8 +721,8 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
/* Set other data. */
tsig_rdata_set_other_data(tmp_tsig, 0, NULL);
- dbg_tsig_detail("Message max length: %zu, message length: %zu\n",
- msg_max_len, *msg_len);
+ 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;
@@ -788,7 +770,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
return ret;
}
- dbg_tsig("TSIG: time checked.\n");
+ dbg_tsig_verb("TSIG: time checked.\n");
/* Check that libknot knows the algorithm. */
ret = knot_tsig_check_algorithm(tsig_rr);
@@ -796,7 +778,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
return ret;
}
- dbg_tsig("TSIG: algorithm checked.\n");
+ dbg_tsig_verb("TSIG: algorithm checked.\n");
/* Check that key is valid, ie. the same as given in args. */
ret = knot_tsig_check_key(tsig_rr, tsig_key);
@@ -804,22 +786,15 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
return ret;
}
- dbg_tsig("TSIG: key validity checked.\n");
+ dbg_tsig_verb("TSIG: key validity checked.\n");
/* Time OK algorithm OK, key name OK - do digest. */
/* Calculate the size of TSIG RR. */
size_t tsig_len = tsig_wire_actsize(tsig_rr);
- dbg_tsig_detail("TSIG: check digest: wire before strip: \n");
- //dbg_tsig_hex_detail(wire, size);
-
/* Strip the TSIG. */
size -= tsig_len;
- dbg_tsig_detail("TSIG: check digest: wire after strip (stripped %zu):\n",
- tsig_len);
- //dbg_tsig_hex_detail(wire, size);
-
uint8_t *wire_to_sign = malloc(sizeof(uint8_t) * size);
if (!wire_to_sign) {
ERR_ALLOC_FAILED;
@@ -858,16 +833,7 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
return ret;
}
-// uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
-// size_t digest_tmp_len = 0;
-// ret = knot_tsig_compute_digest(wire, size, digest_tmp,
-// &digest_tmp_len, tsig_key);
-// if (ret != KNOT_EOK) {
-// dbg_tsig("TSIG: digest could not be calculated\n");
-// return ret;
-// }
-
- dbg_tsig("TSIG: digest calculated\n");
+ dbg_tsig_verb("TSIG: digest calculated\n");
/* Compare MAC from TSIG RR RDATA with just computed digest. */
@@ -880,17 +846,16 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
const uint8_t *tsig_mac = tsig_rdata_mac(tsig_rr);
if (mac_length != tsig_alg_digest_length(alg)) {
- dbg_tsig("TSIG: calculated digest length and given length do not match!\n");
+ dbg_tsig("TSIG: calculated digest length and given length do "
+ "not match!\n");
return KNOT_TSIG_EBADSIG;
}
-// assert(tsig_alg_digest_length(alg) == mac_length);
-
- dbg_tsig("TSIG: calc digest : ");
- dbg_tsig_hex(digest_tmp, digest_tmp_len);
+ dbg_tsig_verb("TSIG: calc digest : ");
+ dbg_tsig_hex_verb(digest_tmp, digest_tmp_len);
- dbg_tsig("TSIG: given digest: ");
- dbg_tsig_hex(tsig_mac, mac_length);
+ dbg_tsig_verb("TSIG: given digest: ");
+ dbg_tsig_hex_verb(tsig_mac, mac_length);
if (strncasecmp((char *)(tsig_mac), (char *)digest_tmp,
mac_length) != 0) {
@@ -904,7 +869,7 @@ int knot_tsig_server_check(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
const knot_key_t *tsig_key)
{
- dbg_tsig_verb("tsig_server_check()\n");
+ dbg_tsig("tsig_server_check()\n");
return knot_tsig_check_digest(tsig_rr, wire, size, NULL, 0, tsig_key,
0, 0);
}
@@ -915,7 +880,7 @@ int knot_tsig_client_check(const knot_rrset_t *tsig_rr,
const knot_key_t *tsig_key,
uint64_t prev_time_signed)
{
- dbg_tsig_verb("tsig_client_check()\n");
+ dbg_tsig("tsig_client_check()\n");
return knot_tsig_check_digest(tsig_rr, wire, size, request_mac,
request_mac_len, tsig_key,
prev_time_signed, 0);
@@ -928,9 +893,7 @@ int knot_tsig_client_check_next(const knot_rrset_t *tsig_rr,
const knot_key_t *tsig_key,
uint64_t prev_time_signed)
{
-// return knot_tsig_client_check(tsig_rr, wire, size, prev_digest,
-// prev_digest_len, tsig_key);
- dbg_tsig_verb("tsig_client_check_next()\n");
+ 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);
@@ -950,15 +913,14 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
knot_dname_t *key_name =
knot_dname_deep_copy(knot_rrset_owner(tsig_rr));
if (key_name == NULL) {
- dbg_tsig_detail("TSIG: failed to copy owner\n");
+ dbg_tsig("TSIG: failed to copy owner\n");
return KNOT_ERROR;
}
knot_rrset_t *tmp_tsig =
- knot_rrset_new(key_name,
- KNOT_RRTYPE_TSIG, KNOT_CLASS_ANY, 0);
+ knot_rrset_new(key_name, KNOT_RRTYPE_TSIG, KNOT_CLASS_ANY, 0);
if (!tmp_tsig) {
- dbg_tsig_detail("TSIG: tmp_tsig = NULL\n");
+ dbg_tsig("TSIG: tmp_tsig = NULL\n");
knot_dname_free(&key_name);
return KNOT_ENOMEM;
}
@@ -966,7 +928,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
/* Create rdata for TSIG RR. */
knot_rdata_t *rdata = knot_rdata_new();
if (!rdata) {
- dbg_tsig_detail("TSIG: rdata = NULL\n");
+ dbg_tsig("TSIG: rdata = NULL\n");
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
return KNOT_ENOMEM;
}
@@ -981,7 +943,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
knot_rdata_item_t *items =
malloc(sizeof(knot_rdata_item_t) * desc->length);
if (items == NULL) {
- dbg_tsig_detail("TSIG: items = NULL\n");
+ dbg_tsig("TSIG: items = NULL\n");
ERR_ALLOC_FAILED;
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
return KNOT_ENOMEM;
@@ -992,8 +954,8 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
int ret = knot_rdata_set_items(rdata, items, desc->length);
free(items);
if (ret != KNOT_EOK) {
- dbg_tsig_detail("TSIG: rdata_set_items returned %s\n",
- knot_strerror(ret));
+ dbg_tsig("TSIG: rdata_set_items returned %s\n",
+ knot_strerror(ret));
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
return ret;
}
@@ -1001,14 +963,18 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
knot_dname_t *alg_name =
knot_dname_deep_copy(tsig_rdata_alg_name(tsig_rr));
if (alg_name == NULL) {
- dbg_tsig_detail("TSIG: failed to copy alg name\n");
+ dbg_tsig("TSIG: failed to copy alg name\n");
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
return KNOT_ERROR;
}
tsig_rdata_set_alg_name(tmp_tsig, alg_name);
tsig_rdata_set_time_signed(tmp_tsig, tsig_rdata_time_signed(tsig_rr));
- tsig_rdata_set_fudge(tmp_tsig, tsig_rdata_fudge(tsig_rr));
+
+ /* Comparing to BIND it was found out that the Fudge should always be
+ * set to the server's value.
+ */
+ tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
tsig_rdata_set_mac(tmp_tsig, 0, NULL);
knot_dname_release(alg_name); /* Already copied in tsig_rdata_set_alg_name() */
@@ -1029,7 +995,7 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
ret = knot_rrset_to_wire(tmp_tsig, msg + *msg_len,
&tsig_wire_len, &rr_count);
if (ret != KNOT_EOK) {
- dbg_tsig_detail("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
+ dbg_tsig("TSIG: rrset_to_wire = %s\n", knot_strerror(ret));
knot_rrset_deep_free(&tmp_tsig, 1, 1, 1);
return ret;
}
diff --git a/src/libknot/tsig-op.h b/src/libknot/tsig-op.h
index 07a84a8..07a84a8 100644..100755
--- a/src/libknot/tsig-op.h
+++ b/src/libknot/tsig-op.h
diff --git a/src/libknot/tsig.c b/src/libknot/tsig.c
index e8df92e..86b7f9d 100644..100755
--- a/src/libknot/tsig.c
+++ b/src/libknot/tsig.c
@@ -319,21 +319,21 @@ tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
/* Get the algorithm name. */
const knot_dname_t *alg_name = tsig_rdata_alg_name(tsig);
if (!alg_name) {
- dbg_tsig_detail("TSIG: rdata: cannot get algorithm name.\n");
+ dbg_tsig("TSIG: rdata: cannot get algorithm name.\n");
return KNOT_TSIG_ALG_NULL;
}
/* Convert alg name to string. */
char *name = knot_dname_to_str(alg_name);
if (!name) {
- dbg_tsig_detail("TSIG: rdata: cannot convert alg name.\n");
+ dbg_tsig("TSIG: rdata: cannot convert alg name.\n");
return KNOT_TSIG_ALG_NULL;
}
knot_lookup_table_t *item = knot_lookup_by_name(tsig_alg_table, name);
free(name);
if (!item) {
- dbg_tsig_detail("TSIG: rdata: unknown algorithm.\n");
+ dbg_tsig("TSIG: rdata: unknown algorithm.\n");
return KNOT_TSIG_ALG_NULL;
}
@@ -342,7 +342,7 @@ tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
uint64_t tsig_rdata_time_signed(const knot_rrset_t *tsig)
{
- /*!< \note How about assert. Or maybe change API??? */
+ /*! \note How about assert. Or maybe change API??? */
if (!tsig) {
return 0;
}
@@ -366,7 +366,7 @@ uint64_t tsig_rdata_time_signed(const knot_rrset_t *tsig)
uint16_t tsig_rdata_fudge(const knot_rrset_t *tsig)
{
- /*!< \note How about assert. Or maybe change API??? */
+ /*! \note How about assert. Or maybe change API??? */
if (!tsig) {
return 0;
}
@@ -390,7 +390,7 @@ uint16_t tsig_rdata_fudge(const knot_rrset_t *tsig)
const uint8_t *tsig_rdata_mac(const knot_rrset_t *tsig)
{
- /*!< \note How about assert. Or maybe change API??? */
+ /*! \note How about assert. Or maybe change API??? */
if (!tsig) {
return 0;
}
@@ -424,7 +424,7 @@ size_t tsig_rdata_mac_length(const knot_rrset_t *tsig)
uint16_t tsig_rdata_orig_id(const knot_rrset_t *tsig)
{
- /*!< \note How about assert. Or maybe change API??? */
+ /*! \note How about assert. Or maybe change API??? */
if (!tsig) {
return 0;
}
@@ -448,7 +448,7 @@ uint16_t tsig_rdata_orig_id(const knot_rrset_t *tsig)
uint16_t tsig_rdata_error(const knot_rrset_t *tsig)
{
- /*!< \note How about assert. Or maybe change API??? */
+ /*! \note How about assert. Or maybe change API??? */
if (!tsig) {
return 0;
}
@@ -472,7 +472,7 @@ uint16_t tsig_rdata_error(const knot_rrset_t *tsig)
const uint8_t *tsig_rdata_other_data(const knot_rrset_t *tsig)
{
- /*!< \note How about assert. Or maybe change API??? */
+ /*! \note How about assert. Or maybe change API??? */
if (!tsig) {
return 0;
}
@@ -491,7 +491,7 @@ const uint8_t *tsig_rdata_other_data(const knot_rrset_t *tsig)
uint16_t tsig_rdata_other_data_length(const knot_rrset_t *tsig)
{
- /*!< \note How about assert. Or maybe change API??? */
+ /*! \note How about assert. Or maybe change API??? */
if (!tsig) {
return 0;
}
@@ -558,6 +558,9 @@ uint16_t tsig_alg_digest_length(tsig_algorithm_t alg)
size_t tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig)
{
+ if (tsig == NULL) {
+ return 0;
+ }
/* Key name, Algorithm name and Other data have variable lengths. */
const knot_dname_t *key_name = knot_rrset_owner(tsig);
if (!key_name) {
@@ -569,13 +572,6 @@ size_t tsig_rdata_tsig_variables_length(const knot_rrset_t *tsig)
return 0;
}
-// dbg_tsig_detail("key_name: %.*s (size: %u) alg_name: %.*s (size: %u)\n", knot_dname_size(key_name),
-// key_name->name, alg_name->size, alg_name->name,
-// key_name->size, alg_name->size);
-
-// dbg_tsig_hex_detail(key_name->name, key_name->size);
-// dbg_tsig_hex_detail(alg_name->name, alg_name->size);
-
uint16_t other_data_length = tsig_rdata_other_data_length(tsig);
return knot_dname_size(key_name) + knot_dname_size(alg_name) +
@@ -594,7 +590,7 @@ int tsig_rdata_store_current_time(knot_rrset_t *tsig)
return KNOT_EBADARG;
}
time_t curr_time = time(NULL);
- /*!< \todo bleeding eyes. */
+ /*! \todo bleeding eyes. */
tsig_rdata_set_time_signed(tsig, (uint64_t)curr_time);
return KNOT_EOK;
}
@@ -612,6 +608,10 @@ const char* tsig_alg_to_str(tsig_algorithm_t alg)
size_t tsig_wire_maxsize(const knot_key_t* key)
{
+ if (key == NULL) {
+ return 0;
+ }
+
size_t alg_name_size = strlen(tsig_alg_to_str(key->algorithm)) + 1;
return knot_dname_size(key->name) +
@@ -632,6 +632,10 @@ size_t tsig_wire_maxsize(const knot_key_t* key)
size_t tsig_wire_actsize(const knot_rrset_t *tsig)
{
+ if (tsig == NULL) {
+ return 0;
+ }
+
return knot_dname_size(knot_rrset_owner(tsig)) +
sizeof(uint16_t) + /* TYPE */
sizeof(uint16_t) + /* CLASS */
@@ -648,3 +652,12 @@ size_t tsig_wire_actsize(const knot_rrset_t *tsig)
tsig_rdata_other_data_length(tsig);
}
+int tsig_rdata_is_ok(const knot_rrset_t *tsig)
+{
+ return (tsig
+ && knot_rrset_rdata(tsig) != NULL
+ && knot_rdata_item_count(knot_rrset_rdata(tsig)) >= 7
+ && 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 73fa832..249184d 100644..100755
--- a/src/libknot/tsig.h
+++ b/src/libknot/tsig.h
@@ -140,6 +140,8 @@ uint16_t tsig_alg_digest_length(tsig_algorithm_t alg);
size_t tsig_wire_maxsize(const knot_key_t *key);
size_t tsig_wire_actsize(const knot_rrset_t *tsig);
+int tsig_rdata_is_ok(const knot_rrset_t *tsig);
+
#endif /* _KNOT_TSIG_H_ */
/*! @} */
diff --git a/src/libknot/updates/changesets.c b/src/libknot/updates/changesets.c
index 1c3d3b9..502a858 100644..100755
--- a/src/libknot/updates/changesets.c
+++ b/src/libknot/updates/changesets.c
@@ -115,23 +115,20 @@ int knot_changeset_add_rr(knot_rrset_t ***rrsets, size_t *count,
// try to find the RRSet in the list of RRSets, but search backwards
// as it is probable that the last RRSet is the one to which the RR
// belongs
- int i = *count - 1;
-
- while (i >= 0 && !knot_changeset_rrsets_match((*rrsets)[i], rr)) {
- --i;
- }
- if (i >= 0) {
- // found RRSet to merge the new one into
- if (knot_rrset_merge((void **)&(*rrsets)[i],
- (void **)&rr) != KNOT_EOK) {
+ // Just check the last RRSet. If the RR belongs to it, merge it,
+ // otherwise just add the RR to the end of the list
+
+ if (*count > 0
+ && 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) {
return KNOT_ERROR;
}
- // remove the RR
- /*! \todo does this make sense? */
- knot_rrset_free(&rr); // used to be deep free with all 1's
-
+ knot_rrset_free(&rr);
return KNOT_EOK;
} else {
return knot_changeset_add_rrset(rrsets, count, allocated, rr);
@@ -211,7 +208,7 @@ int knot_changeset_add_soa(knot_changeset_t *changeset, knot_rrset_t *soa,
int knot_changesets_check_size(knot_changesets_t *changesets)
{
/* Check if allocated is sufficient. */
- if (changesets->count <= changesets->allocated) {
+ if (changesets->count < changesets->allocated) {
return KNOT_EOK;
}
@@ -243,7 +240,6 @@ int knot_changesets_check_size(knot_changesets_t *changesets)
void knot_free_changeset(knot_changeset_t **changeset)
{
- /* XXX XXX investigate wrong frees. */
assert((*changeset)->add_allocated >= (*changeset)->add_count);
assert((*changeset)->remove_allocated >= (*changeset)->remove_count);
assert((*changeset)->allocated >= (*changeset)->size);
@@ -292,7 +288,3 @@ void knot_free_changesets(knot_changesets_t **changesets)
free(*changesets);
*changesets = NULL;
}
-
-/*---------------------------------------------------------------------------*/
-
-
diff --git a/src/libknot/updates/changesets.h b/src/libknot/updates/changesets.h
index 0570fc9..642b155 100644..100755
--- a/src/libknot/updates/changesets.h
+++ b/src/libknot/updates/changesets.h
@@ -5,7 +5,7 @@
*
* \brief Structure for representing IXFR/DDNS changeset and its API.
*
- * \addtogroup libknot
+ * \addtogroup xfr
* @{
*/
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
@@ -90,9 +90,9 @@ typedef struct {
int new_rdata_count;
int new_rdata_allocated;
-// /*!
-// * Deleted (without contents) after successful update.
-// */
+ /*!
+ * Deleted (without contents) after successful update.
+ */
knot_node_t **old_nodes;
int old_nodes_count;
int old_nodes_allocated;
diff --git a/src/libknot/updates/ddns.c b/src/libknot/updates/ddns.c
index 025cd6b..905c44b 100644..100755
--- a/src/libknot/updates/ddns.c
+++ b/src/libknot/updates/ddns.c
@@ -97,7 +97,7 @@ static int knot_ddns_add_prereq_rrset(const knot_rrset_t *rrset,
}
knot_rrset_t *new_rrset = NULL;
- ret = knot_rrset_deep_copy(rrset, &new_rrset);
+ ret = knot_rrset_deep_copy(rrset, &new_rrset, 0);
if (ret != KNOT_EOK) {
return ret;
}
@@ -202,7 +202,7 @@ static int knot_ddns_add_update(knot_changeset_t *changeset,
* copy.
*/
knot_rrset_t *rrset_copy;
- ret = knot_rrset_deep_copy(rrset, &rrset_copy);
+ ret = knot_rrset_deep_copy(rrset, &rrset_copy, 0);
if (ret != KNOT_EOK) {
return ret;
}
diff --git a/src/libknot/updates/ddns.h b/src/libknot/updates/ddns.h
index dceebed..35dfcb7 100644..100755
--- a/src/libknot/updates/ddns.h
+++ b/src/libknot/updates/ddns.h
@@ -5,7 +5,7 @@
*
* \brief Dynamic updates processing.
*
- * \addtogroup query_processing
+ * \addtogroup ddns
* @{
*/
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
diff --git a/src/libknot/updates/xfr-in.c b/src/libknot/updates/xfr-in.c
index ea8178d..c870ece 100644..100755
--- a/src/libknot/updates/xfr-in.c
+++ b/src/libknot/updates/xfr-in.c
@@ -102,7 +102,7 @@ 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;
}
@@ -112,7 +112,7 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype,
char *name = knot_dname_to_str(xfr->tsig_key->name);
dbg_xfrin_detail("Signing XFR query with key (name %s): \n",
name);
- free(name);
+ free(name);
dbg_xfrin_hex_detail(xfr->tsig_key->secret,
xfr->tsig_key->secret_size);
@@ -152,9 +152,9 @@ static int xfrin_create_query(knot_dname_t *qname, uint16_t qtype,
int xfrin_create_soa_query(knot_dname_t *owner, knot_ns_xfr_t *xfr,
size_t *size)
{
- /*! \todo [TSIG] Should TSIG apply for SOA query too? */
return xfrin_create_query(owner, KNOT_RRTYPE_SOA,
- KNOT_CLASS_IN, xfr, size, 0, 0);
+ KNOT_CLASS_IN, xfr, size, 0,
+ xfr->tsig_key != NULL);
}
/*----------------------------------------------------------------------------*/
@@ -164,8 +164,8 @@ 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("Response - parsed: %zu, total wire size: %zu\n",
- soa_response->parsed, soa_response->size);
+ dbg_xfrin_verb("Response - parsed: %zu, total wire size: %zu\n",
+ soa_response->parsed, soa_response->size);
int ret;
if (soa_response->parsed < soa_response->size) {
@@ -199,7 +199,7 @@ dbg_xfrin_exec(
dbg_xfrin("Malformed data in SOA of zone %s\n", name);
free(name);
);
- return KNOT_EMALF; // maybe some other error
+ return KNOT_EMALF; // maybe some other error
}
/*
@@ -273,8 +273,8 @@ static int xfrin_add_orphan_rrsig(xfrin_orphan_rrsig_t **rrsigs,
&& knot_rdata_rrsig_type_covered(knot_rrset_rdata(
last->rrsig))
== knot_rdata_rrsig_type_covered(knot_rrset_rdata(rr))) {
- ret = knot_rrset_merge((void **)&last->rrsig,
- (void **)&rr);
+ ret = knot_rrset_merge_no_dupl((void **)&last->rrsig,
+ (void **)&rr);
if (ret != KNOT_EOK) {
return ret;
} else {
@@ -341,7 +341,7 @@ void xfrin_free_orphan_rrsigs(xfrin_orphan_rrsig_t **rrsigs)
}
/*----------------------------------------------------------------------------*/
-/*! \note [TSIG] */
+
static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
int tsig_req)
{
@@ -400,8 +400,8 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
}
if (ret != KNOT_EOK) {
- /*! \note [TSIG] No need to check TSIG error
- * here, propagate and check elsewhere.*/
+ /* No need to check TSIG error
+ * here, propagate and check elsewhere.*/
knot_rrset_deep_free(&tsig, 1, 1, 1);
return ret;
}
@@ -425,9 +425,7 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
tsig_rdata_time_signed(tsig);
- }/* else { // TSIG not required and not there
-
- }*/
+ }
} else if (tsig != NULL) {
// TSIG where it should not be
knot_rrset_deep_free(&tsig, 1, 1, 1);
@@ -441,9 +439,7 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
/*----------------------------------------------------------------------------*/
-int xfrin_process_axfr_packet(/*const uint8_t *pkt, size_t size,
- xfrin_constructed_zone_t **constr*/
- knot_ns_xfr_t *xfr)
+int xfrin_process_axfr_packet(knot_ns_xfr_t *xfr)
{
const uint8_t *pkt = xfr->wire;
size_t size = xfr->wire_size;
@@ -451,11 +447,10 @@ int xfrin_process_axfr_packet(/*const uint8_t *pkt, size_t size,
(xfrin_constructed_zone_t **)(&xfr->data);
if (pkt == NULL || constr == NULL) {
- dbg_xfrin("Wrong parameters supported.\n");
return KNOT_EBADARG;
}
- dbg_xfrin("Processing AXFR packet of size %zu.\n", size);
+ 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) {
@@ -473,8 +468,7 @@ int xfrin_process_axfr_packet(/*const uint8_t *pkt, size_t size,
int ret = knot_packet_parse_from_wire(packet, pkt, size, 1);
if (ret != KNOT_EOK) {
- dbg_xfrin("Could not parse packet: %s.\n",
- knot_strerror(ret));
+ dbg_xfrin("Could not parse packet: %s.\n", knot_strerror(ret));
knot_packet_free(&packet);
/*! \todo Cleanup. */
return KNOT_EMALF;
@@ -510,18 +504,16 @@ int xfrin_process_axfr_packet(/*const uint8_t *pkt, size_t size,
if (*constr == NULL) {
// this should be the first packet
- /*! \note [TSIG] Packet number for checking TSIG validation. */
+ /*! Packet number for checking TSIG validation. */
xfr->packet_nr = 0;
-// /*! \note [TSIG] Storing total size of data for TSIG digest. */
-// xfr->tsig_data_size = 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, 0);
+ knot_node_free(&node);
knot_rrset_deep_free(&rr, 1, 1, 1);
/*! \todo Cleanup. */
return KNOT_EMALF;
@@ -543,7 +535,7 @@ dbg_xfrin_exec(
);
/*! \todo Cleanup. */
knot_packet_free(&packet);
- knot_node_free(&node, 0);
+ knot_node_free(&node);
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_EMALF;
}
@@ -564,19 +556,20 @@ dbg_xfrin_exec(
if (*constr == NULL) {
dbg_xfrin("Failed to create new constr. zone.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 0);
+ knot_node_free(&node);
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ENOMEM;
}
memset(*constr, 0, sizeof(xfrin_constructed_zone_t));
- (*constr)->contents = knot_zone_contents_new(node, 0, 1, NULL);
-// assert(0);
+ dbg_xfrin_verb("Creating new zone contents.\n");
+ (*constr)->contents = knot_zone_contents_new(node, 0, 1,
+ xfr->zone);
if ((*constr)->contents== NULL) {
dbg_xfrin("Failed to create new zone.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 0);
+ knot_node_free(&node);
knot_rrset_deep_free(&rr, 1, 1, 1);
/*! \todo Cleanup. */
return KNOT_ENOMEM;
@@ -588,21 +581,19 @@ dbg_xfrin_exec(
assert(zone->apex == node);
assert(zone->apex->owner == rr->owner);
// add the RRSet to the node
- //ret = knot_node_add_rrset(node, rr, 0);
ret = knot_zone_contents_add_rrset(zone, rr, &node,
KNOT_RRSET_DUPL_MERGE, 1);
if (ret < 0) {
dbg_xfrin("Failed to add RRSet to zone node: %s.\n",
knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0);
+ knot_node_free(&node);
knot_rrset_deep_free(&rr, 1, 1, 1);
/*! \todo Cleanup. */
return KNOT_ERROR;
} else if (ret > 0) {
dbg_xfrin("Merged SOA RRSet.\n");
// merged, free the RRSet
- //knot_rrset_deep_free(&rr, 1, 0, 0);
knot_rrset_free(&rr);
}
@@ -613,20 +604,6 @@ dbg_xfrin_exec(
++xfr->packet_nr;
}
- /*! \note [TSIG] add the packet wire size to the data to be verified by
- * TSIG
- */
-// if (xfr->tsig_key) {
-// dbg_xfrin("Adding packet wire to TSIG data (size till now: %zu,"
-// " adding: %zu).\n", xfr->tsig_data_size,
-// xfr->wire_size);
-// assert(KNOT_NS_TSIG_DATA_MAX_SIZE - xfr->tsig_data_size
-// >= xfr->wire_size);
-// memcpy(xfr->tsig_data + xfr->tsig_data_size, xfr->wire,
-// xfr->wire_size);
-// xfr->tsig_data_size += xfr->wire_size;
-// }
-
assert(zone != NULL);
while (ret == KNOT_EOK && rr != NULL) {
@@ -637,9 +614,9 @@ dbg_xfrin_exec(
if (node != NULL
&& knot_dname_compare(rr->owner, node->owner) != 0) {
-dbg_xfrin_exec(
+dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(node->owner);
- dbg_xfrin("Node owner: %s\n", name);
+ dbg_xfrin_detail("Node owner: %s\n", name);
free(name);
);
if (!in_zone) {
@@ -659,16 +636,15 @@ dbg_xfrin_exec(
assert(knot_zone_contents_apex((zone)) != NULL);
assert(knot_node_rrset(knot_zone_contents_apex((zone)),
KNOT_RRTYPE_SOA) != NULL);
- dbg_xfrin("Found last SOA, transfer finished.\n");
+ dbg_xfrin_verb("Found last SOA, transfer finished.\n");
- dbg_xfrin("Verifying TSIG...\n");
+ dbg_xfrin_verb("Verifying TSIG...\n");
/*! \note [TSIG] Now check if there is not a TSIG record
* at the end of the packet.
*/
ret = xfrin_check_tsig(packet, xfr, 1);
- dbg_xfrin_detail("xfrin_check_tsig() returned %d\n",
- ret);
+ dbg_xfrin_verb("xfrin_check_tsig() returned %d\n", ret);
knot_packet_free(&packet);
knot_rrset_deep_free(&rr, 1, 1, 1);
@@ -682,8 +658,7 @@ dbg_xfrin_exec(
ret = xfrin_process_orphan_rrsigs(zone,
(*constr)->rrsigs);
if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to process orphan "
- "RRSIGs\n");
+ dbg_xfrin("Failed to process orphan RRSIGs\n");
/*! \todo Cleanup?? */
return ret;
}
@@ -700,8 +675,8 @@ dbg_xfrin_exec(
ret = knot_zone_contents_add_rrsigs(zone, rr,
&tmp_rrset, &node, KNOT_RRSET_DUPL_MERGE, 1);
if (ret == KNOT_ENONODE || ret == KNOT_ENORRSET) {
- dbg_xfrin("No node or RRSet for RRSIGs\n");
- dbg_xfrin("Saving for later insertion.\n");
+ dbg_xfrin_verb("No node or RRSet for RRSIGs\n");
+ dbg_xfrin_verb("Saving for later insertion.\n");
if (ret == KNOT_ENORRSET) {
in_zone = 1;
@@ -711,13 +686,13 @@ dbg_xfrin_exec(
rr);
if (ret > 0) {
- dbg_xfrin("Merged RRSIGs.\n");
+ dbg_xfrin_detail("Merged RRSIGs.\n");
knot_rrset_free(&rr);
} else if (ret != KNOT_EOK) {
dbg_xfrin("Failed to save orphan"
- " RRSIGs.\n");
+ " RRSIGs.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 0); // ???
+ knot_node_free(&node); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return ret;
}
@@ -725,15 +700,15 @@ dbg_xfrin_exec(
dbg_xfrin("Failed to add RRSIGs (%s).\n",
knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0); // ???
+ knot_node_free(&node); // ???
knot_rrset_deep_free(&rr, 1, 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("Found node for the record in "
- "zone: %s. Merged.\n", name);
+ dbg_xfrin_detail("Found node for the record in "
+ "zone: %s. Merged.\n", name);
free(name);
);
in_zone = 1;
@@ -741,13 +716,12 @@ dbg_xfrin_exec_verb(
} else if (ret == 2) {
// should not happen
assert(0);
-// knot_rrset_deep_free(&rr, 1, 1, 1);
} else {
assert(node != NULL);
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(node->owner);
- dbg_xfrin("Found node for the record in "
- "zone: %s.\n", name);
+ dbg_xfrin_detail("Found node for the record in "
+ "zone: %s.\n", name);
free(name);
);
in_zone = 1;
@@ -760,12 +734,12 @@ dbg_xfrin_exec_verb(
continue;
}
- /*! \note [TSIG] TSIG where it should not be - in Answer section.*/
+ /* TSIG where it should not be - in Answer section.*/
if (knot_rrset_type(rr) == KNOT_RRTYPE_TSIG) {
// not allowed here
- dbg_xfrin(" in Answer section.\n");
+ dbg_xfrin("TSIG in Answer section.\n");
knot_packet_free(&packet);
- knot_node_free(&node, 0); // ???
+ knot_node_free(&node); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_EMALF;
}
@@ -786,7 +760,7 @@ dbg_xfrin_exec_verb(
if (node == NULL && (node = get_node(zone,
knot_rrset_owner(rr))) != NULL) {
// the node for this RR was found in the zone
- dbg_xfrin("Found node for the record in zone.\n");
+ dbg_xfrin_detail("Found node for the record in zone\n");
in_zone = 1;
}
@@ -800,31 +774,30 @@ dbg_xfrin_exec_verb(
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ENOMEM;
}
- dbg_xfrin("Created new node for the record.\n");
+ dbg_xfrin_detail("Created new node for the record.\n");
// insert the RRSet to the node
- ret = knot_node_add_rrset(node, rr, 1);
+ ret = knot_node_add_rrset_no_dupl(node, rr);
if (ret < 0) {
- dbg_xfrin("Failed to add RRSet to node (%s"
- ")\n", knot_strerror(ret));
+ dbg_xfrin("Failed to add RRSet to node (%s)\n",
+ knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0); // ???
+ knot_node_free(&node); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ERROR;
} else if (ret > 0) {
// should not happen, this is new node
assert(0);
-// knot_rrset_deep_free(&rr, 1, 0, 0);
}
// insert the node into the zone
ret = add_node(zone, node, 1, 0, 1);
assert(node != NULL);
if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add node to zone (%s)"
- ".\n", knot_strerror(ret));
+ dbg_xfrin("Failed to add node to zone (%s).\n",
+ knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0); // ???
+ knot_node_free(&node); // ???
knot_rrset_deep_free(&rr, 1, 1, 1);
return KNOT_ERROR;
}
@@ -837,12 +810,11 @@ dbg_xfrin_exec_verb(
KNOT_RRSET_DUPL_MERGE, 1);
if (ret < 0) {
knot_packet_free(&packet);
- dbg_xfrin("Failed to add RRSet to zone:"
- "%s.\n", knot_strerror(ret));
+ dbg_xfrin("Failed to add RRSet to zone :%s.\n",
+ knot_strerror(ret));
return KNOT_ERROR;
} else if (ret > 0) {
// merged, free the RRSet
-// knot_rrset_deep_free(&rr, 1, 0, 0);
knot_rrset_free(&rr);
}
@@ -858,12 +830,11 @@ dbg_xfrin_exec_verb(
if (ret < 0) {
// some error in parsing
- dbg_xfrin("Could not parse next RR: %s.\n",
- knot_strerror(ret));
+ dbg_xfrin("Could not parse next RR: %s.\n", knot_strerror(ret));
knot_packet_free(&packet);
if (!in_zone) {
- knot_node_free(&node, 0);
+ knot_node_free(&node);
}
knot_rrset_deep_free(&rr, 1, 1, 1);
@@ -878,25 +849,23 @@ dbg_xfrin_exec_verb(
assert(node != NULL);
ret = knot_zone_contents_add_node(zone, node, 1, 0, 1);
if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add last node into zone (%s)"
- ".\n", knot_strerror(ret));
+ dbg_xfrin("Failed to add last node into zone (%s).\n",
+ knot_strerror(ret));
knot_packet_free(&packet);
- knot_node_free(&node, 0);
+ knot_node_free(&node);
return KNOT_ERROR; /*! \todo Other error */
}
}
- /*! \note [TSIG] Now check if there is not a TSIG record at the end of
- * the packet.
- */
+ /* 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));
++xfr->packet_nr;
knot_packet_free(&packet);
- dbg_xfrin("Processed one AXFR packet successfully.\n");
+ dbg_xfrin_verb("Processed one AXFR packet successfully.\n");
- /*! \note [TSIG] TSIG errors are propagated and reported in a standard
+ /* TSIG errors are propagated and reported in a standard
* manner, as we're in response processing, no further error response
* should be sent.
*/
@@ -920,8 +889,7 @@ static int xfrin_parse_first_rr(knot_packet_t **packet, const uint8_t *pkt,
int ret = knot_packet_parse_from_wire(*packet, pkt, size, 1);
if (ret != KNOT_EOK) {
- dbg_xfrin("Could not parse packet: %s.\n",
- knot_strerror(ret));
+ dbg_xfrin("Could not parse packet: %s.\n", knot_strerror(ret));
knot_packet_free(packet);
return KNOT_EMALF;
}
@@ -986,7 +954,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
}
if (*chs == NULL) {
- dbg_xfrin("Changesets empty, creating new.\n");
+ dbg_xfrin_verb("Changesets empty, creating new.\n");
ret = knot_changeset_allocate(chs);
if (ret != KNOT_EOK) {
@@ -1007,7 +975,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
(*chs)->first_soa = rr;
state = -1;
- dbg_xfrin("First SOA of IXFR saved, state set to -1.\n");
+ 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);
@@ -1050,7 +1018,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
ret = KNOT_EBADARG;
goto cleanup;
}
- dbg_xfrin("Changesets present.\n");
+ dbg_xfrin_detail("Changesets present.\n");
}
/*
@@ -1090,7 +1058,7 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
* calls to this function.
*/
if (state != -1) {
- dbg_xfrin("State is not -1, deciding...\n");
+ 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);
@@ -1108,15 +1076,15 @@ int xfrin_process_ixfr_packet(knot_ns_xfr_t *xfr)
}
}
- dbg_xfrin("State before the loop: %d\n", state);
+ 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_verb("Next loop, state: %d\n", state);
+ dbg_xfrin_detail("Next loop, state: %d\n", state);
char *name = knot_dname_to_str(knot_rrset_owner(rr));
- dbg_xfrin_verb("Actual RR: %s, type %s.\n", name,
+ dbg_xfrin_detail("Actual RR: %s, type %s.\n", name,
knot_rrtype_to_string(knot_rrset_type(rr)));
free(name);
);
@@ -1128,7 +1096,7 @@ 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("RR type: %s\n",
+ dbg_xfrin_verb("RR type: %s\n",
knot_rrtype_to_string(knot_rrset_type(rr)));
ret = KNOT_EMALF;
knot_rrset_deep_free(&rr, 1, 1, 1);
@@ -1222,15 +1190,12 @@ dbg_xfrin_exec_verb(
}
}
break;
- // dead code
-// default:
-// assert(0);
}
// parse the next RR
- dbg_xfrin_verb("Parsing next RR..\n");
+ dbg_xfrin_detail("Parsing next RR..\n");
ret = knot_packet_parse_next_rr_answer(packet, &rr);
- dbg_xfrin_verb("Returned %d, %p.\n", ret, rr);
+ dbg_xfrin_detail("Returned %d, %p.\n", ret, rr);
}
/*! \note Check TSIG, we're at the end of packet. It may not be
@@ -1238,7 +1203,7 @@ dbg_xfrin_exec_verb(
*/
ret = xfrin_check_tsig(packet, xfr,
knot_ns_tsig_required(xfr->packet_nr));
- dbg_xfrin_detail("xfrin_check_tsig() returned %d\n", ret);
+ dbg_xfrin_verb("xfrin_check_tsig() returned %d\n", ret);
++xfr->packet_nr;
/*! \note [TSIG] Cleanup and propagate error if TSIG validation fails.*/
@@ -1255,7 +1220,7 @@ cleanup:
/* We should go here only if some error occured. */
assert(ret < 0);
- dbg_xfrin("Cleanup after processing IXFR/IN packet.\n");
+ dbg_xfrin_detail("Cleanup after processing IXFR/IN packet.\n");
knot_free_changesets(chs);
knot_packet_free(&packet);
xfr->data = 0;
@@ -1337,6 +1302,9 @@ static int xfrin_changes_check_rdata(knot_rdata_t ***rdatas, uint **types,
}
int new_count = (*allocated == 0) ? 2 : *allocated * 2;
+ while (new_count < count + to_add) {
+ new_count *= 2;
+ }
/* Allocate new memory block. */
knot_rdata_t **rdatas_new = malloc(new_count * sizeof(knot_rdata_t *));
@@ -1372,36 +1340,21 @@ static int xfrin_changes_check_rdata(knot_rdata_t ***rdatas, uint **types,
static void xfrin_changes_add_rdata(knot_rdata_t **rdatas, uint *types,
int *count, knot_rdata_t *rdata, uint type)
{
- dbg_xfrin_detail("Adding RDATA to RDATA list: %p\n", rdata);
-
if (rdata == NULL) {
return;
}
-//dbg_xfrin_exec_detail(
-// // try to find the first RDATA in the given list
-// for (int i = 0; i < *count; ++i) {
-// knot_rdata_t *r = rdatas[i];
-// if (r == NULL) {
-// continue;
-// }
-// while (r != NULL && r->next != rdatas[i]) {
-// if (r == rdata) {
-// dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
-// knot_rdata_dump(rdata, type, 0);
-// }
-// r = r->next;
-// }
-// if (r == rdata) {
-// dbg_xfrin_detail("Found same RDATA: %p\n", rdata);
-// knot_rdata_dump(rdata, type, 0);
-// }
-// }
-//);
+ // Add all RDATAs from the chain!!
- rdatas[*count] = rdata;
- types[*count] = type;
- ++*count;
+ 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);
}
/*----------------------------------------------------------------------------*/
@@ -1412,7 +1365,6 @@ static void xfrin_zone_contents_free(knot_zone_contents_t **contents)
if ((*contents)->table != NULL) {
ck_destroy_table(&(*contents)->table, NULL, 0);
-// ck_table_free(&(*contents)->table);
}
// free the zone tree with nodes
@@ -1459,10 +1411,9 @@ static knot_rdata_t *xfrin_remove_rdata(knot_rrset_t *from,
static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
knot_changes_t *changes)
{
- dbg_xfrin_verb("Copying old RRSet: %p\n", old);
+ dbg_xfrin_detail("Copying old RRSet: %p\n", old);
// create new RRSet by copying the old one
-// int ret = knot_rrset_shallow_copy(old, copy);
- int ret = knot_rrset_deep_copy(old, copy);
+ int ret = knot_rrset_deep_copy(old, copy, 0);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to create RRSet copy.\n");
return KNOT_ENOMEM;
@@ -1479,11 +1430,14 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
return ret;
}
+ int 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 = xfrin_changes_check_rdata(&changes->new_rdata,
&changes->new_rdata_types,
changes->new_rdata_count,
- &changes->new_rdata_allocated, 2);
+ &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);
@@ -1492,7 +1446,8 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
changes->new_rrsets[changes->new_rrsets_count++] = *copy;
- dbg_xfrin_verb("Adding RDATA from the RRSet copy to new RDATA list.\n");
+ dbg_xfrin_detail("Adding RDATA from the RRSet copy to new RDATA list."
+ "\n");
xfrin_changes_add_rdata(changes->new_rdata, changes->new_rdata_types,
&changes->new_rdata_count,
knot_rrset_get_rdata(*copy),
@@ -1502,8 +1457,9 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
assert(old->rrsigs != NULL);
changes->new_rrsets[changes->new_rrsets_count++] =
(*copy)->rrsigs;
- dbg_xfrin_verb("Adding RDATA from RRSIG of the RRSet copy to "
- "new RDATA list.\n");
+
+ dbg_xfrin_detail("Adding RDATA from RRSIG of the RRSet copy to "
+ "new RDATA list.\n");
xfrin_changes_add_rdata(changes->new_rdata,
changes->new_rdata_types,
&changes->new_rdata_count,
@@ -1520,11 +1476,14 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
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 = xfrin_changes_check_rdata(&changes->old_rdata,
&changes->old_rdata_types,
changes->old_rdata_count,
- &changes->old_rdata_allocated, 2);
+ &changes->old_rdata_allocated, count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add old RRSet to list.\n");
return ret;
@@ -1532,7 +1491,7 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
changes->old_rrsets[changes->old_rrsets_count++] = old;
- dbg_xfrin_verb("Adding RDATA from old RRSet to old RDATA list.\n");
+ dbg_xfrin_detail("Adding RDATA from old RRSet to old RDATA list.\n");
xfrin_changes_add_rdata(changes->old_rdata, changes->old_rdata_types,
&changes->old_rdata_count, old->rdata,
knot_rrset_type(old));
@@ -1541,8 +1500,8 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
assert(old->rrsigs != NULL);
changes->old_rrsets[changes->old_rrsets_count++] = old->rrsigs;
- dbg_xfrin_verb("Adding RDATA from RRSIG of the old RRSet to "
- "old RDATA list.\n");
+ dbg_xfrin_detail("Adding RDATA from RRSIG of the old RRSet to "
+ "old RDATA list.\n");
xfrin_changes_add_rdata(changes->old_rdata,
changes->old_rdata_types,
&changes->old_rdata_count,
@@ -1558,15 +1517,15 @@ static int xfrin_copy_old_rrset(knot_rrset_t *old, knot_rrset_t **copy,
static int xfrin_copy_rrset(knot_node_t *node, knot_rr_type_t type,
knot_rrset_t **rrset, knot_changes_t *changes)
{
-dbg_xfrin_exec_verb(
+dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_node_owner(node));
- dbg_xfrin_verb("Removing RRSet of type %s from node %s (%p)\n",
+ dbg_xfrin_detail("Removing RRSet of type %s from node %s (%p)\n",
knot_rrtype_to_string(type), name, node);
free(name);
);
knot_rrset_t *old = knot_node_remove_rrset(node, type);
- dbg_xfrin_verb("Removed RRSet: %p\n", old);
+ 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));
@@ -1580,7 +1539,7 @@ dbg_xfrin_exec_verb(
return ret;
}
- dbg_xfrin_verb("Copied old rrset %p to new %p.\n", old, *rrset);
+ 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);
@@ -1597,7 +1556,8 @@ dbg_xfrin_exec_verb(
static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
const knot_rrset_t *remove,
knot_node_t *node,
- knot_rrset_t **rrset)
+ knot_rrset_t **rrset,
+ knot_rrset_t **rrsigs_old)
{
assert(changes != NULL);
assert(remove != NULL);
@@ -1613,37 +1573,35 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
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))) {
+ 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))) {
+ // 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));
// copy the rrset
- dbg_xfrin_verb("Copying RRSet that carries the RRSIGs.\n");
+ dbg_xfrin_detail("Copying RRSet that carries the RRSIGs.\n");
ret = xfrin_copy_rrset(node, type, rrset, changes);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to copy rrset from changeset.\n");
return ret;
}
+ dbg_xfrin_detail("Copied RRSet:\n");
+ knot_rrset_dump(*rrset, 0);
copied = 1;
- } else {
- // we should have the right RRSIG RRSet in *rrset
- assert(knot_rrset_type(*rrset)
- == knot_rdata_rrsig_type_covered(
- knot_rrset_rdata(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");
}
-
+
// get the old rrsigs
knot_rrset_t *old = knot_rrset_get_rrsigs(*rrset);
- dbg_xfrin_verb("Old RRSIGs from RRSet: %p\n", old);
+ dbg_xfrin_detail("Old RRSIGs from RRSet: %p\n", old);
if (old == NULL) {
return 1;
}
@@ -1651,14 +1609,22 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
// copy the RRSIGs
knot_rrset_t *rrsigs = NULL;
if (!copied) {
- ret = xfrin_copy_old_rrset(old, &rrsigs, changes);
- if (ret != KNOT_EOK) {
- return ret;
+ // check if the stored RRSIGs are not the right ones
+ if (*rrsigs_old && *rrsigs_old == (*rrset)->rrsigs) {
+ dbg_xfrin_verb("Using RRSIG from previous iteration\n");
+ rrsigs = *rrsigs_old;
+ } else {
+ ret = xfrin_copy_old_rrset(old, &rrsigs, changes);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+ dbg_xfrin_detail("Copied RRSIGs: %p\n", rrsigs);
+ dbg_xfrin_detail("Copied RRSet:\n");
+ knot_rrset_dump(rrsigs, 0);
}
- dbg_xfrin_verb("Copied RRSIGs: %p\n", rrsigs);
} else {
rrsigs = old;
- dbg_xfrin_verb("Using old RRSIGs: %p\n", rrsigs);
+ dbg_xfrin_detail("Using old RRSIGs: %p\n", rrsigs);
}
// set the RRSIGs to the new RRSet copy
@@ -1667,21 +1633,25 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
return KNOT_ERROR;
}
+ *rrsigs_old = 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);
if (rdata == NULL) {
dbg_xfrin("Failed to remove RDATA from RRSet: %s.\n",
- knot_strerror(ret));
+ knot_strerror(ret));
return 1;
}
+
+ int count = knot_rdata_count(rdata);
// connect the RDATA to the list of old RDATA
ret = xfrin_changes_check_rdata(&changes->old_rdata,
&changes->old_rdata_types,
changes->old_rdata_count,
- &changes->old_rdata_allocated, 1);
+ &changes->old_rdata_allocated, count);
if (ret != KNOT_EOK) {
return ret;
}
@@ -1704,7 +1674,7 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
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;
@@ -1729,7 +1699,7 @@ static int xfrin_apply_remove_rrsigs(knot_changes_t *changes,
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;
@@ -1762,10 +1732,13 @@ static int xfrin_apply_remove_normal(knot_changes_t *changes,
// now we have the copy of the node, so lets get the right RRSet
// check if we do not already have it
- if (!*rrset
- || knot_dname_compare(knot_rrset_owner(*rrset),
- knot_node_owner(node)) != 0
- || knot_rrset_type(*rrset) != knot_rrset_type(remove)) {
+ if (*rrset
+ && knot_dname_compare(knot_rrset_owner(*rrset),
+ 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
* copied RRSet. In that case it would be
@@ -1774,30 +1747,29 @@ static int xfrin_apply_remove_normal(knot_changes_t *changes,
*/
ret = xfrin_copy_rrset(node,
knot_rrset_type(remove), rrset, changes);
- dbg_xfrin_detail("Copied RRSet:\n");
- knot_rrset_dump(*rrset, 0);
if (ret != KNOT_EOK) {
return ret;
}
- } /*! \todo Does some other case even occur? */
+ dbg_xfrin_detail("Copied RRSet:\n");
+ knot_rrset_dump(*rrset, 0);
+ }
if (*rrset == NULL) {
dbg_xfrin_verb("RRSet not found for RR to be removed.\n");
return 1;
}
-dbg_xfrin_exec_verb(
+dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
- dbg_xfrin("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 %s\n", name,
+ knot_rrtype_to_string(knot_rrset_type(*rrset)));
free(name);
);
- // remove the specified RRs from the RRSet (de facto difference of
- // sets)
+ // remove the specified RRs from the RRSet (de facto difference of sets)
knot_rdata_t *rdata = xfrin_remove_rdata(*rrset, remove);
if (rdata == NULL) {
- dbg_xfrin("Failed to remove RDATA from RRSet\n");
+ dbg_xfrin_verb("Failed to remove RDATA from RRSet\n");
// In this case, the RDATA was not found in the RRSet
return 1;
}
@@ -1814,11 +1786,12 @@ dbg_xfrin_exec_detail(
}
);
+ int count = knot_rdata_count(rdata);
// connect the RDATA to the list of old RDATA
ret = xfrin_changes_check_rdata(&changes->old_rdata,
&changes->old_rdata_types,
changes->old_rdata_count,
- &changes->old_rdata_allocated, 1);
+ &changes->old_rdata_allocated, count);
if (ret != KNOT_EOK) {
return ret;
}
@@ -1859,7 +1832,7 @@ dbg_xfrin_exec_detail(
}
/*----------------------------------------------------------------------------*/
-
+/*! \todo Needs review - RRs may not be merged into RRSets. */
static int xfrin_apply_remove_all_rrsets(knot_changes_t *changes,
knot_node_t *node, uint16_t type)
{
@@ -1918,9 +1891,6 @@ static knot_node_t *xfrin_add_new_node(knot_zone_contents_t *contents,
// insert the node into zone structures and create parents if
// necessary
-// dbg_xfrin("Adding new node to zone. From owner: %s type %s\n",
-// knot_dname_to_str(node->owner),
-// knot_rrtype_to_string(rrset->type));
if (is_nsec3) {
ret = knot_zone_contents_add_nsec3_node(contents, node, 1, 0,
1);
@@ -1959,35 +1929,53 @@ static int xfrin_apply_add_normal(knot_changes_t *changes,
int ret;
- dbg_xfrin_verb("applying rrset:\n");
+dbg_xfrin_exec_detail(
+ dbg_xfrin_detail("applying rrset:\n");
knot_rrset_dump(add, 0);
+);
+ int copied = 0;
/*! \note Reusing RRSet from previous function caused it not to be
* removed from the node.
* Maybe modification of the code would allow reusing the RRSet
* as in apply_add_rrsigs() - the RRSet should not be copied
* in such case.
*/
-// if (!*rrset
-// || knot_dname_compare(knot_rrset_owner(*rrset),
-// knot_node_owner(node)) != 0
-// || knot_rrset_type(*rrset)
-// != knot_rrset_type(add)) {
-// dbg_xfrin("Removing rrset!\n");
-// *rrset = knot_node_remove_rrset(node, knot_rrset_type(add));
-// }
-
- *rrset = knot_node_remove_rrset(node, knot_rrset_type(add));
-
- dbg_xfrin_verb("Removed RRSet: \n");
+ if (*rrset
+ && knot_dname_compare(knot_rrset_owner(*rrset),
+ knot_node_owner(node)) == 0
+ && knot_rrset_type(*rrset) == knot_rrset_type(add)) {
+ dbg_xfrin_verb("Using RRSet from previous iteration.\n");
+ } else {
+ dbg_xfrin_detail("Removing rrset!\n");
+ *rrset = knot_node_remove_rrset(node, knot_rrset_type(add));
+
+ knot_rrset_t *old = *rrset;
+
+ if (*rrset != NULL) {
+ ret = xfrin_copy_old_rrset(old, rrset, changes);
+ if (ret != KNOT_EOK) {
+ return ret;
+ }
+
+ dbg_xfrin_detail("Copied RRSet: %p\n", *rrset);
+ dbg_xfrin_detail("Copied RRSet:\n");
+ knot_rrset_dump(*rrset, 0);
+ copied = 1;
+ }
+ }
+
+dbg_xfrin_exec_detail(
+ dbg_xfrin_detail("Removed RRSet: \n");
knot_rrset_dump(*rrset, 1);
+);
if (*rrset == NULL) {
-dbg_xfrin_exec_verb(
+dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(add->owner);
- dbg_xfrin_verb("RRSet to be added not found in zone.\n");
- dbg_xfrin_verb("owner: %s type: %s\n", name,
- knot_rrtype_to_string(add->type));
+ 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));
free(name);
);
// add the RRSet from the changeset to the node
@@ -2013,25 +2001,12 @@ dbg_xfrin_exec_verb(
return 1; // return 1 to indicate the add RRSet was used
}
- knot_rrset_t *old = *rrset;
-
-dbg_xfrin_exec_verb(
+dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
- dbg_xfrin("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 %s\n", name,
+ knot_rrtype_to_string(knot_rrset_type(*rrset)));
free(name);
);
-// knot_rrset_dump(*rrset, 1);
- ret = xfrin_copy_old_rrset(old, rrset, changes);
- if (ret != KNOT_EOK) {
- return ret;
- }
-
- dbg_xfrin_verb("Copied RRSet: %p\n", *rrset);
-
-// dbg_xfrin("After copy: Found RRSet with owner %s, type %s\n",
-// knot_dname_to_str((*rrset)->owner),
-// knot_rrtype_to_string(knot_rrset_type(*rrset)));
// merge the changeset RRSet to the copy
/* What if the update fails?
@@ -2044,25 +2019,38 @@ dbg_xfrin_exec_verb(
*
* TODO: add the 'add' rrset to list of old RRSets?
*/
- dbg_xfrin_verb("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: %s, %s\n",
+ (*rrset)->owner->name, add->owner->name,
+ knot_rrtype_to_string((*rrset)->type),
+ knot_rrtype_to_string(add->type));
dbg_xfrin_detail("RDATA in RRSet1: %p, RDATA in RRSet2: %p\n",
(*rrset)->rdata, add->rdata);
- ret = knot_rrset_merge((void **)rrset, (void **)&add);
+ /* 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
+ && 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);
if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to merge changeset RRSet to copy.\n");
- return KNOT_ERROR;
+ dbg_xfrin("Failed to merge changeset RRSet.\n");
+ return ret;
}
- dbg_xfrin_verb("Merge returned: %d\n", ret);
+ dbg_xfrin_detail("Merge returned: %d\n", ret);
knot_rrset_dump(*rrset, 1);
- ret = knot_node_add_rrset(node, *rrset, 0);
- if (ret < 0) {
- dbg_xfrin("Failed to add merged RRSet to the node.\n");
- return ret;
+ if (copied) {
+ ret = knot_node_add_rrset(node, *rrset, 0);
+
+ if (ret < 0) {
+ dbg_xfrin("Failed to add merged RRSet to the node.\n");
+ return ret;
+ }
}
// return 2 so that the add RRSet is removed from
@@ -2078,6 +2066,7 @@ static int xfrin_apply_add_rrsig(knot_changes_t *changes,
knot_rrset_t *add,
knot_node_t *node,
knot_rrset_t **rrset,
+ knot_rrset_t **rrsigs_old,
knot_zone_contents_t *contents)
{
assert(changes != NULL);
@@ -2095,8 +2084,8 @@ static int xfrin_apply_add_rrsig(knot_changes_t *changes,
dbg_xfrin_exec_verb(
char *name = knot_dname_to_str(knot_rrset_owner(add));
const char *typestr = knot_rrtype_to_string(type);
- dbg_xfrin("Adding RRSIG: Owner %s, type covered %s.\n",
- name, typestr);
+ dbg_xfrin_verb("Adding RRSIG: Owner %s, type covered %s.\n",
+ name, typestr);
free(name);
);
@@ -2105,11 +2094,12 @@ dbg_xfrin_exec_verb(
/*! \note Here the check is OK, because if we aready have the RRSet,
* it's a copied one, so it is OK to modify it right away.
*/
- 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(add))) {
+ if (*rrset
+ && knot_dname_compare(knot_rrset_owner(*rrset),
+ knot_node_owner(node)) == 0
+ && knot_rrset_type(*rrset) == type) {
+ dbg_xfrin_verb("Using RRSet from previous iteration.\n");
+ } else {
// copy the rrset
ret = xfrin_copy_rrset(node, type, rrset, changes);
if (ret < 0) {
@@ -2118,15 +2108,12 @@ dbg_xfrin_exec_verb(
*rrset = NULL;
}
copied = 1;
- } else {
- // we should have the right RRSIG RRSet in *rrset
- assert(knot_rrset_type(*rrset) == type);
- // this RRSet should be the already copied RRSet so we may
- // update it right away
+ dbg_xfrin_detail("Copied RRSet:\n");
+ knot_rrset_dump(*rrset, 0);
}
if (*rrset == NULL) {
- dbg_xfrin_verb("RRSet to be added not found in zone.\n");
+ 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,
@@ -2136,7 +2123,7 @@ dbg_xfrin_exec_verb(
dbg_xfrin("Failed to create new RRSet for RRSIGs.\n");
return KNOT_ENOMEM;
}
- dbg_xfrin_verb("Created new RRSet for RRSIG: %p.\n", *rrset);
+ dbg_xfrin_detail("Created new RRSet for RRSIG: %p.\n", *rrset);
// add the RRset to the list of new RRsets
ret = xfrin_changes_check_rrsets(
@@ -2144,8 +2131,7 @@ dbg_xfrin_exec_verb(
&changes->new_rrsets_count,
&changes->new_rrsets_allocated, 1);
if (ret != KNOT_EOK) {
- dbg_xfrin("Failed to add old RRSet to "
- "list.\n");
+ dbg_xfrin("Failed to add old RRSet to list.\n");
knot_rrset_free(rrset);
return ret;
}
@@ -2163,20 +2149,19 @@ dbg_xfrin_exec_verb(
changes->new_rrsets[changes->new_rrsets_count++] = *rrset;
}
-dbg_xfrin_exec_verb(
+dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_rrset_owner(*rrset));
- dbg_xfrin("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 %s\n", name,
+ knot_rrtype_to_string(knot_rrset_type(*rrset)));
free(name);
);
if (knot_rrset_rrsigs(*rrset) == NULL) {
- dbg_xfrin_verb("Adding new RRSIGs to RRSet.\n");
+ dbg_xfrin_detail("Adding new RRSIGs to RRSet.\n");
ret = knot_zone_contents_add_rrsigs(contents, add, rrset, &node,
KNOT_RRSET_DUPL_SKIP, 1);
-// ret = knot_rrset_set_rrsigs(*rrset, add);
if (ret < 0) {
dbg_xfrin("Failed to add RRSIGs to the RRSet.\n");
return KNOT_ERROR;
@@ -2191,20 +2176,30 @@ dbg_xfrin_exec_verb(
knot_rrset_t *rrsig;
if (!copied) {
- ret = xfrin_copy_old_rrset(old, &rrsig, changes);
- if (ret != KNOT_EOK) {
- return ret;
+ // check if the stored RRSIGs are not the right ones
+ if (*rrsigs_old && *rrsigs_old == old) {
+ dbg_xfrin_verb("Using RRSIG from previous iteration\n");
+ rrsig = *rrsigs_old;
+ } else {
+ ret = xfrin_copy_old_rrset(old, &rrsig, changes);
+ 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);
}
} 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_verb("Merging RRSIG to the one in the RRSet.\n");
- ret = knot_rrset_merge((void **)&rrsig, (void **)&add);
+ dbg_xfrin_detail("Merging RRSIG to the one in the RRSet.\n");
+ ret = knot_rrset_merge_no_dupl((void **)&rrsig, (void **)&add);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to merge changeset RRSIG to copy: %s"
".\n", knot_strerror(ret));
@@ -2232,23 +2227,50 @@ void xfrin_cleanup_successful_update(knot_changes_t **changes)
// 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]));
+ (*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);
- 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]);
- }
+ // 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]);
+// }
}
+ // 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]));
+ dbg_xfrin_detail("Deleting old empty node: %p, owner: %s\n",
+ (*changes)->old_nodes[i], name);
+ free(name);
+);
+ knot_node_free(&(*changes)->old_nodes[i]);
+ }
+
+ // free empty NSEC3 nodes
+ 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]));
+ dbg_xfrin_detail("Deleting old empty node: %p, owner: %s\n",
+ (*changes)->old_nsec3[i], name);
+ free(name);
+);
+ knot_node_free(&(*changes)->old_nsec3[i]);
+ }
+
// free allocated arrays of nodes and rrsets
free((*changes)->new_rrsets);
free((*changes)->new_rdata);
@@ -2304,13 +2326,21 @@ static void xfrin_switch_node_in_dname_table(knot_dname_t *dname, void *data)
{
UNUSED(data);
- if (knot_dname_node(dname) == NULL) {
+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;
}
- assert(knot_node_new_node(knot_dname_node(dname)) != NULL);
- knot_dname_set_node(dname, knot_node_get_new_node(
- knot_dname_get_node(dname)));
+ knot_dname_update_node(dname);
}
/*----------------------------------------------------------------------------*/
@@ -2333,10 +2363,10 @@ static int xfrin_switch_nodes(knot_zone_contents_t *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);
+// // 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);
return KNOT_EOK;
}
@@ -2349,7 +2379,6 @@ static void xfrin_zone_contents_free2(knot_zone_contents_t **contents)
if ((*contents)->table != NULL) {
ck_destroy_table(&(*contents)->table, NULL, 0);
-// ck_table_free(&(*contents)->table);
}
// free the zone tree, but only the structure
@@ -2423,8 +2452,8 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
}
for (int i = 0; i < (*changes)->new_rdata_count; ++i) {
- dbg_xfrin("Freeing %d. RDATA chain: %p\n", i,
- (*changes)->new_rdata[i]);
+ dbg_xfrin_detail("Freeing %d. RDATA: %p\n", i,
+ (*changes)->new_rdata[i]);
/*
* In some case, the same RDATA may be stored in
@@ -2438,28 +2467,14 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
* already deleted, but that may be very time-consuming.
*/
- // discard the whole chain of RDATA
- knot_rdata_t *rdata = (*changes)->new_rdata[i];
- knot_rdata_t *rdata_next = NULL;
-
- while (rdata != NULL && rdata->next !=
- (*changes)->new_rdata[i]) {
- assert(rdata->next != rdata);
- rdata_next = rdata->next;
- dbg_xfrin(" Deleting RDATA: %p\n", rdata);
- knot_rdata_deep_free(&rdata,
- (*changes)->new_rdata_types[i], 1);
- rdata = rdata_next;
- }
-
- assert(rdata == NULL
- || rdata->next == (*changes)->new_rdata[i]);
+ /*
+ * Every RDATA from a chain is stored separately.
+ * We thus do not follow the RDATA chains and free only
+ * the first RDATA in each.
+ */
- dbg_xfrin(" Deleting RDATA: %p\n", rdata);
- knot_rdata_deep_free(&rdata,
+ knot_rdata_deep_free(&(*changes)->new_rdata[i],
(*changes)->new_rdata_types[i], 1);
-
- //(*changes)->new_rdata[i] = NULL;
}
// free allocated arrays of nodes and rrsets
@@ -2481,9 +2496,9 @@ void xfrin_rollback_update(knot_zone_contents_t *old_contents,
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_remove2(knot_zone_contents_t *contents,
- knot_changeset_t *chset,
- knot_changes_t *changes)
+static int xfrin_apply_remove(knot_zone_contents_t *contents,
+ knot_changeset_t *chset,
+ knot_changes_t *changes)
{
/*
* Iterate over removed RRSets, and remove them from the new nodes
@@ -2492,7 +2507,7 @@ static int xfrin_apply_remove2(knot_zone_contents_t *contents,
*/
int ret = 0;
knot_node_t *node = NULL;
- knot_rrset_t *rrset = NULL;
+ knot_rrset_t *rrset = NULL, *rrsigs = NULL;
int is_nsec3 = 0;
@@ -2501,8 +2516,8 @@ 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])));
+ knot_rrtype_to_string(
+ knot_rrset_type(chset->remove[i])));
free(name);
);
dbg_xfrin_exec_detail(
@@ -2551,7 +2566,7 @@ dbg_xfrin_exec_detail(
// this should work also for UPDATE
ret = xfrin_apply_remove_rrsigs(changes,
chset->remove[i],
- node, &rrset);
+ node, &rrset, &rrsigs);
} else {
// this should work also for UPDATE
ret = xfrin_apply_remove_normal(changes,
@@ -2559,7 +2574,7 @@ dbg_xfrin_exec_detail(
node, &rrset);
}
- dbg_xfrin_verb("xfrin_apply_remove() ret = %d\n", ret);
+ dbg_xfrin_detail("xfrin_apply_remove() ret = %d\n", ret);
if (ret > 0) {
continue;
@@ -2573,13 +2588,14 @@ dbg_xfrin_exec_detail(
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_add2(knot_zone_contents_t *contents,
- knot_changeset_t *chset,
- knot_changes_t *changes)
+static int xfrin_apply_add(knot_zone_contents_t *contents,
+ knot_changeset_t *chset,
+ knot_changes_t *changes)
{
int ret = 0;
knot_node_t *node = NULL;
knot_rrset_t *rrset = NULL;
+ knot_rrset_t *rrsigs = NULL;
int is_nsec3 = 0;
@@ -2588,8 +2604,8 @@ 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])));
+ knot_rrtype_to_string(
+ knot_rrset_type(chset->add[i])));
free(name);
);
dbg_xfrin_exec_detail(
@@ -2605,14 +2621,14 @@ dbg_xfrin_exec_detail(
knot_rrset_rdata(chset->add[i]))
== KNOT_RRTYPE_NSEC3))
{
- dbg_xfrin_verb("This is NSEC3-related RRSet.\n");
+ dbg_xfrin_detail("This is NSEC3-related RRSet.\n");
is_nsec3 = 1;
}
// check if the old node is not the one we should use
if (!node || knot_rrset_owner(chset->add[i])
!= knot_node_owner(node)) {
- dbg_xfrin_verb("Searching for node...\n");
+ dbg_xfrin_detail("Searching for node...\n");
if (is_nsec3) {
node = knot_zone_contents_get_nsec3_node(
contents,
@@ -2624,7 +2640,8 @@ dbg_xfrin_exec_detail(
if (node == NULL) {
// create new node, connect it properly to the
// zone nodes
- dbg_xfrin_verb("Node not found. Creating new.\n");
+ dbg_xfrin_detail("Node not found. Creating new."
+ "\n");
node = xfrin_add_new_node(contents,
chset->add[i],
is_nsec3);
@@ -2640,7 +2657,8 @@ 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, contents);
+ node, &rrset, &rrsigs,
+ contents);
} else {
ret = xfrin_apply_add_normal(changes, chset->add[i],
node, &rrset, contents);
@@ -2648,8 +2666,8 @@ dbg_xfrin_exec_detail(
assert(ret != KNOT_EOK);
- dbg_xfrin_verb("xfrin_apply_..() returned %d, rrset: %p\n", ret,
- rrset);
+ dbg_xfrin_detail("xfrin_apply_..() returned %s, rrset: %p\n",
+ knot_strerror(ret), rrset);
if (ret > 0) {
if (ret == 1) {
@@ -2670,21 +2688,24 @@ dbg_xfrin_exec_detail(
= chset->add[i];
// the same goes for the RDATA
+ int count = knot_rrset_rdata_rr_count(
+ chset->add[i]);
// connect the RDATA to the list of new RDATA
- int res = xfrin_changes_check_rdata(&changes->new_rdata,
+ int res = xfrin_changes_check_rdata(
+ &changes->new_rdata,
&changes->new_rdata_types,
changes->new_rdata_count,
- &changes->new_rdata_allocated, 1);
+ &changes->new_rdata_allocated, count);
if (res != KNOT_EOK) {
return res;
}
xfrin_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_types,
+ &changes->new_rdata_count,
+ knot_rrset_get_rdata(chset->add[i]),
+ knot_rrset_type(chset->add[i]));
chset->add[i] = NULL;
} else if (ret == 2) {
@@ -2712,9 +2733,9 @@ dbg_xfrin_exec_detail(
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
- knot_changes_t *changes,
- knot_changeset_t *chset)
+static int xfrin_apply_replace_soa(knot_zone_contents_t *contents,
+ knot_changes_t *changes,
+ knot_changeset_t *chset)
{
dbg_xfrin("Replacing SOA record.\n");
knot_node_t *node = knot_zone_contents_get_apex(contents);
@@ -2762,11 +2783,13 @@ static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
return ret;
}
+ int count = knot_rrset_rdata_rr_count(rrset);
+ count += knot_rrset_rdata_rr_count(chset->soa_to);
// save the new SOA RDATA
ret = xfrin_changes_check_rdata(&changes->new_rdata,
&changes->new_rdata_types,
changes->new_rdata_count,
- &changes->new_rdata_allocated, 1);
+ &changes->new_rdata_allocated, count);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to add new RDATA to list.\n");
return ret;
@@ -2813,9 +2836,9 @@ static int xfrin_apply_replace_soa2(knot_zone_contents_t *contents,
/*----------------------------------------------------------------------------*/
-static int xfrin_apply_changeset2(knot_zone_contents_t *contents,
- knot_changes_t *changes,
- knot_changeset_t *chset)
+static int xfrin_apply_changeset(knot_zone_contents_t *contents,
+ knot_changes_t *changes,
+ knot_changeset_t *chset)
{
/*
* Applies one changeset to the zone. Checks if the changeset may be
@@ -2836,19 +2859,17 @@ static int xfrin_apply_changeset2(knot_zone_contents_t *contents,
return KNOT_ERROR;
}
- int ret = xfrin_apply_remove2(contents, chset, changes);
+ int ret = xfrin_apply_remove(contents, chset, changes);
if (ret != KNOT_EOK) {
-// xfrin_clean_changes_after_fail2(changes);
return ret;
}
- ret = xfrin_apply_add2(contents, chset, changes);
+ ret = xfrin_apply_add(contents, chset, changes);
if (ret != KNOT_EOK) {
-// xfrin_clean_changes_after_fail(changes);
return ret;
}
- return xfrin_apply_replace_soa2(contents, changes, chset);
+ return xfrin_apply_replace_soa(contents, changes, chset);
}
/*----------------------------------------------------------------------------*/
@@ -2871,6 +2892,8 @@ static void xfrin_mark_empty(knot_node_t *node, void *data)
}
changes->old_nodes[changes->old_nodes_count++] = node;
+ // mark the node as empty
+ knot_node_set_empty(node);
if (node->parent != NULL) {
assert(node->parent->children > 0);
@@ -2903,6 +2926,8 @@ static void xfrin_mark_empty_nsec3(knot_node_t *node, void *data)
}
changes->old_nsec3[changes->old_nsec3_count++] = node;
+ // mark the node as empty
+ knot_node_set_empty(node);
if (node->parent != NULL) {
assert(node->parent->children > 0);
@@ -2950,11 +2975,13 @@ static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
zone_node = NULL;
hash_item = NULL;
+dbg_xfrin_exec_detail(
char *name = knot_dname_to_str(knot_node_owner(
changes->old_nodes[i]));
dbg_xfrin_detail("Old node #%d: %p, %s\n", i,
changes->old_nodes[i], name);
free(name);
+);
ret = knot_zone_contents_remove_node(
contents, changes->old_nodes[i], &zone_node,
@@ -2967,9 +2994,7 @@ static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
free(hash_item);
free(zone_node);
- knot_node_free(&changes->old_nodes[i], 0);
}
- changes->old_nodes_count = 0;
// remove NSEC3 nodes
for (int i = 0; i < changes->old_nsec3_count; ++i) {
@@ -2990,9 +3015,7 @@ static int xfrin_remove_empty_nodes(knot_zone_contents_t *contents,
}
free(zone_node);
- knot_node_free(&changes->old_nsec3[i], 0);
}
- changes->old_nsec3_count = 0;
return KNOT_EOK;
}
@@ -3060,9 +3083,6 @@ int xfrin_apply_changesets(knot_zone_t *zone,
dbg_xfrin("Applying changesets to zone...\n");
-// dbg_xfrin("\nOLD ZONE CONTENTS:\n\n");
-// knot_zone_contents_dump(old_contents, 1);
-
/*
* Ensure that the zone generation is set to 0.
*/
@@ -3130,7 +3150,7 @@ int xfrin_apply_changesets(knot_zone_t *zone,
dbg_xfrin_verb("Old contents apex: %p, new apex: %p\n",
old_contents->apex, contents_copy->apex);
for (int i = 0; i < chsets->count; ++i) {
- if ((ret = xfrin_apply_changeset2(contents_copy, changes,
+ if ((ret = xfrin_apply_changeset(contents_copy, changes,
&chsets->sets[i]))
!= KNOT_EOK) {
xfrin_rollback_update(old_contents,
@@ -3155,7 +3175,8 @@ int xfrin_apply_changesets(knot_zone_t *zone,
*/
/*
- * Select and delete empty nodes.
+ * Select and remove empty nodes from zone trees. Do not free them right
+ * away as they may be referenced by some domain names.
*/
ret = xfrin_remove_empty_nodes(contents_copy, changes);
if (ret != KNOT_EOK) {
@@ -3165,11 +3186,9 @@ int xfrin_apply_changesets(knot_zone_t *zone,
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 = xfrin_adjust_contents(contents_copy, &changes);
ret = knot_zone_contents_adjust(contents_copy);
if (ret != KNOT_EOK) {
dbg_xfrin("Failed to finalize zone contents: %s\n",
@@ -3187,7 +3206,6 @@ int xfrin_apply_changesets(knot_zone_t *zone,
return ret;
}
- //xfrin_cleanup_update(&changes);
chsets->changes = changes;
*new_contents = contents_copy;
@@ -3215,6 +3233,20 @@ int xfrin_switch_zone(knot_zone_t *zone,
dbg_xfrin_verb("Old contents: %p, apex: %p, new apex: %p\n",
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) {
+ // 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);
+ assert(ret == KNOT_EOK);
+ }
+
+ // set generation to old, so that the flags may be used in next transfer
+ // and we do not search for new nodes anymore
+ knot_zone_contents_set_gen_old(new_contents);
+
// wait for readers to finish
dbg_xfrin_verb("Waiting for readers to finish...\n");
synchronize_rcu();
diff --git a/src/libknot/updates/xfr-in.h b/src/libknot/updates/xfr-in.h
index b009152..a762b81 100644..100755
--- a/src/libknot/updates/xfr-in.h
+++ b/src/libknot/updates/xfr-in.h
@@ -5,7 +5,7 @@
*
* \brief XFR client API.
*
- * \addtogroup query_processing
+ * \addtogroup xfr
* @{
*/
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
@@ -189,9 +189,6 @@ int xfrin_switch_zone(knot_zone_t *zone,
knot_zone_contents_t *new_contents,
int deep_free);
-//void xfrin_cleanup_failed_update(knot_zone_contents_t *old_contents,
-// knot_zone_contents_t **new_contents);
-
void xfrin_cleanup_successful_update(knot_changes_t **changes);
void xfrin_rollback_update(knot_zone_contents_t *old_contents,
diff --git a/src/libknot/util/conv.c b/src/libknot/util/conv.c
deleted file mode 100644
index 6626ddd..0000000
--- a/src/libknot/util/conv.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * 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 <stdlib.h>
-#include <stdint.h>
-#include <ctype.h>
-#include "conv.h"
-
-#define B64BUFSIZE 65535 /*!< Buffer size for b64 conversion. */
-
-
-static const char Base64[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-static const char Pad64 = '=';
-
-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...
- **/
-static 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;
-}
-
-static 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);
-}
-
-
-static 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);
- }
-}
-
-#define B64BUFSIZE 65535 /*!< Buffer size for b64 conversion. */
diff --git a/src/libknot/util/conv.h b/src/libknot/util/conv.h
deleted file mode 100644
index d1e6dae..0000000
--- a/src/libknot/util/conv.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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_CONV_H_
-#define _KNOT_CONV_H_
-
-#define B64BUFSIZE 65535 /*!< Buffer size for b64 conversion. */
-
-/*!
- * \brief Base64 presentation to wire conversion.
- */
-int b64_pton(char const *src, uint8_t *target, size_t targsize);
-
-#endif // _KNOT_CONV_H_
diff --git a/src/libknot/util/debug.c b/src/libknot/util/debug.c
index f14c3cd..a6555ad 100644..100755
--- a/src/libknot/util/debug.c
+++ b/src/libknot/util/debug.c
@@ -105,7 +105,6 @@ void knot_rrset_dump(const knot_rrset_t *rrset, char loaded_zone)
return;
}
- fprintf(stderr, " rdata count: %d\n", rrset->rdata->count);
knot_rdata_t *tmp = rrset->rdata;
while (tmp->next != rrset->rdata && tmp->next != NULL) {
@@ -133,11 +132,6 @@ void knot_node_dump(knot_node_t *node, void *loaded_zone)
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);
- if (loaded_zone && node->prev != NULL) {
- name = knot_dname_to_str(node->prev->owner);
- fprintf(stderr, "previous node: %s\n", name);
- free(name);
- }
if (knot_node_is_deleg_point(node)) {
fprintf(stderr, "delegation point\n");
@@ -197,6 +191,8 @@ void knot_node_dump(knot_node_t *node, void *loaded_zone)
} else {
fprintf(stderr, "none\n");
}
+
+ fprintf(stderr, "Zone: %p\n", node->zone);
fprintf(stderr, "RRSet count: %d\n", node->rrset_count);
diff --git a/src/libknot/util/debug.h b/src/libknot/util/debug.h
index b6aba6e..731fed8 100644..100755
--- a/src/libknot/util/debug.h
+++ b/src/libknot/util/debug.h
@@ -42,6 +42,7 @@
#define KNOT_ZONE_DEBUG
#define KNOT_ZONEDB_DEBUG
#define KNOT_NODE_DEBUG
+ #define KNOT_ZONEDIFF_DEBUG
#endif
#ifdef KNOT_NS_DEBUG
@@ -368,6 +369,48 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
#define dbg_zonedb_exec_detail(cmds)
#endif
+#ifdef KNOT_ZONEDIFF_DEBUG
+
+/* Brief messages. */
+#ifdef DEBUG_ENABLE_BRIEF
+#define dbg_zonediff(msg...) fprintf(stderr, msg)
+#define dbg_zonediff_hex(data, len) hex_print((data), (len))
+#else
+#define dbg_zonediff(msg...)
+#define dbg_zonediff_hex(data, len)
+#endif
+
+/* Verbose messages. */
+#ifdef DEBUG_ENABLE_VERBOSE
+#define dbg_zonediff_verb(msg...) fprintf(stderr, msg)
+#define dbg_zonediff_hex_verb(data, len) hex_print((data), (len))
+#else
+#define dbg_zonediff_verb(msg...)
+#define dbg_zonediff_hex_verb(data, len)
+#endif
+
+/* Detail messages. */
+#ifdef DEBUG_ENABLE_DETAILS
+#define dbg_zonediff_detail(msg...) fprintf(stderr, msg)
+#define dbg_zonediff_hex_detail(data, len) hex_print((data), (len))
+#define dbg_zonediff_exec_detail(cmds) do { cmds } while (0)
+#else
+#define dbg_zonediff_detail(msg...)
+#define dbg_zonediff_hex_detail(data, len)
+#define dbg_zonediff_exec_detail(cmds)
+#endif
+
+/* No messages. */
+#else
+#define dbg_zonediff(msg...)
+#define dbg_zonediff_hex(data, len)
+#define dbg_zonediff_verb(msg...)
+#define dbg_zonediff_hex_verb(data, len)
+#define dbg_zonediff_detail(msg...)
+#define dbg_zonediff_hex_detail(data, len)
+#define dbg_zonediff_exec_detail(cmds)
+#endif
+
/******************************************************************************/
#ifdef KNOT_RESPONSE_DEBUG
@@ -607,7 +650,6 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
/* Brief messages. */
#ifdef DEBUG_ENABLE_BRIEF
#define dbg_ck_hash(msg...) log_msg(LOG_SERVER, LOG_DEBUG, msg)
-#define dbg_ck_rehash(msg...) log_msg(LOG_SERVER, LOG_DEBUG, msg)
#define dbg_ck_hash_hex(data, len) hex_log(LOG_SERVER, (data), (len))
#else
#define dbg_ck_hash(msg...)
@@ -636,7 +678,6 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
/* No messages. */
#else
#define dbg_ck_hash(msg...)
-#define dbg_ck_rehash(msg...)
#define dbg_ck_hash_hex(data, len)
#define dbg_ck_hash_verb(msg...)
#define dbg_ck_hash_hex_verb(data, len)
@@ -646,6 +687,21 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
/******************************************************************************/
+#ifdef KNOT_STASH_DEBUG
+
+#ifdef DEBUG_ENABLE_BRIEF
+#define dbg_stash(msg...) log_msg(LOG_ZONE, LOG_DEBUG, msg)
+#else
+#define dbg_stash(msg...)
+#endif
+
+#else
+#define dbg_stash(msg...)
+#endif
+
+
+/******************************************************************************/
+
#ifdef KNOT_XFRIN_DEBUG
/* Brief messages. */
@@ -780,37 +836,46 @@ void knot_zone_contents_dump(knot_zone_contents_t *zone, char loaded_zone);
#ifdef DEBUG_ENABLE_BRIEF
#define dbg_rrset(msg...) log_msg(LOG_ZONE, LOG_DEBUG, msg)
#define dbg_rrset_hex(data, len) hex_log(LOG_ZONE, (data), (len))
+#define dbg_rrset_exec(cmds) do { cmds } while (0)
#else
#define dbg_rrset(msg...)
#define dbg_rrset_hex(data, len)
+#define dbg_rrset_exec(cmds)
#endif
/* Verbose messages. */
#ifdef DEBUG_ENABLE_VERBOSE
#define dbg_rrset_verb(msg...) log_msg(LOG_ZONE, LOG_DEBUG, msg)
#define dbg_rrset_hex_verb(data, len) hex_log(LOG_ZONE, (data), (len))
+#define dbg_rrset_exec_verb(cmds) do { cmds } while (0)
#else
#define dbg_rrset_verb(msg...)
#define dbg_rrset_hex_verb(data, len)
+#define dbg_rrset_exec_verb(cmds)
#endif
/* Detail messages. */
#ifdef DEBUG_ENABLE_DETAILS
#define dbg_rrset_detail(msg...) log_msg(LOG_ZONE, LOG_DEBUG, msg)
#define dbg_rrset_hex_detail(data, len) hex_log(LOG_ZONE, (data), (len))
+#define dbg_rrset_exec_detail(cmds) do { cmds } while (0)
#else
#define dbg_rrset_detail(msg...)
#define dbg_rrset_hex_detail(data, len)
+#define dbg_rrset_exec_detail(cmds)
#endif
/* No messages. */
#else
#define dbg_rrset(msg...)
#define dbg_rrset_hex(data, len)
+#define dbg_rrset_exec(cmds)
#define dbg_rrset_verb(msg...)
#define dbg_rrset_hex_verb(data, len)
+#define dbg_rrset_exec_verb(cmds)
#define dbg_rrset_detail(msg...)
#define dbg_rrset_hex_detail(data, len)
+#define dbg_rrset_exec_detail(cmds)
#endif
/******************************************************************************/
diff --git a/src/libknot/util/descriptor.c b/src/libknot/util/descriptor.c
index 63e1747..35ae77e 100644..100755
--- a/src/libknot/util/descriptor.c
+++ b/src/libknot/util/descriptor.c
@@ -569,3 +569,5 @@ int knot_rrtype_is_metatype(uint16_t type)
|| type == KNOT_RRTYPE_OPT);
}
+/*! @} */
+
diff --git a/src/libknot/util/descriptor.h b/src/libknot/util/descriptor.h
index b7e4a53..b7e4a53 100644..100755
--- a/src/libknot/util/descriptor.h
+++ b/src/libknot/util/descriptor.h
diff --git a/src/libknot/util/error.h b/src/libknot/util/error.h
index 888669a..96eff68 100644..100755
--- a/src/libknot/util/error.h
+++ b/src/libknot/util/error.h
@@ -52,6 +52,7 @@ enum knot_error {
KNOT_EACCES, /*!< Permission is denied. */
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, /*!< Domain name does not belong to the zone. */
KNOT_EHASH, /*!< Error in hash table. */
KNOT_EZONEIN, /*!< Error inserting zone. */
@@ -65,10 +66,12 @@ 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_ECONN, /*!< Connection reset. */
KNOT_EIXFRSPACE, /*!< IXFR reply did not fit in. */
KNOT_ECNAME, /*!< CNAME loop found in zone. */
- KNOT_ERROR_COUNT = 34
+ KNOT_ENODIFF, /*!< No zone diff can be created. */
+ KNOT_ERROR_COUNT = 37
};
/*! \brief Table linking error messages to error codes. */
diff --git a/src/libknot/util/libknot_error.c b/src/libknot/util/libknot_error.c
index f787565..dd4280d 100644..100755
--- a/src/libknot/util/libknot_error.c
+++ b/src/libknot/util/libknot_error.c
@@ -24,7 +24,7 @@ const error_table_t knot_error_msgs[KNOT_ERROR_COUNT] = {
{KNOT_ENOTSUP, "Operation not supported."},
{KNOT_EAGAIN, "OS lacked necessary resources."},
{KNOT_ERANGE, "Value is out of range."},
- {KNOT_EBADARG, "Wrong argument supported."},
+ {KNOT_EBADARG, "Wrong argument supplied."},
{KNOT_EFEWDATA, "Not enough data to parse."},
{KNOT_ESPACE, "Not enough space provided."},
{KNOT_EMALF, "Malformed data."},
@@ -32,6 +32,7 @@ const error_table_t knot_error_msgs[KNOT_ERROR_COUNT] = {
{KNOT_EACCES, "Permission to perform requested operation is denied."},
{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, "Domain name does not belong to the given zone."},
{KNOT_EHASH, "Error in hash table."},
{KNOT_EZONEIN, "Error inserting zone."},
@@ -45,11 +46,13 @@ const error_table_t knot_error_msgs[KNOT_ERROR_COUNT] = {
{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_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_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_ERROR, 0}
};
diff --git a/src/libknot/util/tolower.c b/src/libknot/util/tolower.c
index d71c467..d71c467 100644..100755
--- a/src/libknot/util/tolower.c
+++ b/src/libknot/util/tolower.c
diff --git a/src/libknot/util/tolower.h b/src/libknot/util/tolower.h
index 6b9e98c..2e92258 100644..100755
--- a/src/libknot/util/tolower.h
+++ b/src/libknot/util/tolower.h
@@ -55,3 +55,5 @@ static inline uint8_t knot_tolower(uint8_t c) {
}
#endif /* _KNOT_TOLOWER_H_ */
+
+/*! @} */
diff --git a/src/libknot/util/utils.c b/src/libknot/util/utils.c
index 04e12c5..04e12c5 100644..100755
--- a/src/libknot/util/utils.c
+++ b/src/libknot/util/utils.c
diff --git a/src/libknot/util/utils.h b/src/libknot/util/utils.h
index fd275b3..fd275b3 100644..100755
--- a/src/libknot/util/utils.h
+++ b/src/libknot/util/utils.h
diff --git a/src/libknot/util/wire.h b/src/libknot/util/wire.h
index 0a24ff1..0a24ff1 100644..100755
--- a/src/libknot/util/wire.h
+++ b/src/libknot/util/wire.h
diff --git a/src/libknot/zone/dname-table.c b/src/libknot/zone/dname-table.c
index d2d97c2..d2d97c2 100644..100755
--- a/src/libknot/zone/dname-table.c
+++ b/src/libknot/zone/dname-table.c
diff --git a/src/libknot/zone/dname-table.h b/src/libknot/zone/dname-table.h
index 945b6de..945b6de 100644..100755
--- a/src/libknot/zone/dname-table.h
+++ b/src/libknot/zone/dname-table.h
diff --git a/src/libknot/zone/node.c b/src/libknot/zone/node.c
index 4ad2a27..c196f29 100644..100755
--- a/src/libknot/zone/node.c
+++ b/src/libknot/zone/node.c
@@ -81,67 +81,29 @@ static inline void knot_node_flags_set_nonauth(uint8_t *flags)
*flags |= KNOT_NODE_FLAGS_NONAUTH;
}
-///*----------------------------------------------------------------------------*/
-///*!
-// * \brief Returns the old node flag
-// *
-// * \param flags Flags to retrieve the flag from.
-// *
-// * \return A byte with only the old node flag set if it was set in \a flags.
-// */
-//static inline uint8_t knot_node_flags_get_old(uint8_t flags)
-//{
-// return flags & KNOT_NODE_FLAGS_OLD;
-//}
-
-///*----------------------------------------------------------------------------*/
-///*!
-// * \brief Sets the old node flag.
-// *
-// * \param flags Flags to set the flag in.
-// */
-//static inline void knot_node_flags_set_new(uint8_t *flags)
-//{
-// *flags |= KNOT_NODE_FLAGS_NEW;
-//}
-
-///*----------------------------------------------------------------------------*/
-///*!
-// * \brief Returns the new node flag
-// *
-// * \param flags Flags to retrieve the flag from.
-// *
-// * \return A byte with only the new node flag set if it was set in \a flags.
-// */
-//static inline uint8_t knot_node_flags_get_new(uint8_t flags)
-//{
-// return flags & KNOT_NODE_FLAGS_NEW;
-//}
-
-///*----------------------------------------------------------------------------*/
-///*!
-// * \brief Sets the new node flag.
-// *
-// * \param flags Flags to set the flag in.
-// */
-//static inline void knot_node_flags_set_old(uint8_t *flags)
-//{
-// *flags |= KNOT_NODE_FLAGS_OLD;
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//static inline void knot_node_flags_clear_new(uint8_t *flags)
-//{
-// *flags &= ~KNOT_NODE_FLAGS_NEW;
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//static inline void knot_node_flags_clear_old(uint8_t *flags)
-//{
-// *flags &= ~KNOT_NODE_FLAGS_OLD;
-//}
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief Sets the empty node flag.
+ *
+ * \param flags Flags to set the flag in.
+ */
+static inline void knot_node_flags_set_empty(uint8_t *flags)
+{
+ *flags |= KNOT_NODE_FLAGS_EMPTY;
+}
+
+/*----------------------------------------------------------------------------*/
+/*!
+ * \brief Returns the empty node flag
+ *
+ * \param flags Flags to retrieve the flag from.
+ *
+ * \return A byte with only the empty node flag set if it was set in \a flags.
+ */
+static inline uint8_t knot_node_flags_get_empty(uint8_t flags)
+{
+ return flags & KNOT_NODE_FLAGS_EMPTY;
+}
/*----------------------------------------------------------------------------*/
/*!
@@ -166,26 +128,6 @@ static int compare_rrset_types(void *rr1, void *rr2)
}
/*----------------------------------------------------------------------------*/
-
-//static int knot_node_zone_gen_is_new(const knot_node_t *node)
-//{
-// assert(node->zone != NULL);
-// knot_zone_contents_t *cont = rcu_dereference(node->zone->contents);
-// assert(cont != NULL);
-// return knot_zone_contents_gen_is_new(cont);
-//}
-
-///*----------------------------------------------------------------------------*/
-
-//static int knot_node_zone_gen_is_old(const knot_node_t *node)
-//{
-// assert(node->zone != NULL);
-// knot_zone_contents_t *cont = rcu_dereference(node->zone->contents);
-// assert(cont != NULL);
-// return knot_zone_contents_gen_is_old(cont);
-//}
-
-/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -211,9 +153,12 @@ knot_node_t *knot_node_new(knot_dname_t *owner, knot_node_t *parent,
}
/*----------------------------------------------------------------------------*/
-
+/*! \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 merge)
{
if (node == NULL) {
return KNOT_EBADARG;
@@ -235,6 +180,24 @@ int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
}
}
+int knot_node_add_rrset_no_dupl(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 (ret >= 0) {
+ node->rrset_count += (ret > 0 ? 0 : 1);
+ return ret;
+ } else {
+ return KNOT_ERROR;
+ }
+}
+
/*----------------------------------------------------------------------------*/
const knot_rrset_t *knot_node_rrset(const knot_node_t *node,
@@ -315,6 +278,8 @@ struct knot_node_save_rrset_arg {
size_t max_count;
};
+/*----------------------------------------------------------------------------*/
+
static void save_rrset_to_array(void *node, void *data)
{
struct knot_node_save_rrset_arg *args =
@@ -329,6 +294,8 @@ static void save_rrset_to_array(void *node, void *data)
args->array[args->count++] = rrset;
}
+/*----------------------------------------------------------------------------*/
+
knot_rrset_t **knot_node_get_rrsets(const knot_node_t *node)
{
if (node == NULL || node->rrset_count == 0) {
@@ -463,17 +430,6 @@ knot_node_t *knot_node_get_previous(const knot_node_t *node)
/*----------------------------------------------------------------------------*/
-const knot_node_t *knot_node_next(const knot_node_t *node)
-{
- if (node == NULL) {
- return NULL;
- }
-
- return node->next;
-}
-
-/*----------------------------------------------------------------------------*/
-
void knot_node_set_previous(knot_node_t *node, knot_node_t *prev)
{
if (node == NULL) {
@@ -620,7 +576,7 @@ void knot_node_set_new_node(knot_node_t *node,
/*----------------------------------------------------------------------------*/
-void knot_node_set_zone(knot_node_t *node, knot_zone_t *zone)
+void knot_node_set_zone(knot_node_t *node, const knot_zone_t *zone)
{
if (node == NULL) {
return;
@@ -631,6 +587,17 @@ void knot_node_set_zone(knot_node_t *node, knot_zone_t *zone)
/*----------------------------------------------------------------------------*/
+const knot_zone_t *knot_node_zone(const knot_node_t *node)
+{
+ if (node == NULL) {
+ return NULL;
+ }
+
+ return node->zone;
+}
+
+/*----------------------------------------------------------------------------*/
+
void knot_node_update_ref(knot_node_t **ref)
{
if (*ref != NULL && (*ref)->new_node != NULL) {
@@ -644,8 +611,6 @@ void knot_node_update_refs(knot_node_t *node)
{
// reference to previous node
knot_node_update_ref(&node->prev);
- // reference to next node
- knot_node_update_ref(&node->next);
// reference to parent
knot_node_update_ref(&node->parent);
// reference to wildcard child
@@ -713,6 +678,20 @@ int knot_node_is_auth(const knot_node_t *node)
/*----------------------------------------------------------------------------*/
+int knot_node_is_empty(const knot_node_t *node)
+{
+ return knot_node_flags_get_empty(node->flags);
+}
+
+/*----------------------------------------------------------------------------*/
+
+void knot_node_set_empty(knot_node_t *node)
+{
+ knot_node_flags_set_empty(&node->flags);
+}
+
+/*----------------------------------------------------------------------------*/
+
static void knot_node_free_rrsets_from_tree(void *item, void *data)
{
if (item == NULL) {
@@ -727,14 +706,6 @@ static void knot_node_free_rrsets_from_tree(void *item, void *data)
void knot_node_free_rrsets(knot_node_t *node, int free_rdata_dnames)
{
- /* CLEANUP */
-// knot_rrset_t **rrsets = knot_node_get_rrsets(node);
-// for (int i = 0; i < node->rrset_count; i++) {
-// knot_rrset_deep_free(&(rrsets[i]), 0, 1, free_rdata_dnames);
-// }
-
-// free(rrsets);
-
if (node == NULL) {
return;
}
@@ -748,16 +719,16 @@ void knot_node_free_rrsets(knot_node_t *node, int free_rdata_dnames)
/*----------------------------------------------------------------------------*/
-void knot_node_free(knot_node_t **node, int fix_refs)
+void knot_node_free(knot_node_t **node)
{
if (node == NULL || *node == NULL) {
return;
}
- dbg_node("Freeing node: %p\n", *node);
+ dbg_node_detail("Freeing node: %p\n", *node);
if ((*node)->rrset_tree != NULL) {
- dbg_node("Freeing RRSets.\n");
+ dbg_node_detail("Freeing RRSets.\n");
gen_tree_destroy(&(*node)->rrset_tree, NULL, NULL);
}
@@ -768,53 +739,13 @@ void knot_node_free(knot_node_t **node, int fix_refs)
knot_dname_set_node((*node)->owner, NULL);
}
- dbg_node("Releasing owner.\n");
+ dbg_node_detail("Releasing owner.\n");
knot_dname_release((*node)->owner);
- // check nodes referencing this node and fix the references
-
- if (fix_refs) {
- // previous node
- dbg_node("Checking previous.\n");
- if ((*node)->prev && (*node)->prev->next == (*node)) {
- (*node)->prev->next = (*node)->next;
- }
-
- dbg_node("Checking next.\n");
- if ((*node)->next && (*node)->next->prev == (*node)) {
- (*node)->next->prev = (*node)->prev;
- }
-
- // NSEC3 node
- dbg_node("Checking NSEC3.\n");
- if ((*node)->nsec3_node
- && (*node)->nsec3_node->nsec3_referer == (*node)) {
- (*node)->nsec3_node->nsec3_referer = NULL;
- }
-
- dbg_node("Checking NSEC3 ref.\n");
- if ((*node)->nsec3_referer
- && (*node)->nsec3_referer->nsec3_node == (*node)) {
- (*node)->nsec3_referer->nsec3_node = NULL;
- }
-
- // wildcard child node
- dbg_node("Checking parent's wildcard child.\n");
- if ((*node)->parent
- && (*node)->parent->wildcard_child == (*node)) {
- (*node)->parent->wildcard_child = NULL;
- }
-
- // fix parent's children count
- if ((*node)->parent) {
- --(*node)->parent->children;
- }
- }
-
free(*node);
*node = NULL;
- dbg_node("Done.\n");
+ dbg_node_detail("Done.\n");
}
/*----------------------------------------------------------------------------*/
diff --git a/src/libknot/zone/node.h b/src/libknot/zone/node.h
index 11cd0ce..1ab814a 100644..100755
--- a/src/libknot/zone/node.h
+++ b/src/libknot/zone/node.h
@@ -62,8 +62,6 @@ struct knot_node {
*/
struct knot_node *prev;
- struct knot_node *next;
-
/*!
* \brief NSEC3 node corresponding to this node.
*
@@ -74,7 +72,7 @@ struct knot_node {
struct knot_node *nsec3_referer;
- struct knot_zone *zone;
+ const struct knot_zone *zone;
struct knot_node *new_node;
@@ -83,22 +81,12 @@ struct knot_node {
unsigned short rrset_count; /*!< Number of RRSets stored in the node. */
/*!
- * \brief Generation of node to be used.
- *
- * If set to 0, the old node will be used. Otherwise new nodes will
- * be used. This applies when getting some referenced node.
-
- */
-// short **generation;
-
- /*!
* \brief Various flags.
*
* Currently only two:
* 0x01 - node is a delegation point
* 0x02 - node is non-authoritative (under a delegation point)
- * 0x80 - node is old and will be removed (during update)
- * 0x40 - node is new, should not be used while zone is old
+ * 0x10 - node is empty and will be deleted after update
*/
uint8_t flags;
};
@@ -113,9 +101,11 @@ typedef enum {
/*! \brief Node is not authoritative (i.e. below a zone cut). */
KNOT_NODE_FLAGS_NONAUTH = (uint8_t)0x02,
/*! \brief Node is old and will be removed (during update). */
- KNOT_NODE_FLAGS_OLD = (uint8_t)0x80,
+ KNOT_NODE_FLAGS_OLD = (uint8_t)0x04,
/*! \brief Node is new and should not be used while zoen is old. */
- KNOT_NODE_FLAGS_NEW = (uint8_t)0x40
+ KNOT_NODE_FLAGS_NEW = (uint8_t)0x08,
+ /*! \brief Node is empty and will be deleted after update. */
+ KNOT_NODE_FLAGS_EMPTY = (uint8_t)0x10
} knot_node_flags_t;
/*----------------------------------------------------------------------------*/
@@ -147,6 +137,8 @@ knot_node_t *knot_node_new(knot_dname_t *owner, knot_node_t *parent,
int knot_node_add_rrset(knot_node_t *node, knot_rrset_t *rrset,
int merge);
+int knot_node_add_rrset_no_dupl(knot_node_t *node, knot_rrset_t *rrset);
+
/*!
* \brief Returns the RRSet of the given type from the node.
*
@@ -255,8 +247,6 @@ const knot_node_t *knot_node_previous(const knot_node_t *node);
*/
knot_node_t *knot_node_get_previous(const knot_node_t *node);
-const knot_node_t *knot_node_next(const knot_node_t *node);
-
/*!
* \brief Sets the previous node of the given node.
*
@@ -351,7 +341,9 @@ knot_node_t *knot_node_get_new_node(const knot_node_t *node);
void knot_node_set_new_node(knot_node_t *node, knot_node_t *new_node);
-void knot_node_set_zone(knot_node_t *node, struct knot_zone *zone);
+void knot_node_set_zone(knot_node_t *node, const struct knot_zone *zone);
+
+const struct knot_zone *knot_node_zone(const knot_node_t *node);
void knot_node_update_ref(knot_node_t **ref);
@@ -405,6 +397,10 @@ void knot_node_clear_new(knot_node_t *node);
void knot_node_clear_old(knot_node_t *node);
+int knot_node_is_empty(const knot_node_t *node);
+
+void knot_node_set_empty(knot_node_t *node);
+
/*!
* \brief Destroys the RRSets within the node structure.
*
@@ -428,7 +424,7 @@ void knot_node_free_rrsets(knot_node_t *node, int free_rdata_dnames);
*
* \todo Document missing parameters.
*/
-void knot_node_free(knot_node_t **node, int fix_refs);
+void knot_node_free(knot_node_t **node);
/*!
* \brief Compares two nodes according to their owner.
diff --git a/src/libknot/zone/zone-contents.c b/src/libknot/zone/zone-contents.c
index 19268c4..7e453a5 100644..100755
--- a/src/libknot/zone/zone-contents.c
+++ b/src/libknot/zone/zone-contents.c
@@ -20,6 +20,8 @@
#include "util/error.h"
#include "util/debug.h"
#include "common/base32hex.h"
+/*! \todo XXX TODO FIXME remove once testing is done. */
+#include "zcompile/zcompile.h"
#include "consts.h"
/*----------------------------------------------------------------------------*/
@@ -42,7 +44,7 @@ typedef struct {
const uint8_t KNOT_ZONE_FLAGS_GEN_OLD = 0; /* xxxxxx00 */
const uint8_t KNOT_ZONE_FLAGS_GEN_NEW = 1 << 0; /* xxxxxx01 */
-const uint8_t KNOT_ZONE_FLAGS_GEN_FIN = 1 << 2; /* xxxxxx10 */
+const uint8_t KNOT_ZONE_FLAGS_GEN_FIN = 1 << 1; /* xxxxxx10 */
const uint8_t KNOT_ZONE_FLAGS_GEN_MASK = 3; /* 00000011 */
const uint8_t KNOT_ZONE_FLAGS_ANY_MASK = 4; /* 00000100 */
const uint8_t KNOT_ZONE_FLAGS_ANY = 4; /* 00000100 */
@@ -91,8 +93,8 @@ 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);
);
@@ -137,7 +139,7 @@ static void knot_zone_contents_destroy_node_owner_from_tree(
UNUSED(data);
/*!< \todo change completely! */
- knot_node_free(&tnode->node, 0);
+ knot_node_free(&tnode->node);
}
/*----------------------------------------------------------------------------*/
@@ -159,11 +161,8 @@ static int knot_zone_contents_dnames_from_rdata_to_table(
== KNOT_RDATA_WF_UNCOMPRESSED_DNAME
|| d->wireformat[j]
== KNOT_RDATA_WF_LITERAL_DNAME) {
-// printf("Saving dname from rdata to dname table: "
-// "%p.\n", knot_rdata_get_item(rdata, j)->dname);
rc = knot_dname_table_add_dname_check(table,
&knot_rdata_get_item(rdata, j)->dname);
-// printf("Returned: %d\n", rc);
if (rc < 0) {
dbg_zone("Error: %s\n", knot_strerror(rc));
return rc;
@@ -171,7 +170,7 @@ static int knot_zone_contents_dnames_from_rdata_to_table(
}
}
- dbg_zone("RDATA OK.\n");
+ dbg_zone_detail("RDATA OK.\n");
return KNOT_EOK;
}
@@ -187,7 +186,7 @@ static int knot_zone_contents_dnames_from_rrset_to_table(
// discard the old owner and replace it with the new
knot_rrset_set_owner(rrset, owner);
}
- dbg_zone("RRSet owner: %p\n", 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));
@@ -197,10 +196,6 @@ static int knot_zone_contents_dnames_from_rrset_to_table(
return KNOT_EOK;
}
// for each RDATA in RRSet
-// char *name = knot_dname_to_str(rrset->owner);
-// char *type = knot_rrtype_to_string(rrset->type);
-// printf("Storing dnames from RDATA from RRSet %s, %s\n", name, type);
-// free(name);
knot_rdata_t *rdata = knot_rrset_get_rdata(rrset);
while (rdata != NULL) {
int rc = knot_zone_contents_dnames_from_rdata_to_table(table,
@@ -227,10 +222,10 @@ static int knot_zone_contents_dnames_from_node_to_table(
// insert owner
char *name = knot_dname_to_str(node->owner);
- dbg_zone("Node owner before inserting to dname table: %p.\n",
- node->owner);
- dbg_zone("Node owner before inserting to dname table: %s.\n",
- name);
+ 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);
@@ -239,17 +234,18 @@ static int knot_zone_contents_dnames_from_node_to_table(
return rc;
}
int replace_owner = (rc > 0);
- dbg_zone("Node owner after inserting to dname table: %p.\n",
- node->owner);
+
+dbg_zone_exec_detail(
name = knot_dname_to_str(node->owner);
- dbg_zone("Node owner after inserting to dname table: %s.\n",
- name);
+ 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("Inserting RRSets from node to table.\n");
+ 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) {
@@ -264,27 +260,46 @@ static int knot_zone_contents_dnames_from_node_to_table(
}
/*----------------------------------------------------------------------------*/
-/*!
- * \brief Finds and sets wildcard child for given node's owner.
- *
- * \param zone Current zone.
- * \param node Node to be used.
- */
-//static void find_and_set_wildcard_child(knot_zone_contents_t *zone,
-// knot_node_t *node)
-//{
-// knot_dname_t *chopped = knot_dname_left_chop(node->owner);
-// assert(chopped);
-// knot_node_t *wildcard_parent;
-// wildcard_parent =
-// knot_zone_contents_get_node(zone, chopped);
-// knot_dname_free(&chopped);
+static const knot_node_t *knot_zone_contents_find_wildcard_child(
+ knot_zone_contents_t *zone, const knot_node_t *closest_encloser)
+{
+ assert(zone != NULL);
+ assert(closest_encloser != NULL);
+
+ knot_dname_t *tmp = knot_dname_new_from_str("*", 1, NULL);
+ CHECK_ALLOC(tmp, NULL);
-// assert(wildcard_parent); /* it *has* to be there */
+ knot_dname_t *wildcard = knot_dname_cat(tmp, knot_node_owner(
+ closest_encloser));
+ if (wildcard == NULL) {
+ free(tmp);
+ return NULL;
+ }
-// knot_node_set_wildcard_child(wildcard_parent, node);
-//}
+ assert(wildcard == tmp);
+
+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);
+ 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);
+
+ knot_dname_free(&wildcard);
+
+ if (ret != KNOT_ZONE_NAME_FOUND) {
+ return NULL;
+ } else {
+ return found;
+ }
+}
/*----------------------------------------------------------------------------*/
/*!
@@ -303,54 +318,79 @@ static int knot_zone_contents_dnames_from_node_to_table(
* \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)
-//{
-// return;
-// 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;
-// const knot_node_t *n = NULL;
-// const knot_node_t *closest_encloser = NULL;
-// const knot_node_t *prev = NULL;
-
-// if (knot_dname_is_wildcard(dname)) {
-// find_and_set_wildcard_child(zone, node);
-// }
-
-// int ret = knot_zone_contents_find_dname(zone, dname, &n,
-// &closest_encloser, &prev);
-
-// // n = knot_zone_find_node(zone, dname);
-
-// if (ret == KNOT_EBADARG || ret == KNOT_EBADZONE) {
-// // TODO: do some cleanup if needed
-// return;
-// }
-
-// assert(ret != KNOT_ZONE_NAME_FOUND
-// || n == closest_encloser);
-
-// if (ret != KNOT_ZONE_NAME_FOUND
-// && (closest_encloser != NULL)) {
-// dbg_zone("Saving closest encloser to RDATA.\n");
-// // save pointer to the closest encloser
-// knot_rdata_item_t *item =
-// knot_rdata_get_item(rdata, pos);
-// assert(item->dname != NULL);
-// assert(item->dname->node == NULL);
-// //skip_insert(list, (void *)item->dname,
-// // (void *)closest_encloser->owner, NULL);
-// item->dname->node = closest_encloser->owner->node;
-// }
-// }
-//}
+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 node either set or the name "
+ "does not belong to the zone (%p).\n",
+ knot_dname_node(dname));
+ return;
+ }
+
+ const knot_node_t *n = NULL;
+ const knot_node_t *closest_encloser = NULL;
+ const knot_node_t *prev = NULL;
+
+ int ret = knot_zone_contents_find_dname(zone, dname, &n,
+ &closest_encloser, &prev);
+
+ if (ret == KNOT_EBADARG || 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;
+ }
+
+ 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
+ * right away.
+ * Having the closest encloser saved in the dname
+ * would disrupt the query processing algorithms
+ * anyway.
+ */
+
+ dbg_zone_verb("Trying to find wildcard child.\n");
+
+ n = knot_zone_contents_find_wildcard_child(zone,
+ 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));
+ char *name2 = knot_dname_to_str(dname);
+ dbg_zone_detail("Set wildcard node %s "
+ "to RDATA dname %s.\n",
+ name, name2);
+ free(name);
+ free(name2);
+ );
+ }
+ }
+ }
+}
/*----------------------------------------------------------------------------*/
/*!
@@ -364,65 +404,64 @@ static int knot_zone_contents_dnames_from_node_to_table(
* \param rrset RRSet to adjust RDATA in.
* \param zone Zone to which the RRSet belongs.
*/
-//static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
-// knot_zone_contents_t *zone,
-// knot_node_t *node)
-//{
-// uint16_t type = knot_rrset_type(rrset);
+static void knot_zone_contents_adjust_rdata_in_rrset(knot_rrset_t *rrset,
+ 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_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;
+ knot_rdata_t *rdata_first = knot_rrset_get_rdata(rrset);
+ knot_rdata_t *rdata = rdata_first;
-// if (rdata == NULL) {
-// return;
-// }
+ if (rdata == NULL) {
+ return;
+ }
-// while (rdata->next != rdata_first) {
-// 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("Adjusting domain name at "
-// "position %d of RDATA of record with owner "
-// "%s and type %s.\n",
-// i, rrset->owner->name,
-// knot_rrtype_to_string(type));
-
-// knot_zone_contents_adjust_rdata_item(rdata,
-// zone,
-// node,
-// i);
-// }
-// }
-// rdata = rdata->next;
-// }
+ while (rdata->next != rdata_first) {
+ 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("Adjusting domain name at "
+ "position %d of RDATA of record with owner "
+ "%s and type %s.\n",
+ i, rrset->owner->name,
+ knot_rrtype_to_string(type));
+
+ knot_zone_contents_adjust_rdata_item(rdata,
+ zone, node,
+ i);
+ }
+ }
+ rdata = rdata->next;
+ }
-// 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("Adjusting domain name at "
-// "position %d of RDATA of record with owner "
-// "%s and type %s.\n",
-// i, rrset->owner->name,
-// knot_rrtype_to_string(type));
-
-// knot_zone_contents_adjust_rdata_item(rdata, zone,
-// node, i);
-// }
-// }
+ 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("Adjusting domain name at "
+ "position %d of RDATA of record with owner "
+ "%s and type %s.\n",
+ i, rrset->owner->name,
+ knot_rrtype_to_string(type));
+
+ knot_zone_contents_adjust_rdata_item(rdata, zone, node,
+ i);
+ }
+ }
-//}
+}
/*----------------------------------------------------------------------------*/
/*!
@@ -435,32 +474,29 @@ static int knot_zone_contents_dnames_from_node_to_table(
* \param node Zone node to adjust the RRSets in.
* \param zone Zone to which the node belongs.
*/
-//static void knot_zone_contents_adjust_rrsets(knot_node_t *node,
-// knot_zone_contents_t *zone)
-//{
-// //return;
-// knot_rrset_t **rrsets = knot_node_get_rrsets(node);
-// short count = knot_node_rrset_count(node);
-
-// assert(count == 0 || rrsets != NULL);
-
-// for (int r = 0; r < count; ++r) {
-// assert(rrsets[r] != NULL);
-// dbg_zone("Adjusting next RRSet.\n");
-// knot_zone_contents_adjust_rdata_in_rrset(rrsets[r], zone,
-// node);
-// knot_rrset_t *rrsigs = rrsets[r]->rrsigs;
-// if (rrsigs != NULL) {
-// dbg_zone("Adjusting next RRSIGs.\n");
-// knot_zone_contents_adjust_rdata_in_rrset(rrsigs,
-// zone,
-// node);
-// }
-// }
-
-// free(rrsets);
-//}
+static void knot_zone_contents_adjust_rrsets(knot_node_t *node,
+ knot_zone_contents_t *zone)
+{
+ knot_rrset_t **rrsets = knot_node_get_rrsets(node);
+ short count = knot_node_rrset_count(node);
+
+ assert(count == 0 || rrsets != NULL);
+
+ for (int r = 0; r < count; ++r) {
+ assert(rrsets[r] != NULL);
+ dbg_zone("Adjusting next RRSet.\n");
+ knot_zone_contents_adjust_rdata_in_rrset(rrsets[r], zone,
+ node);
+ knot_rrset_t *rrsigs = rrsets[r]->rrsigs;
+ if (rrsigs != NULL) {
+ dbg_zone("Adjusting next RRSIGs.\n");
+ knot_zone_contents_adjust_rdata_in_rrset(rrsigs, zone,
+ node);
+ }
+ }
+ free(rrsets);
+}
/*----------------------------------------------------------------------------*/
/*!
* \brief Adjusts zone node for faster query processing.
@@ -481,35 +517,24 @@ static int knot_zone_contents_dnames_from_node_to_table(
static void knot_zone_contents_adjust_node(knot_node_t *node,
knot_zone_contents_t *zone)
{
-
-dbg_zone_exec(
- char *name = knot_dname_to_str(node->owner);
- dbg_zone("----- Adjusting node %s -----\n", name);
- free(name);
-);
-
// adjust domain names in RDATA
- /*!
- * \note This is unnecessary, as the code in adjust_rdata_item() is not
- * reachable anyway. However, it's not clear why we disabled the
- * code, so this would need further investigation.
- */
- //knot_zone_contents_adjust_rrsets(node, zone);
+ /*! \note Enabled again after a LONG time. Should test thoroughly. */
+ knot_zone_contents_adjust_rrsets(node, zone);
-dbg_zone_exec(
+dbg_zone_exec_detail(
if (knot_node_parent(node)) {
char *name = knot_dname_to_str(knot_node_owner(
knot_node_parent(node)));
- dbg_zone("Parent: %s\n", name);
- dbg_zone("Parent is delegation point: %s\n",
+ dbg_zone_detail("Parent: %s\n", name);
+ dbg_zone_detail("Parent is delegation point: %s\n",
knot_node_is_deleg_point(knot_node_parent(node))
? "yes" : "no");
- dbg_zone("Parent is non-authoritative: %s\n",
+ dbg_zone_detail("Parent is non-authoritative: %s\n",
knot_node_is_non_auth(knot_node_parent(node))
? "yes" : "no");
free(name);
} else {
- dbg_zone("No parent!\n");
+ dbg_zone_detail("No parent!\n");
}
);
// delegation point / non-authoritative node
@@ -539,17 +564,19 @@ dbg_zone_exec(
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;
}
knot_node_set_nsec3_node(node, (knot_node_t *)nsec3);
- dbg_zone("Set flags to the node: \n");
- dbg_zone("Delegation point: %s\n",
- knot_node_is_deleg_point(node) ? "yes" : "no");
- dbg_zone("Non-authoritative: %s\n",
- knot_node_is_non_auth(node) ? "yes" : "no");
+ dbg_zone_detail("Set flags to the node: \n");
+ dbg_zone_detail("Delegation point: %s\n",
+ knot_node_is_deleg_point(node) ? "yes" : "no");
+ dbg_zone_detail("Non-authoritative: %s\n",
+ knot_node_is_non_auth(node) ? "yes" : "no");
}
/*----------------------------------------------------------------------------*/
@@ -578,19 +605,16 @@ static void knot_zone_contents_adjust_node_in_tree(
return;
}
- /*
- * 1) Set previous node pointer.
- */
- knot_node_set_previous(node, args->previous_node);
+dbg_zone_exec_verb(
+ char *name = knot_dname_to_str(node->owner);
+ dbg_zone_verb("----- Adjusting node %s -----\n", name);
+ free(name);
+);
- if (args->first_node == NULL) {
- args->first_node = node;
- }
knot_zone_contents_t *zone = args->zone;
/*
- * 2) Store domain names to dname table.
- *
+ * 1) Store domain names to dname table.
* TODO: make optional!
*/
assert(zone->dname_table != NULL);
@@ -605,13 +629,35 @@ static void knot_zone_contents_adjust_node_in_tree(
}
/*
- * 3) Do other adjusting (flags, closest enclosers, wildcard children,
+ * 2) Do other adjusting (flags, closest enclosers, wildcard children,
* etc.).
*/
knot_zone_contents_adjust_node(node, zone);
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zone_contents_adjust_node_in_tree_ptr(
+ knot_zone_tree_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;
/*
- * 4) Store previous node depending on the type of this node.
+ * 1) Set previous node pointer.
+ */
+ knot_node_set_previous(node, args->previous_node);
+
+ if (args->first_node == NULL) {
+ args->first_node = node;
+ }
+
+ /*
+ * 2) Store previous node depending on the type of this node.
*/
if (!knot_node_is_non_auth(node)
&& knot_node_rrset_count(node) > 0) {
@@ -639,8 +685,11 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree(
knot_zone_adjust_arg_t *args = (knot_zone_adjust_arg_t *)data;
knot_node_t *node = tnode->node;
- // set previous node
- knot_node_set_previous(node, args->previous_node);
+ if (args->err != KNOT_EOK) {
+ dbg_xfrin_detail("Error during adjusting: %s, skipping node.\n",
+ knot_strerror(args->err));
+ return;
+ }
// assure that owner has proper node
if (knot_dname_node(knot_node_owner(node)) == NULL) {
@@ -661,6 +710,22 @@ static void knot_zone_contents_adjust_nsec3_node_in_tree(
args->err = ret;
return;
}
+}
+
+/*----------------------------------------------------------------------------*/
+
+static void knot_zone_contents_adjust_nsec3_node_in_tree_ptr(
+ knot_zone_tree_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;
+
+ // set previous node
+ knot_node_set_previous(node, args->previous_node);
// here is nothing to consider, all nodes are the same
args->previous_node = node;
@@ -710,9 +775,9 @@ dbg_zone_exec(
uint8_t *hashed_name = NULL;
size_t hash_size = 0;
-dbg_zone_exec(
+dbg_zone_exec_verb(
char *n = knot_dname_to_str(name);
- dbg_zone("Hashing name %s.\n", n);
+ dbg_zone_verb("Hashing name %s.\n", n);
free(n);
);
@@ -737,8 +802,7 @@ dbg_zone_exec(
if (size == 0) {
char *n = knot_dname_to_str(name);
- dbg_zone("Error while encoding hashed name %s to "
- "base32.\n", n);
+ dbg_zone("Error while encoding hashed name %s to base32.\n", n);
free(n);
if (name_b32 != NULL) {
free(name_b32);
@@ -749,7 +813,7 @@ dbg_zone_exec(
assert(name_b32 != NULL);
free(hashed_name);
- dbg_zone("Base32-encoded hash: %s\n", name_b32);
+ dbg_zone_verb("Base32-encoded hash: %s\n", name_b32);
/* Will be returned to caller, make sure it is released after use. */
*nsec3_name = knot_dname_new_from_str(name_b32, size, NULL);
@@ -757,8 +821,7 @@ dbg_zone_exec(
free(name_b32);
if (*nsec3_name == NULL) {
- dbg_zone("Error while creating domain name for hashed"
- " name.\n");
+ dbg_zone("Error while creating domain name for hashed name.\n");
return KNOT_ERROR;
}
@@ -767,7 +830,7 @@ dbg_zone_exec(
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;
}
@@ -805,31 +868,14 @@ static int knot_zone_contents_find_in_tree(knot_zone_tree_t *tree,
assert(previous != NULL);
knot_node_t *found = NULL, *prev = NULL;
-// knot_node_t *found2 = NULL, *prev2 = NULL;
int exact_match = knot_zone_tree_get_less_or_equal(tree, name, &found,
&prev);
-// assert(prev != NULL);
assert(exact_match >= 0);
*node = found;
*previous = prev;
-// 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);
-// assert(found != NULL);
-// *previous = knot_node_get_previous(found, 1);
-// } else {
-// // otherwise check if the previous node is not an empty
-// // non-terminal
-// *previous = (knot_node_rrset_count(prev) == 0)
-// ? knot_node_get_previous(prev, 1)
-// : prev;
-// }
-
return exact_match;
}
@@ -852,7 +898,6 @@ static void knot_zone_contents_node_to_hash(knot_zone_tree_node_t *tnode,
*/
#ifdef USE_HASH_TABLE
- //assert(zone->table != NULL);
// add the node also to the hash table if authoritative, or deleg. point
if (zone->table != NULL
&& ck_insert_item(zone->table,
@@ -977,23 +1022,6 @@ static void knot_zone_contents_check_loops_in_tree(knot_zone_tree_node_t *tnode,
args->zone, next_name,
&next_node, &ce);
-// char *name1 = knot_dname_to_str(next_name);
-// char *name2 = (next_node != NULL)
-// ? knot_dname_to_str(knot_node_owner(next_node))
-// : "none";
-// char *name3 = (ce != NULL)
-// ? knot_dname_to_str(knot_node_owner(ce))
-// : "none";
-// printf("Searched: %s, found: %p (%s), %p (%s); ret: %d"
-// ".\n", name1, next_node, name2, ce, name3, ret);
-// free(name1);
-// if (next_node != NULL) {
-// free(name2);
-// }
-// if (ce != NULL) {
-// free(name3);
-// }
-
if (ret != KNOT_ZONE_NAME_FOUND
&& ce != NULL) {
// try to find wildcard child
@@ -1025,6 +1053,32 @@ static void knot_zone_contents_check_loops_in_tree(knot_zone_tree_node_t *tnode,
}
/*----------------------------------------------------------------------------*/
+
+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));
+ 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);
+}
+
+/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -1041,22 +1095,19 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
return NULL;
}
-// printf("created cont: %p (%s)\n",
-// contents, knot_dname_to_str(apex->owner));
-
contents->apex = apex;
contents->zone = zone;
- knot_node_set_zone(apex, zone);
+ knot_node_set_zone(apex, contents->zone);
contents->node_count = 1;
- dbg_zone("Creating tree for normal nodes.\n");
+ dbg_zone_verb("Creating tree for normal nodes.\n");
contents->nodes = malloc(sizeof(knot_zone_tree_t));
if (contents->nodes == NULL) {
ERR_ALLOC_FAILED;
goto cleanup;
}
- dbg_zone("Creating tree for NSEC3 nodes.\n");
+ dbg_zone_verb("Creating tree for NSEC3 nodes.\n");
contents->nsec3_nodes = malloc(sizeof(knot_zone_tree_t));
if (contents->nsec3_nodes == NULL) {
ERR_ALLOC_FAILED;
@@ -1064,7 +1115,7 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
}
if (use_domain_table) {
- dbg_zone("Creating domain name table.\n");
+ dbg_zone_verb("Creating domain name table.\n");
contents->dname_table = knot_dname_table_new();
if (contents->dname_table == NULL) {
ERR_ALLOC_FAILED;
@@ -1077,20 +1128,20 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
//contents->node_count = node_count;
/* Initialize NSEC3 params */
- dbg_zone("Initializing NSEC3 parameters.\n");
+ dbg_zone_verb("Initializing NSEC3 parameters.\n");
contents->nsec3_params.algorithm = 0;
contents->nsec3_params.flags = 0;
contents->nsec3_params.iterations = 0;
contents->nsec3_params.salt_length = 0;
contents->nsec3_params.salt = NULL;
- dbg_zone("Initializing zone trees.\n");
+ 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("Inserting apex into the zone tree.\n");
+ 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;
@@ -1098,14 +1149,14 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
#ifdef USE_HASH_TABLE
if (node_count > 0) {
- dbg_zone("Creating hash table.\n");
+ 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("Inserting apex into the hash table.\n");
+ 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)),
@@ -1121,7 +1172,7 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
// insert names from the apex to the domain table
if (use_domain_table) {
- dbg_zone("Inserting names from apex to table.\n");
+ 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) {
@@ -1133,7 +1184,7 @@ knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
return contents;
cleanup:
- dbg_zone("Cleaning up.\n");
+ dbg_zone_verb("Cleaning up.\n");
free(contents->dname_table);
free(contents->nodes);
free(contents->nsec3_nodes);
@@ -1234,6 +1285,12 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
return KNOT_EBADARG;
}
+dbg_zone_exec_detail(
+ char *name = knot_dname_to_str(knot_node_owner(node));
+ dbg_zone_detail("Adding node to zone: %s.\n", name);
+ free(name);
+);
+
int ret = 0;
if ((ret = knot_zone_contents_check_node(zone, node)) != 0) {
dbg_zone("Node check failed.\n");
@@ -1257,10 +1314,6 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
}
#ifdef USE_HASH_TABLE
-// char *name = knot_dname_to_str(node->owner);
-// dbg_zone("Adding node with owner %s to hash table.\n", name);
-// free(name);
- //assert(zone->table != NULL);
// add the node also to the hash table if authoritative, or deleg. point
if (zone->table != NULL
&& ck_insert_item(zone->table,
@@ -1281,7 +1334,7 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
return KNOT_EOK;
}
- dbg_zone("Creating parents of the node.\n");
+ dbg_zone_detail("Creating parents of the node.\n");
knot_dname_t *chopped =
knot_dname_left_chop(knot_node_owner(node));
@@ -1293,7 +1346,7 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
}
if (knot_dname_compare(knot_node_owner(zone->apex), chopped) == 0) {
- dbg_zone("Zone apex is the parent.\n");
+ dbg_zone_detail("Zone apex is the parent.\n");
knot_node_set_parent(node, zone->apex);
// check if the node is not wildcard child of the parent
@@ -1307,7 +1360,7 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
= knot_zone_contents_get_node(zone, chopped)) == NULL &&
chopped != NULL) {
/* Adding new dname to zone + add to table. */
- dbg_zone("Creating new node.\n");
+ dbg_zone_detail("Creating new node.\n");
assert(chopped);
next_node = knot_node_new(chopped, NULL, flags);
@@ -1322,7 +1375,7 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
knot_zone_contents_dnames_from_node_to_table(
zone->dname_table, next_node);
if (ret != KNOT_EOK) {
- knot_node_free(&next_node, 0);
+ knot_node_free(&next_node);
knot_dname_release(chopped);
return ret;
}
@@ -1339,14 +1392,13 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
== NULL);
assert(knot_node_owner(next_node) == chopped);
- dbg_zone("Inserting new node to zone tree.\n");
-// TREE_INSERT(zone->tree, knot_node, avl, next_node);
+ dbg_zone_detail("Inserting new node to zone tree.\n");
ret = knot_zone_tree_insert(zone->nodes,
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);
@@ -1354,11 +1406,11 @@ int knot_zone_contents_add_node(knot_zone_contents_t *zone,
}
#ifdef USE_HASH_TABLE
-dbg_zone_exec(
+dbg_zone_exec_detail(
char *name = knot_dname_to_str(
knot_node_owner(next_node));
- dbg_zone("Adding new node with owner %s to "
- "hash table.\n", name);
+ dbg_zone_detail("Adding new node with owner %s to "
+ "hash table.\n", name);
free(name);
);
@@ -1369,7 +1421,7 @@ dbg_zone_exec(
knot_dname_size(knot_node_owner(next_node)),
(void *)next_node) != 0) {
dbg_zone("Error inserting node into "
- "hash table!\n");
+ "hash table!\n");
/*! \todo Delete the node?? */
/* Directly discard. */
knot_dname_release(chopped);
@@ -1390,7 +1442,7 @@ dbg_zone_exec(
++zone->node_count;
- dbg_zone("Next parent.\n");
+ dbg_zone_detail("Next parent.\n");
node = next_node;
knot_dname_t *chopped_last = chopped;
chopped = knot_dname_left_chop(chopped);
@@ -1406,7 +1458,7 @@ dbg_zone_exec(
assert(knot_node_parent(node) == NULL);
knot_node_set_parent(node, next_node);
- dbg_zone("Created all parents.\n");
+ dbg_zone_detail("Created all parents.\n");
}
/* Directly discard. */
@@ -1419,15 +1471,22 @@ dbg_zone_exec(
/*----------------------------------------------------------------------------*/
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_t *rrset, knot_node_t **node,
+ knot_rrset_dupl_handling_t dupl,
+ int use_domain_table)
{
if (zone == NULL || rrset == NULL || zone->apex == NULL
|| zone->apex->owner == NULL || node == NULL) {
return KNOT_EBADARG;
}
+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)));
+ free(name);
+);
+
// check if the RRSet belongs to the zone
if (knot_dname_compare(knot_rrset_owner(rrset),
zone->apex->owner) != 0
@@ -1448,8 +1507,12 @@ int knot_zone_contents_add_rrset(knot_zone_contents_t *zone,
int rc;
/*! \todo REMOVE RRSET */
- rc = knot_node_add_rrset(*node, rrset,
- dupl == KNOT_RRSET_DUPL_MERGE);
+ if (dupl == KNOT_RRSET_DUPL_MERGE) {
+ rc = knot_node_add_rrset_no_dupl(*node, rrset);
+ } else {
+ rc = knot_node_add_rrset(*node, rrset, 0);
+ }
+
if (rc < 0) {
dbg_zone("Failed to add RRSet to node.\n");
return rc;
@@ -1458,14 +1521,13 @@ int knot_zone_contents_add_rrset(knot_zone_contents_t *zone,
int ret = rc;
if (use_domain_table) {
- dbg_zone("Saving RRSet to table.\n");
+ 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");
+ "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
@@ -1480,7 +1542,7 @@ int knot_zone_contents_add_rrset(knot_zone_contents_t *zone,
knot_rrset_set_owner(rrset, (*node)->owner);
}
- dbg_zone("RRSet OK.\n");
+ dbg_zone_detail("RRSet OK.\n");
return ret;
}
@@ -1493,11 +1555,13 @@ int knot_zone_contents_add_rrsigs(knot_zone_contents_t *zone,
knot_rrset_dupl_handling_t dupl,
int use_domain_table)
{
+ dbg_zone_verb("Adding RRSIGs to zone contents.\n");
+
if (zone == NULL || rrsigs == NULL || rrset == NULL || node == NULL
|| 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) {
@@ -1522,7 +1586,7 @@ dbg_zone_exec(
if (*rrset != NULL
&& (knot_dname_compare(knot_rrset_owner(rrsigs),
knot_rrset_owner(*rrset)) != 0)) {
- dbg_zone("RRSIGs does not belong to the given RRSet.\n");
+ dbg_zone("RRSIGs do not belong to the given RRSet.\n");
return KNOT_EBADARG;
}
@@ -1548,8 +1612,8 @@ dbg_zone_exec(
// find the RRSet in the node
// take only the first RDATA from the RRSIGs
- dbg_zone("Finding RRSet for type %s\n",
- knot_rrtype_to_string(
+ dbg_zone_detail("Finding RRSet for type %s\n",
+ knot_rrtype_to_string(
knot_rdata_rrsig_type_covered(
knot_rrset_rdata(rrsigs))));
*rrset = knot_node_get_rrset(
@@ -1563,28 +1627,28 @@ dbg_zone_exec(
assert(*rrset != NULL);
- // add all domain names from the RRSet to domain name table
int rc;
int ret = KNOT_EOK;
rc = knot_rrset_add_rrsigs(*rrset, rrsigs, dupl);
if (rc < 0) {
- dbg_dname("Failed to add RRSIGs to RRSet.\n");
+ dbg_zone("Failed to add RRSIGs to RRSet.\n");
return rc;
} else if (rc > 0) {
- assert(dupl == KNOT_RRSET_DUPL_MERGE);
+ assert(dupl == KNOT_RRSET_DUPL_MERGE ||
+ dupl == KNOT_RRSET_DUPL_SKIP);
ret = 1;
}
+ // add all domain names from the RRSet to domain name table
if (use_domain_table) {
- dbg_zone("Saving RRSIG RRSet to table.\n");
+ dbg_zone_detail("Saving RRSIG RRSet to table.\n");
rc = knot_zone_contents_dnames_from_rrset_to_table(
- zone->dname_table, rrsigs, 0, (*rrset)->owner);
+ 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");
+ "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
@@ -1598,7 +1662,7 @@ dbg_zone_exec(
knot_rrset_set_owner((*rrset)->rrsigs, (*rrset)->owner);
}
- dbg_zone("RRSIGs OK\n");
+ dbg_zone_detail("RRSIGs OK\n");
return ret;
}
@@ -1617,6 +1681,7 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone,
int ret = 0;
if ((ret = knot_zone_contents_check_node(zone, node)) != 0) {
+ dbg_zone("Failed node check: %s\n", knot_strerror(ret));
return ret;
}
@@ -1624,6 +1689,8 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone,
// 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));
return ret;
}
@@ -1632,7 +1699,8 @@ int knot_zone_contents_add_nsec3_node(knot_zone_contents_t *zone,
zone->dname_table, node);
if (ret != KNOT_EOK) {
/*! \todo Remove the node from the tree. */
- dbg_zone("Failed to add dnames into table.\n");
+ dbg_zone("Failed to add dnames into table: %s.\n",
+ knot_strerror(ret));
return ret;
}
}
@@ -1682,8 +1750,12 @@ int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone,
int rc;
/*! \todo REMOVE RRSET */
- rc = knot_node_add_rrset(*node, rrset,
- dupl == KNOT_RRSET_DUPL_MERGE);
+ if (dupl == KNOT_RRSET_DUPL_MERGE) {
+ rc = knot_node_add_rrset_no_dupl(*node, rrset);
+ } else {
+ rc = knot_node_add_rrset(*node, rrset, 0);
+ }
+
if (rc < 0) {
return rc;
}
@@ -1691,14 +1763,13 @@ int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone,
int ret = rc;
if (use_domain_table) {
- dbg_zone("Saving NSEC3 RRSet to table.\n");
+ 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");
+ "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
@@ -1713,7 +1784,7 @@ int knot_zone_contents_add_nsec3_rrset(knot_zone_contents_t *zone,
knot_rrset_set_owner(rrset, (*node)->owner);
}
- dbg_zone("NSEC3 OK\n");
+ dbg_zone_detail("NSEC3 OK\n");
return ret;
}
@@ -1740,9 +1811,6 @@ dbg_zone_exec_verb(
*removed_hash = ck_remove_item(contents->table,
(const char *)knot_dname_name(owner),
knot_dname_size(owner));
-// int ret = ck_detete_item(contents->table,
-// (const char *)knot_dname_name(owner),
-// knot_dname_size(owner), NULL, 0);
if (*removed_hash == NULL) {
return KNOT_ENONODE;
}
@@ -1837,11 +1905,6 @@ knot_node_t *knot_zone_contents_get_node(const knot_zone_contents_t *zone,
return NULL;
}
- // create dummy node to use for lookup
-// knot_node_t *tmp = knot_node_new((knot_dname_t *)name, NULL);
-// knot_node_t *n = TREE_FIND(zone->tree, knot_node, avl, tmp);
-// knot_node_free(&tmp, 0);
-
knot_node_t *n;
int ret = knot_zone_tree_get(zone->nodes, name, &n);
if (ret != KNOT_EOK) {
@@ -1861,10 +1924,6 @@ knot_node_t *knot_zone_contents_get_nsec3_node(
return NULL;
}
- // create dummy node to use for lookup
-// knot_node_t *tmp = knot_node_new((knot_dname_t *)name, NULL);
-// knot_node_t *n = TREE_FIND(zone->nsec3_nodes, knot_node, avl, tmp);
-// knot_node_free(&tmp, 0);
knot_node_t *n;
int ret = knot_zone_tree_get(zone->nsec3_nodes, name, &n);
@@ -1899,11 +1958,11 @@ int knot_zone_contents_find_dname(const knot_zone_contents_t *zone,
return KNOT_EBADARG;
}
-dbg_zone_exec(
+dbg_zone_exec_verb(
char *name_str = knot_dname_to_str(name);
char *zone_str = knot_dname_to_str(zone->apex->owner);
- dbg_zone("Searching for name %s in zone %s...\n",
- name_str, zone_str);
+ dbg_zone_verb("Searching for name %s in zone %s...\n",
+ name_str, zone_str);
free(name_str);
free(zone_str);
);
@@ -1928,14 +1987,14 @@ dbg_zone_exec(
*node = found;
*previous = prev;
-dbg_zone_exec(
+dbg_zone_exec_detail(
char *name_str = (*node) ? knot_dname_to_str((*node)->owner)
: "(nil)";
char *name_str2 = (*previous != NULL)
? knot_dname_to_str((*previous)->owner)
: "(nil)";
- dbg_zone("Search function returned %d, node %s and prev: %s\n",
- exact_match, name_str, name_str2);
+dbg_zone_detail("Search function returned %d, node %s (%p) and prev: %s (%p)\n",
+ exact_match, name_str, *node, name_str2, *previous);
if (*node) {
free(name_str);
@@ -1944,19 +2003,23 @@ dbg_zone_exec(
free(name_str2);
}
);
-
- *closest_encloser = *node;
-
// there must be at least one node with domain name less or equal to
// the searched name if the name belongs to the zone (the root)
- if (*node == NULL) {
+ if (*node == NULL && *previous == NULL) {
return KNOT_EBADZONE;
}
- // TODO: this could be replaced by saving pointer to closest encloser
- // in node
+ /* This function was quite out of date. The find_in_tree() function
+ * may return NULL in the 'found' field, so we cannot search for the
+ * closest encloser from this node.
+ */
+
+ if (exact_match) {
+ *closest_encloser = *node;
+ } else {
+ *closest_encloser = *previous;
+ assert(*closest_encloser != NULL);
- if (!exact_match) {
int matched_labels = knot_dname_matched_labels(
knot_node_owner((*closest_encloser)), name);
while (matched_labels < knot_dname_label_count(
@@ -1968,11 +2031,11 @@ dbg_zone_exec(
}
dbg_zone_exec(
char *n = knot_dname_to_str(knot_node_owner((*closest_encloser)));
- dbg_zone("Closest encloser: %s\n", n);
+ dbg_zone_detail("Closest encloser: %s\n", n);
free(n);
);
- dbg_zone("find_dname() returning %d\n", exact_match);
+ dbg_zone_verb("find_dname() returning %d\n", exact_match);
return (exact_match)
? KNOT_ZONE_NAME_FOUND
@@ -2055,11 +2118,11 @@ int knot_zone_contents_find_dname_hash(const knot_zone_contents_t *zone,
return KNOT_EBADARG;
}
-dbg_zone_exec(
+dbg_zone_exec_verb(
char *name_str = knot_dname_to_str(name);
char *zone_str = knot_dname_to_str(zone->apex->owner);
- dbg_zone("Searching for name %s in zone %s...\n",
- name_str, zone_str);
+ dbg_zone_verb("Searching for name %s in zone %s...\n",
+ name_str, zone_str);
free(name_str);
free(zone_str);
);
@@ -2092,9 +2155,9 @@ dbg_zone_exec(
*node = (const knot_node_t *)item->value;
*closest_encloser = *node;
- dbg_zone("Found node in hash table: %p (owner %p, "
- "labels: %d)\n", *node, (*node)->owner,
- knot_dname_label_count((*node)->owner));
+ 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;
@@ -2104,34 +2167,22 @@ dbg_zone_exec(
// chop leftmost labels until some node is found
// copy the name for chopping
- /* Local allocation, will be discarded. */
- //knot_dname_t *name_copy = knot_dname_deep_copy(name);
-dbg_zone_exec(
- //char *n = knot_dname_to_str(name_copy);
- dbg_zone("Finding closest encloser..\nStarting with: %.*s\n",
- (int)name_size, name_tmp);
- //free(n);
-);
+
+ dbg_zone_detail("Finding closest encloser..\nStarting with: %.*s\n",
+ (int)name_size, name_tmp);
while (item == NULL) {
- //knot_dname_left_chop_no_copy(name_copy);
knot_zone_contents_left_chop(name_tmp, &name_size);
-dbg_zone_exec(
- //char *n = knot_dname_to_str(name_copy);
- dbg_zone("Chopped leftmost label: %.*s\n",
- (int)name_size, name_tmp);
- //free(n);
+dbg_zone_exec_detail(
+ dbg_zone_detail("Chopped leftmost label: %.*s\n",
+ (int)name_size, name_tmp);
);
// not satisfied in root zone!!
- //assert(name_copy->label_count > 0);
assert(name_size > 0);
item = ck_find_item(zone->table, name_tmp, name_size);
}
- /* Directly discard. */
- //knot_dname_free(&name_copy);
-
assert(item != NULL);
*closest_encloser = (const knot_node_t *)item->value;
@@ -2165,9 +2216,16 @@ int knot_zone_contents_find_nsec3_for_name(const knot_zone_contents_t *zone,
return ret;
}
-dbg_zone_exec(
+ // check if the NSEC3 tree is not empty
+ if (zone->nsec3_nodes->th_root == NULL) {
+ dbg_zone("NSEC3 tree is empty.\n");
+ knot_dname_release(nsec3_name);
+ return KNOT_ENSEC3CHAIN;
+ }
+
+dbg_zone_exec_verb(
char *n = knot_dname_to_str(nsec3_name);
- dbg_zone("NSEC3 node name: %s.\n", n);
+ dbg_zone_verb("NSEC3 node name: %s.\n", n);
free(n);
);
@@ -2180,26 +2238,33 @@ dbg_zone_exec(
knot_dname_release(nsec3_name);
-dbg_zone_exec(
+dbg_zone_exec_detail(
if (found) {
char *n = knot_dname_to_str(found->owner);
- dbg_zone("Found NSEC3 node: %s.\n", n);
+ dbg_zone_detail("Found NSEC3 node: %s.\n", n);
free(n);
} else {
- dbg_zone("Found no NSEC3 node.\n");
+ dbg_zone_detail("Found no NSEC3 node.\n");
}
if (prev) {
assert(prev->owner);
char *n = knot_dname_to_str(prev->owner);
- dbg_zone("Found previous NSEC3 node: %s.\n", n);
+ dbg_zone_detail("Found previous NSEC3 node: %s.\n", n);
free(n);
} else {
- dbg_zone("Found no previous NSEC3 node.\n");
+ dbg_zone_detail("Found no previous NSEC3 node.\n");
}
);
*nsec3_node = found;
+ // This check cannot be used now, the function returns proper return
+ // value if the node was not found
+// if (*nsec3_node == NULL) {
+// // there is no NSEC3 node even if there should be
+// return KNOT_ENSEC3CHAIN;
+// }
+
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
@@ -2211,7 +2276,55 @@ dbg_zone_exec(
*nsec3_previous = prev;
}
- dbg_zone("find_nsec3_for_name() returning %d\n", exact_match);
+ 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
+ * 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_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;
+ }
+
+ /* If there is none, try 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)
+ ? knot_dname_to_str(
+ knot_node_owner(*nsec3_previous))
+ : "none";
+ dbg_zone_detail("Previous node: %s, checking parameters...\n",
+ name);
+ if (*nsec3_previous) {
+ free(name);
+ }
+);
+ if (*nsec3_previous == original_prev || nsec3_rdata == NULL) {
+ // cycle
+ *nsec3_previous = NULL;
+ break;
+ }
+ }
return (exact_match)
? KNOT_ZONE_NAME_FOUND
@@ -2257,23 +2370,18 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone)
adjust_arg.first_node = NULL;
adjust_arg.previous_node = NULL;
adjust_arg.err = KNOT_EOK;
-// adjust_arg.check_ver = check_ver;
/*
- * Adjust the NSEC3 nodes first.
- * There are independent on the normal nodes, but the normal nodes are
- * dependent on them.
+ * First of all we must set node.prev pointers, as these are used in
+ * the search functions.
*/
-
- dbg_zone("Adjusting NSEC3 nodes.\n");
- int ret = knot_zone_tree_forward_apply_inorder(
- zone->nsec3_nodes,
- knot_zone_contents_adjust_nsec3_node_in_tree,
- &adjust_arg);
+ 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);
assert(ret == KNOT_EOK);
if (adjust_arg.err != KNOT_EOK) {
- dbg_zone("Failed to adjust NSEC3 nodes: %s\n",
+ dbg_zone("Failed to set 'prev' pointers to NSEC3 nodes: %s\n",
knot_strerror(adjust_arg.err));
return adjust_arg.err;
}
@@ -2281,13 +2389,46 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone)
// 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);
}
dbg_zone("Done.\n");
adjust_arg.first_node = NULL;
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);
+ 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));
+ return adjust_arg.err;
+ }
+
+ // set the last node as previous of the first node
+ assert(zone->apex == adjust_arg.first_node);
+ knot_node_set_previous(zone->apex, adjust_arg.previous_node);
+ dbg_zone("Done.\n");
+
+ /*
+ * Adjust the NSEC3 nodes first.
+ * There are independent on the normal nodes, but the normal nodes are
+ * dependent on them.
+ */
+
+ 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);
+ assert(ret == KNOT_EOK);
+
+ if (adjust_arg.err != KNOT_EOK) {
+ dbg_zone("Failed to adjust NSEC3 nodes: %s\n",
+ knot_strerror(adjust_arg.err));
+ 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,
@@ -2300,9 +2441,6 @@ int knot_zone_contents_adjust(knot_zone_contents_t *zone)
return adjust_arg.err;
}
- assert(zone->apex == adjust_arg.first_node);
- knot_node_set_previous(zone->apex, adjust_arg.previous_node);
-
dbg_zone("Done.\n");
return ret;
@@ -2339,58 +2477,6 @@ int knot_zone_contents_check_loops(knot_zone_contents_t *zone)
/*----------------------------------------------------------------------------*/
-int knot_zone_contents_adjust_old(knot_zone_contents_t *zone)
-{
- if (zone == NULL) {
- return KNOT_EBADARG;
- }
-
- // load NSEC3PARAM (needed on adjusting function)
- knot_zone_contents_load_nsec3param(zone);
-
- knot_zone_adjust_arg_t adjust_arg;
- adjust_arg.zone = zone;
- adjust_arg.first_node = NULL;
- adjust_arg.previous_node = NULL;
-// adjust_arg.check_ver = check_ver;
- adjust_arg.err = KNOT_EOK;
-
- dbg_zone("Adjusting normal nodes.\n");
- int ret = knot_zone_tree_forward_apply_inorder(zone->nodes,
- knot_zone_contents_adjust_node_in_tree,
- &adjust_arg);
- if (ret != KNOT_EOK) {
- return ret;
- }
- if (adjust_arg.err != KNOT_EOK) {
- dbg_zone("Failed node adjusting: %s\n",
- knot_strerror(adjust_arg.err));
- return adjust_arg.err;
- }
-
- dbg_zone("Done.\n");
-
- assert(zone->apex == adjust_arg.first_node);
- knot_node_set_previous(zone->apex, adjust_arg.previous_node);
-
- adjust_arg.first_node = NULL;
- adjust_arg.previous_node = NULL;
-
- 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);
-
- dbg_zone("Done.\n");
- if (adjust_arg.first_node) {
- knot_node_set_previous(adjust_arg.first_node,
- adjust_arg.previous_node);
- }
-
- return ret;
-}
-
-/*----------------------------------------------------------------------------*/
-
int knot_zone_contents_load_nsec3param(knot_zone_contents_t *zone)
{
if (zone == NULL || zone->apex == NULL) {
@@ -2418,8 +2504,8 @@ int knot_zone_contents_nsec3_enabled(const knot_zone_contents_t *zone)
return KNOT_EBADARG;
}
- //return (zone->nsec3_params.algorithm != 0);
- return (zone->nsec3_nodes->th_root != NULL);
+ return (zone->nsec3_params.algorithm != 0
+ && zone->nsec3_nodes->th_root != NULL);
}
/*----------------------------------------------------------------------------*/
@@ -2662,16 +2748,15 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
// ret = ck_copy_table(from->table, &contents->table);
ret = ck_shallow_copy(from->table, &contents->table);
if (ret != 0) {
- dbg_zone("knot_zone_contents_shallow_copy: "
- "hash table copied\n");
+ 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");
+ dbg_zone("knot_zone_contents_shallow_copy: finished OK\n");
*to = contents;
return KNOT_EOK;
@@ -2740,13 +2825,11 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
contents->node_count = from->node_count;
contents->flags = from->flags;
+ // set the 'new' flag
+ knot_zone_contents_set_gen_new(contents);
contents->zone = from->zone;
-// /* Initialize NSEC3 params */
-// memcpy(&contents->nsec3_params, &from->nsec3_params,
-// sizeof(knot_nsec3_params_t));
-
if ((ret = knot_zone_tree_deep_copy(from->nodes,
contents->nodes)) != KNOT_EOK
|| (ret = knot_zone_tree_deep_copy(from->nsec3_nodes,
@@ -2758,8 +2841,8 @@ int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
if (from->table != NULL) {
ret = ck_deep_copy(from->table, &contents->table);
if (ret != 0) {
- dbg_zone("knot_zone_contents_shallow_copy: "
- "hash table copied\n");
+ dbg_zone_verb("knot_zone_contents_shallow_copy: "
+ "hash table copied\n");
ret = KNOT_ERROR;
goto cleanup;
}
@@ -2903,16 +2986,6 @@ static void knot_zc_integrity_check_previous(const knot_node_t *node,
++check_data->errors;
}
-// if (knot_node_next(check_data->previous) != node) {
-// char *name2 = knot_dname_to_str(knot_node_owner(
-// knot_node_next(check_data->previous)));
-// fprintf(stderr, "Wrong next node: node %s, next %s. "
-// "Should be %s.\n", name_prev, name2 ,name);
-// free(name2);
-
-// ++check_data->errors;
-// }
-
free(name_prev);
}
}
@@ -2995,11 +3068,6 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node,
&& knot_dname_matched_labels(node_owner, parent_owner)
== knot_dname_label_count(parent_owner)) {
-// // increase the parent's children count
-// fprintf(stderr, "Parent: %s, node: %s. Increasing children count.\n",
-// pname, name);
-// ++check_data->children;
-
// check the parent pointer
const knot_node_t *parent = knot_node_parent(node);
if (parent != check_data->parent) {
@@ -3038,22 +3106,6 @@ static void knot_zc_integrity_check_parent(const knot_node_t *node,
++check_data->errors;
}
}
- } else {
- // not a direct child, check children count
-// if (check_data->parent
-// && knot_node_children(check_data->parent)
-// != check_data->children) {
-// fprintf(stderr, "Wrong children count: node %s, count: "
-// "%u. Should be: %u\n", pname,
-// knot_node_children(check_data->parent),
-// check_data->children);
-
-// ++check_data->errors;
-// }
-
- // reset the children count
- //check_data->parent = node;
-// check_data->children = 0;
}
free(pname);
@@ -3110,15 +3162,6 @@ static int knot_zc_integrity_check_find_dname(const knot_zone_contents_t *zone,
const char *node_name)
{
int ret = 0;
-
-// find_dname_data_t data_find;
-// data_find.found = NULL;
-// data_find.to_find = to_find;
-
-// int res = knot_zone_contents_dname_table_apply(
-// (knot_zone_contents_t *)zone,
-// find_in_dname_table, (void *)&data_find);
-// assert(res == KNOT_EOK);
knot_dname_t *found = knot_dname_table_find_dname(zone->dname_table,
(knot_dname_t *)to_find);
@@ -3364,27 +3407,12 @@ static void reset_new_nodes(knot_zone_tree_node_t *tree_node, void *data)
/*----------------------------------------------------------------------------*/
-/*!< \todo remove debug code. */
-//static void print_child_count(knot_node_t *node, void *data)
-//{
-// UNUSED(data);
-// assert(node != NULL);
-
-// char *name = knot_dname_to_str(knot_node_owner(node));
-// fprintf(stderr, "Node: %s, children count: %d\n", name,
-// knot_node_children(node));
-// free(name);
-//}
-
-/*----------------------------------------------------------------------------*/
-
static void count_nsec3_nodes(knot_zone_tree_node_t *tree_node, void *data)
{
assert(tree_node != NULL);
assert(tree_node->node != NULL);
assert(data != NULL);
-// int *count = (int *)data;
knot_node_t *apex = (knot_node_t *)data;
assert(apex != NULL);
@@ -3406,10 +3434,6 @@ int knot_zc_integrity_check_child_count(check_data_t *data)
knot_zone_tree_init(nodes_copy);
-// int ret = knot_zone_contents_tree_apply_inorder(data->contents,
-// print_child_count,
-// NULL);
-
int ret = knot_zone_tree_deep_copy(data->contents->nodes, nodes_copy);
assert(ret == KNOT_EOK);
@@ -3425,9 +3449,8 @@ int knot_zc_integrity_check_child_count(check_data_t *data)
knot_zone_tree_forward_apply_inorder(nodes_copy, count_children, NULL);
// add count of NSEC3 nodes to the apex' children count
-// int nsec3_nodes = 0;
- dbg_zone("Children count of new apex before NSEC3: %d\n",
- data->contents->apex->new_node->children);
+ 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);
@@ -3435,7 +3458,6 @@ int knot_zc_integrity_check_child_count(check_data_t *data)
// now compare the children counts
// iterate over the old zone and search for nodes in the copy
-// data->children = nsec3_nodes;
knot_zone_tree_forward_apply_inorder(nodes_copy, check_child_count,
(void *)data);
diff --git a/src/libknot/zone/zone-contents.h b/src/libknot/zone/zone-contents.h
index 3143ef9..2ca333e 100644..100755
--- a/src/libknot/zone/zone-contents.h
+++ b/src/libknot/zone/zone-contents.h
@@ -55,7 +55,7 @@ typedef struct knot_zone_contents_t {
knot_nsec3_params_t nsec3_params;
- /*!
+ /*!
* \todo Unify the use of this field - authoritative nodes vs. all.
*/
uint node_count;
@@ -80,17 +80,14 @@ typedef struct knot_zone_contents_t {
/*----------------------------------------------------------------------------*/
knot_zone_contents_t *knot_zone_contents_new(knot_node_t *apex,
- uint node_count,
- int use_domain_table,
- struct knot_zone *zone);
-
-//short knot_zone_contents_generation(const knot_zone_contents_t *contents);
+ uint node_count,
+ int use_domain_table,
+ struct knot_zone *zone);
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);
int knot_zone_contents_gen_is_finished(const knot_zone_contents_t *contents);
-//void knot_zone_contents_switch_generation(knot_zone_contents_t *contents);
void knot_zone_contents_set_gen_old(knot_zone_contents_t *contents);
void knot_zone_contents_set_gen_new(knot_zone_contents_t *contents);
@@ -187,9 +184,6 @@ 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);
-//knot_zone_tree_node_t *knot_zone_contents_remove_node(
-// knot_zone_contents_t *contents, const knot_node_t *node);
-
int knot_zone_contents_remove_nsec3_node(knot_zone_contents_t *contents,
const knot_node_t *node, knot_zone_tree_node_t **removed);
@@ -357,9 +351,6 @@ const knot_node_t *knot_zone_contents_apex(
knot_node_t *knot_zone_contents_get_apex(
const knot_zone_contents_t *contents);
-//knot_dname_t *knot_zone_contents_name(
-// const knot_zone_contents_t *contents);
-
/*!
* \brief Optimizes zone by replacing domain names in RDATA with references to
* domain names present in zone (as node owners).
@@ -555,12 +546,6 @@ int knot_zone_contents_shallow_copy(const knot_zone_contents_t *from,
int knot_zone_contents_shallow_copy2(const knot_zone_contents_t *from,
knot_zone_contents_t **to);
-//int knot_zone_contents_dnames_from_node_to_table(
-// knot_dname_table_t *table, knot_node_t *node);
-
-//void knot_zone_contents_adjust_node(knot_node_t *node,
-// knot_zone_contents_t *zone, int check_ver);
-
void knot_zone_contents_free(knot_zone_contents_t **contents);
void knot_zone_contents_deep_free(knot_zone_contents_t **contents,
diff --git a/src/libknot/zone/zone-diff.c b/src/libknot/zone/zone-diff.c
new file mode 100755
index 0000000..d3fd961
--- /dev/null
+++ b/src/libknot/zone/zone-diff.c
@@ -0,0 +1,1004 @@
+/* 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 <config.h>
+
+#include "libknot/util/error.h"
+#include "libknot/util/debug.h"
+#include "libknot/rdata.h"
+#include "zone-diff.h"
+#include "libknot/nameserver/name-server.h"
+
+struct zone_diff_param {
+ const knot_zone_contents_t *contents;
+ char nsec3;
+ knot_changeset_t *changeset;
+ int ret;
+};
+
+// forward declaration
+static int knot_zone_diff_rdata(const knot_rrset_t *rrset1,
+ const knot_rrset_t *rrset2,
+ knot_changeset_t *changeset);
+
+static int knot_zone_diff_load_soas(const knot_zone_contents_t *zone1,
+ const knot_zone_contents_t *zone2,
+ knot_changeset_t *changeset)
+{
+ if (zone1 == NULL || zone2 == NULL || changeset == NULL) {
+ return KNOT_EBADARG;
+ }
+
+ const knot_node_t *apex1 = knot_zone_contents_apex(zone1);
+ const knot_node_t *apex2 = knot_zone_contents_apex(zone2);
+ if (apex1 == NULL || apex2 == NULL) {
+ dbg_zonediff("zone_diff: "
+ "both zones must have apex nodes.\n");
+ return KNOT_EBADARG;
+ }
+
+ knot_rrset_t *soa_rrset1 = knot_node_get_rrset(apex1, KNOT_RRTYPE_SOA);
+ knot_rrset_t *soa_rrset2 = knot_node_get_rrset(apex2, KNOT_RRTYPE_SOA);
+ if (soa_rrset1 == NULL || soa_rrset2 == NULL) {
+ dbg_zonediff("zone_diff: "
+ "both zones must have apex nodes.\n");
+ return KNOT_EBADARG;
+ }
+
+ if (knot_rrset_rdata(soa_rrset1) == NULL ||
+ knot_rrset_rdata(soa_rrset2) == NULL) {
+ dbg_zonediff("zone_diff: "
+ "both zones must have apex nodes with SOA "
+ "RRs.\n");
+ return KNOT_EBADARG;
+ }
+
+ int64_t soa_serial1 =
+ knot_rdata_soa_serial(knot_rrset_rdata(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));
+
+ 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",
+ 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",
+ 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),
+ changeset);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff_verb("zone_diff: load_soas: Failed to diff SOAs' RRSIGs."
+ " Reason: %s.\n", knot_strerror(ret));
+ /* This might not necasarilly be an error. */
+ }
+
+ assert(changeset);
+
+ ret = knot_rrset_deep_copy(soa_rrset1, &changeset->soa_from, 1);
+ if (ret != KNOT_EOK) {
+ 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);
+ assert(changeset->soa_from->rrsigs == NULL);
+
+ ret = knot_rrset_deep_copy(soa_rrset2, &changeset->soa_to, 1);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: load_soas: Cannot copy RRSet.\n");
+ return ret;
+ }
+
+ knot_rrset_deep_free(&changeset->soa_to->rrsigs, 1, 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",
+ soa_serial1, soa_serial2);
+
+ return KNOT_EOK;
+}
+
+/*!< \todo Only use add or remove function, not both as they are the same. */
+/*!< \todo Also, this might be all handled by function in changesets.h!!! */
+static int knot_zone_diff_changeset_add_rrset(knot_changeset_t *changeset,
+ const knot_rrset_t *rrset)
+{
+ /* Remove all RRs of the RRSet. */
+ if (changeset == NULL || rrset == NULL) {
+ dbg_zonediff("zone_diff: add_rrset: NULL parameters.\n");
+ return KNOT_EBADARG;
+ }
+
+ 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_t *rrset_copy = NULL;
+ int ret = knot_rrset_deep_copy(rrset, &rrset_copy, 1);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: add_rrset: Cannot copy RRSet.\n");
+ return ret;
+ }
+ if (rrset_copy->rrsigs != NULL) {
+ knot_rrset_deep_free(&rrset_copy->rrsigs, 1, 1, 1);
+ }
+ assert(knot_rrset_rrsigs(rrset_copy) == NULL);
+
+ ret = knot_changeset_add_new_rr(changeset, rrset_copy,
+ XFRIN_CHANGESET_ADD);
+ if (ret != KNOT_EOK) {
+ /* We have to free the copy now! */
+ knot_rrset_deep_free(&rrset_copy, 1, 1, 1);
+ dbg_zonediff("zone_diff: add_rrset: Could not add RRSet. "
+ "Reason: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+
+ return KNOT_EOK;
+}
+
+static int knot_zone_diff_changeset_remove_rrset(knot_changeset_t *changeset,
+ const knot_rrset_t *rrset)
+{
+ /* Remove all RRs of the RRSet. */
+ if (changeset == NULL) {
+ dbg_zonediff("zone_diff: remove_rrset: NULL parameters.\n");
+ return KNOT_EBADARG;
+ }
+
+ if (rrset == NULL) {
+ return KNOT_EOK;
+ }
+
+ if (knot_rrset_rdata_rr_count(rrset) == 0) {
+ 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_t *rrset_copy = NULL;
+ int ret = knot_rrset_deep_copy(rrset, &rrset_copy, 1);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: remove_rrset: Cannot copy RRSet.\n");
+ return ret;
+ }
+ if (rrset_copy->rrsigs != NULL) {
+ knot_rrset_deep_free(&rrset_copy->rrsigs, 1, 1, 1);
+ }
+ assert(knot_rrset_rrsigs(rrset_copy) == NULL);
+
+ ret = knot_changeset_add_new_rr(changeset, rrset_copy,
+ XFRIN_CHANGESET_REMOVE);
+ if (ret != KNOT_EOK) {
+ /* We have to free the copy now. */
+ knot_rrset_deep_free(&rrset_copy, 1, 1, 1);
+ dbg_zonediff("zone_diff: remove_rrset: Could not remove RRSet. "
+ "Reason: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+
+ return KNOT_EOK;
+}
+
+static int knot_zone_diff_add_node(const knot_node_t *node,
+ knot_changeset_t *changeset)
+{
+ if (node == NULL || changeset == NULL) {
+ dbg_zonediff("zone_diff: add_node: NULL arguments.\n");
+ return KNOT_EBADARG;
+ }
+
+ /* Add all rrsets from node. */
+ const knot_rrset_t **rrsets = knot_node_rrsets(node);
+ if (rrsets == NULL) {
+ /* Empty non-terminals - legal case. */
+ dbg_zonediff_detail("zone_diff: Node has no RRSets.\n");
+ return KNOT_EOK;
+ }
+
+ for (uint i = 0; i < knot_node_rrset_count(node); i++) {
+ assert(rrsets[i]);
+ int ret = knot_zone_diff_changeset_add_rrset(changeset,
+ rrsets[i]);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: add_node: Cannot add RRSet (%s).\n",
+ knot_strerror(ret));
+ free(rrsets);
+ return ret;
+ }
+ }
+
+ free(rrsets);
+
+ return KNOT_EOK;
+}
+
+static int knot_zone_diff_remove_node(knot_changeset_t *changeset,
+ const knot_node_t *node)
+{
+ if (changeset == NULL || node == NULL) {
+ dbg_zonediff("zone_diff: remove_node: NULL parameters.\n");
+ return KNOT_EBADARG;
+ }
+
+ dbg_zonediff("zone_diff: remove_node: Removing node:\n");
+dbg_zonediff_exec_detail(
+ knot_node_dump((knot_node_t *)node, 1);
+);
+
+ const knot_rrset_t **rrsets = knot_node_rrsets(node);
+ if (rrsets == NULL) {
+ dbg_zonediff_verb("zone_diff: remove_node: "
+ "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));
+
+ /* Remove all the RRSets of the node. */
+ for (uint i = 0; i < knot_node_rrset_count(node); i++) {
+ int ret = knot_zone_diff_changeset_remove_rrset(changeset,
+ rrsets[i]);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: remove_node: Failed to "
+ "remove rrset. Error: %s\n",
+ knot_strerror(ret));
+ free(rrsets);
+ return ret;
+ }
+ }
+
+ free(rrsets);
+
+ return KNOT_EOK;
+}
+
+static int knot_zone_diff_rdata_return_changes(const knot_rrset_t *rrset1,
+ const knot_rrset_t *rrset2,
+ knot_rrset_t **changes)
+{
+ if (rrset1 == NULL || rrset2 == NULL) {
+ dbg_zonediff("zone_diff: diff_rdata: NULL arguments. (%p) (%p).\n",
+ rrset1, rrset2);
+ return KNOT_EBADARG;
+ }
+
+ /*
+ * 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
+ * particular RR has changed.
+ * 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. "
+ "RR count 1=%d RR count 2=%d.\n",
+ knot_dname_to_str(rrset1->owner),
+ knot_rrtype_to_string(rrset1->type),
+ knot_rrset_rdata_rr_count(rrset1),
+ knot_rrset_rdata_rr_count(rrset2));
+
+ /* Create fake RRSet, it will be easier to handle. */
+ *changes = knot_rrset_new(knot_rrset_get_owner(rrset1),
+ knot_rrset_type(rrset1),
+ knot_rrset_class(rrset1),
+ knot_rrset_ttl(rrset1));
+ if (*changes == NULL) {
+ dbg_zonediff("zone_diff: diff_rdata: "
+ "Could not create RRSet with changes.\n");
+ return KNOT_ENOMEM;
+ }
+
+ knot_rrtype_descriptor_t *desc =
+ knot_rrtype_descriptor_by_type(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.
+ */
+ dbg_zonediff("zone_diff: diff_rdata: "
+ "No match for RR (type=%s owner=%s).\n",
+ knot_rrtype_to_string(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. */
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_rdata: "
+ "Could not add rdata to rrset.");
+ knot_rrset_deep_free(changes, 1, 1, 0);
+ return ret;
+ }
+ } else {
+ dbg_zonediff_detail("zone_diff: diff_rdata: "
+ "Found matching RR for type %s.\n",
+ knot_rrtype_to_string(rrset1->type));
+ }
+ tmp_rdata = knot_rrset_rdata_next(rrset1, tmp_rdata);
+ }
+ return KNOT_EOK;
+}
+
+static int knot_zone_diff_rdata(const knot_rrset_t *rrset1,
+ const knot_rrset_t *rrset2,
+ knot_changeset_t *changeset)
+{
+ if ((changeset == NULL) || (rrset1 == NULL && rrset2 == NULL)) {
+ dbg_zonediff("zone_diff: diff_rdata: NULL arguments.\n");
+ return KNOT_EBADARG;
+ }
+ /*
+ * The easiest solution is to remove all the RRs that had no match and
+ * to add all RRs that had no match, but those from second RRSet. */
+
+ /* Get RRs to remove from zone. */
+ knot_rrset_t *to_remove = NULL;
+ if (rrset1 != NULL && rrset2 == NULL) {
+ assert(rrset1->type == KNOT_RRTYPE_RRSIG);
+ dbg_zonediff_detail("zone_diff: diff_rdata: RRSIG will be "
+ "removed.\n");
+ int ret = knot_rrset_deep_copy(rrset1, &to_remove, 1);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_rdata: Could not copy rrset. "
+ "Error: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ } else if (rrset1 != NULL && rrset2 != NULL) {
+ int ret = knot_zone_diff_rdata_return_changes(rrset1, rrset2,
+ &to_remove);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_rdata: Could not get changes. "
+ "Error: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ } else {
+ 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);
+
+ int ret = knot_zone_diff_changeset_remove_rrset(changeset,
+ to_remove);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&to_remove, 1, 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);
+
+ /* Get RRs to add to zone. */
+ knot_rrset_t *to_add = NULL;
+ if (rrset2 != NULL && rrset1 == NULL) {
+ assert(rrset2->type == KNOT_RRTYPE_RRSIG);
+ dbg_zonediff_detail("zone_diff: diff_rdata: RRSIG will be "
+ "added.\n");
+ int ret = knot_rrset_deep_copy(rrset2, &to_add, 1);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_rdata: Could not copy rrset. "
+ "Error: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ } else if (rrset1 != NULL && rrset2 != NULL) {
+ ret = knot_zone_diff_rdata_return_changes(rrset2, rrset1,
+ &to_add);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_rdata: Could not get changes. "
+ "Error: %s.\n", knot_strerror(ret));
+ return ret;
+ }
+ } else {
+ 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);
+
+ ret = knot_zone_diff_changeset_add_rrset(changeset,
+ to_add);
+ if (ret != KNOT_EOK) {
+ knot_rrset_deep_free(&to_add, 1, 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_add, 1, 1, 1);
+
+ return KNOT_EOK;
+}
+
+static int knot_zone_diff_rrsets(const knot_rrset_t *rrset1,
+ const knot_rrset_t *rrset2,
+ knot_changeset_t *changeset)
+{
+// if (rrset1 == NULL || rrset2 == NULL) {
+// /* This could happen when diffing RRSIGs. */
+// if (rrset1 == NULL && rrset2 != NULL) {
+// dbg_zonediff("zone_diff: diff_rrsets: RRSIG missing in first"
+// " rrset1.\n");
+// int ret =
+// knot_zone_diff_changeset_add_rrset(changeset,
+// rrset2);
+// if (ret != KNOT_EOK) {
+// dbg_zonediff("zone_diff: diff_rrsets: "
+// "Cannot add RRSIG. (%s)\n",
+// knot_strerror(ret));
+// }
+// } else if (rrset1 != NULL && rrset2 == NULL) {
+// dbg_zonediff("zone_diff: diff_rrsets: RRSIG missing in second"
+// " rrset1.\n");
+// int ret =
+// knot_zone_diff_changeset_remove_rrset(changeset,
+// rrset1);
+// if (ret != KNOT_EOK) {
+// dbg_zonediff("zone_diff: diff_rrsets: "
+// "Cannot remove RRSIG. (%s)\n",
+// knot_strerror(ret));
+// }
+// }
+// dbg_zonediff_detail("zone_diff: diff_rrsets: "
+// "NULL arguments (RRSIGs?). (%p) (%p)\n",
+// rrset1, rrset2);
+// return KNOT_EOK;
+// }
+
+ 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));
+ }
+
+ /* RRs (=rdata) have to be cross-compared, unfortunalely. */
+ return knot_zone_diff_rdata(rrset1, rrset2, changeset);
+}
+
+/*!< \todo this could be generic function for adding / removing. */
+static void knot_zone_diff_node(knot_node_t *node, void *data)
+{
+ if (node == NULL || data == NULL) {
+ dbg_zonediff("zone_diff: diff_node: NULL arguments.\n");
+ return;
+ }
+
+ struct zone_diff_param *param = (struct zone_diff_param *)data;
+ if (param->changeset == NULL || param->contents == NULL) {
+ dbg_zonediff("zone_diff: diff_node: NULL arguments.\n");
+ param->ret = KNOT_EBADARG;
+ return;
+ }
+
+ if (param->ret != KNOT_EOK) {
+ /* Error occured before, no point in continuing. */
+ dbg_zonediff_detail("zone_diff: diff_node: error: %s\n",
+ knot_strerror(param->ret));
+ return;
+ }
+
+ /*
+ * First, we have to search the second tree to see if there's according
+ * node, if not, the whole node has been removed.
+ */
+ const knot_node_t *node_in_second_tree = NULL;
+ const knot_dname_t *node_owner = knot_node_owner(node);
+ assert(node_owner);
+ if (!param->nsec3) {
+ node_in_second_tree =
+ knot_zone_contents_find_node(param->contents,
+ node_owner);
+ } else {
+ dbg_zonediff_verb("zone_diff: diff_node: NSEC3 zone.\n");
+ node_in_second_tree =
+ knot_zone_contents_find_nsec3_node(param->contents,
+ node_owner);
+ }
+
+ if (node_in_second_tree == NULL) {
+ dbg_zonediff_detail("zone_diff: diff_node: Node %s is not "
+ "in the second tree.\n",
+ knot_dname_to_str(node_owner));
+ int ret = knot_zone_diff_remove_node(param->changeset,
+ node);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: failed to remove node.\n");
+ param->ret = ret;
+ return;
+ }
+ param->ret = KNOT_EOK;
+ return;
+ }
+
+ assert(node_in_second_tree != node);
+
+ dbg_zonediff_detail("zone_diff: diff_node: Node %s is present in "
+ "both trees.\n", knot_dname_to_str(node_owner));
+ /* The nodes are in both trees, we have to diff each RRSet. */
+ const knot_rrset_t **rrsets = knot_node_rrsets(node);
+ 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
+ * in the second tree will have to be inserted to ADD section.
+ */
+ int ret = knot_zone_diff_add_node(node_in_second_tree,
+ param->changeset);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_node: "
+ "Could not add node from second tree. "
+ "Reason: %s.\n", knot_strerror(ret));
+ }
+ param->ret = ret;
+ return;
+ }
+
+ for (uint i = 0; i < knot_node_rrset_count(node); i++) {
+ /* 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)));
+ /* RRSet has been removed. Make a copy and remove. */
+ assert(rrset);
+ int ret = knot_zone_diff_changeset_remove_rrset(
+ param->changeset,
+ rrset);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_node: "
+ "Failed to remove RRSet.\n");
+ param->ret = ret;
+ free(rrsets);
+ return;
+ }
+ } 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)));
+ /* Diff RRSets. */
+ int ret = knot_zone_diff_rrsets(rrset,
+ rrset_from_second_node,
+ param->changeset);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: "
+ "Failed to diff RRSets.\n");
+ param->ret = ret;
+ 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. */
+// ret = knot_zone_diff_rrsets(rrset->rrsigs,
+// rrset_from_second_node->rrsigs,
+// param->changeset);
+// if (ret != KNOT_EOK) {
+// dbg_zonediff("zone_diff: "
+// "Failed to diff RRSIGs.\n");
+// param->ret = ret;
+// return;
+// }
+ }
+ }
+
+ 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
+ * tree is empty non-terminal and as such has no RRs.
+ * Whole node from the first tree has to be removed.
+ */
+ // TODO following code creates duplicated RR in diff.
+ // IHMO such case should be handled here
+// int ret = knot_zone_diff_remove_node(param->changeset,
+// node);
+// if (ret != KNOT_EOK) {
+// dbg_zonediff("zone_diff: diff_node: "
+// "Cannot remove node. Reason: %s.\n",
+// knot_strerror(ret));
+// }
+ param->ret = KNOT_EOK;
+ return;
+ }
+
+ for (uint i = 0; i < knot_node_rrset_count(node_in_second_tree); i++) {
+ /* 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)));
+ /* RRSet has been added. Make a copy and add. */
+ assert(rrset);
+ int ret = knot_zone_diff_changeset_add_rrset(
+ param->changeset,
+ rrset);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: diff_node: "
+ "Failed to add RRSet.\n");
+ param->ret = ret;
+ free(rrsets);
+ return;
+ }
+ } else {
+ /* Already handled. */
+ ;
+ }
+ }
+
+ free(rrsets);
+
+ assert(param->ret == KNOT_EOK);
+}
+
+/*!< \todo possibly not needed! */
+static void knot_zone_diff_add_new_nodes(knot_node_t *node, void *data)
+{
+ assert(node);
+ if (node == NULL || data == NULL) {
+ dbg_zonediff("zone_diff: add_new_nodes: NULL arguments.\n");
+ return;
+ }
+
+ struct zone_diff_param *param = (struct zone_diff_param *)data;
+ if (param->changeset == NULL || param->contents == NULL) {
+ dbg_zonediff("zone_diff: add_new_nodes: NULL arguments.\n");
+ param->ret = KNOT_EBADARG;
+ return;
+ }
+
+ if (param->ret != KNOT_EOK) {
+ /* Error occured before, no point in continuing. */
+ dbg_zonediff_detail("zone_diff: add_new_nodes: error: %s\n",
+ 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
+ * already handled.
+ */
+ 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);
+ } else {
+ 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);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: add_new_nodes: Cannot add "
+ "node: %s to changeset. Reason: %s.\n",
+ knot_dname_to_str(node->owner),
+ knot_strerror(ret));
+ }
+ }
+
+ assert(param->ret == KNOT_EOK);
+}
+
+int knot_zone_contents_diff(const knot_zone_contents_t *zone1,
+ const knot_zone_contents_t *zone2,
+ knot_changeset_t *changeset)
+{
+ if (zone1 == NULL || zone2 == NULL) {
+ dbg_zonediff("zone_diff: NULL argument(s).\n");
+ return KNOT_EBADARG;
+ }
+
+// /* Create changeset structure. */
+// *changeset = malloc(sizeof(knot_changeset_t));
+// if (*changeset == NULL) {
+// ERR_ALLOC_FAILED;
+// return KNOT_ENOMEM;
+// }
+ memset(changeset, 0, sizeof(knot_changeset_t));
+
+ /* Settle SOAs first. */
+ int ret = knot_zone_diff_load_soas(zone1, zone2, changeset);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: loas_SOAs failed with error: %s\n",
+ 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;
+ param.nsec3 = 0;
+ param.changeset = changeset;
+ param.ret = KNOT_EOK;
+ ret = knot_zone_contents_tree_apply_inorder(
+ (knot_zone_contents_t *)zone1,
+ knot_zone_diff_node,
+ &param);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: Tree traversal failed "
+ "with error: %s. Error from inner function: %s\n",
+ knot_strerror(ret),
+ knot_strerror(param.ret));
+ return ret;
+ }
+
+ /* Do the same for NSEC3 nodes. */
+ param.nsec3 = 1;
+ ret = knot_zone_contents_nsec3_apply_inorder((knot_zone_contents_t *)zone1, knot_zone_diff_node,
+ &param);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: Tree traversal failed "
+ "with error: %s\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+ /*
+ * Some nodes may have been added. The code above will not notice,
+ * we have to go through the second tree and add missing nodes to
+ * changeset.
+ */
+ param.nsec3 = 0;
+ param.contents = zone1;
+ ret = knot_zone_contents_tree_apply_inorder((knot_zone_contents_t *)zone2,
+ knot_zone_diff_add_new_nodes,
+ &param);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: Tree traversal failed "
+ "with error: %s. Error from inner function: %s\n",
+ knot_strerror(ret),
+ knot_strerror(param.ret));
+ return ret;
+ }
+
+ /* NSEC3 nodes. */
+ param.nsec3 = 1;
+ param.contents = zone1;
+ ret = knot_zone_contents_nsec3_apply_inorder((knot_zone_contents_t *)zone2,
+ knot_zone_diff_add_new_nodes,
+ &param);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: Tree traversal failed "
+ "with error: %s\n",
+ knot_strerror(ret));
+ return ret;
+ }
+
+ return KNOT_EOK;
+}
+
+#ifdef KNOT_ZONEDIFF_DEBUG
+#ifdef DEBUG_ENABLE_DETAILS
+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);
+ dbg_zonediff_detail("\n");
+ dbg_zonediff_detail("Changeset TO: %d\n", ch->serial_to);
+ rrset_dump_text(ch->soa_to, stderr);
+ 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("ADD section:\n");
+ dbg_zonediff_detail("**********************************************\n");
+ for (int i = 0; i < ch->add_count; i++) {
+ rrset_dump_text(ch->add[i], stderr);
+ 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);
+ dbg_zonediff_detail("\n");
+ }
+}
+#endif
+#endif
+
+int knot_zone_diff_create_changesets(const knot_zone_contents_t *z1,
+ const knot_zone_contents_t *z2,
+ knot_changesets_t **changesets)
+{
+ if (z1 == NULL || z2 == NULL) {
+ dbg_zonediff("zone_diff: create_changesets: NULL arguments.\n");
+ return KNOT_EBADARG;
+ }
+ /* Create changesets. */
+ int ret = knot_changeset_allocate(changesets);
+ if (ret != KNOT_EOK) {
+ dbg_zonediff("zone_diff: create_changesets: "
+ "Could not allocate changesets."
+ "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: "
+ "Could not diff zones. "
+ "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/tests/common/da_tests.h b/src/libknot/zone/zone-diff.h
index d51b7be..6e0eb1d 100644..100755
--- a/src/tests/common/da_tests.h
+++ b/src/libknot/zone/zone-diff.h
@@ -14,12 +14,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _KNOTD_DA_TESTS_H_
-#define _KNOTD_DA_TESTS_H_
+#ifndef _KNOT_ZONE_DIFF_H_
+#define _KNOT_ZONE_DIFF_H_
-#include "common/libtap/tap_unit.h"
+#include "libknot/zone/zone-contents.h"
+#include "libknot/updates/changesets.h"
-/* Unit API. */
-unit_api da_tests_api;
+/*! \brief zone1 -> zone2 */
+int knot_zone_diff_create_changesets(const knot_zone_contents_t *z1,
+ const knot_zone_contents_t *z2,
+ knot_changesets_t **changesets);
-#endif /* _KNOTD_DA_TESTS_H_ */
+#endif // _KNOT_ZONE_DIFF_H_
diff --git a/src/libknot/zone/zone-tree.c b/src/libknot/zone/zone-tree.c
index 2b79f86..7de460a 100644..100755
--- a/src/libknot/zone/zone-tree.c
+++ b/src/libknot/zone/zone-tree.c
@@ -110,7 +110,7 @@ static void knot_zone_tree_free_node(knot_zone_tree_node_t *node,
knot_zone_tree_free_node(node->avl.avl_right, free_data);
if (free_data) {
- knot_node_free(&node->node, 0);
+ knot_node_free(&node->node);
}
free(node);
@@ -132,8 +132,7 @@ static int knot_zone_tree_deep_copy_node(knot_zone_tree_node_t *from,
}
int ret = knot_node_shallow_copy(from->node, &(*to)->node);
-// printf("Copied node: %p to node %p. New node1: %p, new node 2: %p\n",
-// from->node, (*to)->node, from->node->new_node, (*to)->node->new_node);
+
if (ret != KNOT_EOK) {
dbg_zone_verb("Failed to do shallow copy of node.\n");
free(*to);
@@ -155,7 +154,7 @@ static int knot_zone_tree_deep_copy_node(knot_zone_tree_node_t *from,
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, 0);
+ knot_node_free(&(*to)->node);
free(*to);
*to = NULL;
return ret;
@@ -250,7 +249,7 @@ int knot_zone_tree_get(knot_zone_tree_t *tree, const knot_dname_t *owner,
knot_zone_tree_node_t *n = TREE_FIND(tree, knot_zone_tree_node, avl,
tmp);
- knot_node_free(&tmp_data, 0);
+ knot_node_free(&tmp_data);
free(tmp);
if (n != NULL) {
@@ -313,7 +312,7 @@ int knot_zone_tree_get_less_or_equal(knot_zone_tree_t *tree,
int exact_match = TREE_FIND_LESS_EQUAL(
tree, knot_zone_tree_node, avl, tmp, &f, &prev);
- knot_node_free(&tmp_data, 0);
+ knot_node_free(&tmp_data);
free(tmp);
*found = (exact_match > 0) ? f->node : NULL;
@@ -356,9 +355,17 @@ dbg_zone_exec_detail(
/*! \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);
@@ -399,11 +406,9 @@ int knot_zone_tree_remove(knot_zone_tree_t *tree,
/*! \todo How to know if this was successful? */
TREE_REMOVE(tree, knot_zone_tree_node, avl, tmp);
- knot_node_free(&tmp_data, 0);
+ knot_node_free(&tmp_data);
free(tmp);
-// *removed = (n) ? n->node : NULL;
-// free(n);
*removed = n;
return KNOT_EOK;
diff --git a/src/libknot/zone/zone-tree.h b/src/libknot/zone/zone-tree.h
index ca65fe6..95b4e23 100644..100755
--- a/src/libknot/zone/zone-tree.h
+++ b/src/libknot/zone/zone-tree.h
@@ -39,8 +39,6 @@ typedef struct knot_zone_tree_node {
TREE_ENTRY(knot_zone_tree_node) avl;
/*! \brief Zone tree data. */
knot_node_t *node;
- /*! \brief Owner of the node. */
-// knot_dname_t *owner;
} knot_zone_tree_node_t;
/*----------------------------------------------------------------------------*/
diff --git a/src/libknot/zone/zone.c b/src/libknot/zone/zone.c
index 122b014..65f810d 100644..100755
--- a/src/libknot/zone/zone.c
+++ b/src/libknot/zone/zone.c
@@ -33,6 +33,12 @@
#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);
+}
+
/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -55,6 +61,13 @@ 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;
}
@@ -133,14 +146,18 @@ void knot_zone_set_version(knot_zone_t *zone, time_t version)
short knot_zone_is_master(const knot_zone_t *zone)
{
- return zone->master;
+ return zone->flags & KNOT_ZONE_MASTER;
}
/*----------------------------------------------------------------------------*/
void knot_zone_set_master(knot_zone_t *zone, short master)
{
- zone->master = master;
+ if (master) {
+ zone->flags |= KNOT_ZONE_MASTER;
+ } else {
+ zone->flags &= ~KNOT_ZONE_MASTER;
+ }
}
/*----------------------------------------------------------------------------*/
@@ -175,6 +192,7 @@ knot_zone_contents_t *knot_zone_switch_contents(knot_zone_t *zone,
knot_zone_contents_t *old_contents =
rcu_xchg_pointer(&zone->contents, new_contents);
+
return old_contents;
}
@@ -192,7 +210,7 @@ void knot_zone_free(knot_zone_t **zone)
&& !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 "
- "update.\n");
+ "update.\n");
}
knot_dname_release((*zone)->name);
@@ -221,7 +239,7 @@ void knot_zone_deep_free(knot_zone_t **zone, int destroy_dname_table)
&& !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 "
- "update.\n");
+ "update.\n");
}
dbg_zone_exec(
@@ -241,3 +259,21 @@ dbg_zone_exec(
free(*zone);
*zone = NULL;
}
+
+void knot_zone_set_dtor(knot_zone_t *zone, int (*dtor)(struct knot_zone *))
+{
+ if (zone != NULL) {
+ zone->dtor = dtor;
+ }
+}
+
+void knot_zone_set_flag(knot_zone_t *zone, knot_zone_flag_t flag, unsigned on)
+{
+ if (zone != NULL) {
+ if (on) {
+ zone->flags |= flag;
+ } else {
+ zone->flags &= ~flag;
+ }
+ }
+}
diff --git a/src/libknot/zone/zone.h b/src/libknot/zone/zone.h
index 331ef1f..31ff2ac 100644..100755
--- a/src/libknot/zone/zone.h
+++ b/src/libknot/zone/zone.h
@@ -34,6 +34,7 @@
#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"
@@ -41,11 +42,6 @@
#include "zone/zone-contents.h"
/*----------------------------------------------------------------------------*/
-
-//typedef TREE_HEAD(avl_tree, knot_node) avl_tree_t;
-//struct event_t;
-
-/*----------------------------------------------------------------------------*/
/*!
* \brief Return values for search functions.
*
@@ -58,6 +54,15 @@ enum knot_zone_retvals {
typedef enum knot_zone_retvals knot_zone_retvals_t;
+/*!
+ * \brief Zone flags.
+ */
+typedef enum knot_zone_flag_t {
+ KNOT_ZONE_SLAVE = 0 << 0, /*! Slave zone */
+ KNOT_ZONE_MASTER = 1 << 0, /*! Master zone. */
+ KNOT_ZONE_DISCARDED = 1 << 1 /*! Zone waiting to be discarded. */
+} knot_zone_flag_t;
+
/*----------------------------------------------------------------------------*/
/*!
@@ -68,14 +73,14 @@ typedef enum knot_zone_retvals knot_zone_retvals_t;
* double-free errors when destroying the zone.
*/
struct knot_zone {
+ ref_t ref; /*!< Reference counting. */
knot_dname_t *name;
knot_zone_contents_t *contents;
time_t version;
- /*! \todo Set when loading zone. */
- short master;
+ unsigned flags;
void *data; /*!< Pointer to generic zone-related data. */
int (*dtor)(struct knot_zone *); /*!< Data destructor. */
@@ -88,7 +93,7 @@ typedef struct knot_zone knot_zone_t;
/*!
* \brief Creates new empty DNS zone.
*
- * \notice Zone will be created without contents.
+ * \note Zone will be created without contents.
*
* \param name Zone owner.
*
@@ -152,6 +157,54 @@ void knot_zone_free(knot_zone_t **zone);
*/
void knot_zone_deep_free(knot_zone_t **zone, int destroy_dname_table);
+/*!
+ * \brief Set destructor and initialize reference counter to 1.
+ *
+ * \param zone Related zone.
+ * \param dtor Destructor.
+ */
+void knot_zone_set_dtor(knot_zone_t *zone, int (*dtor)(struct knot_zone *));
+
+/*!
+ * \brief Increment reference counter for dname.
+ *
+ * \param zone Referenced zone.
+ */
+ static inline void knot_zone_retain(knot_zone_t *zone) {
+ if (zone != NULL) {
+ ref_retain(&zone->ref);
+ }
+}
+
+/*!
+ * \brief Decrement reference counter for dname.
+ *
+ * \param zone Referenced zone.
+ */
+ static inline void knot_zone_release(knot_zone_t *zone) {
+ if (zone != NULL) {
+ ref_release(&zone->ref);
+ }
+}
+
+/*!
+ * \brief Return zone flags.
+ *
+ * \param zone Zone.
+ */
+static inline unsigned knot_zone_flags(knot_zone_t *zone) {
+ return zone->flags;
+}
+
+/*!
+ * \brief Set zone flag.
+ *
+ * \param zone Zone.
+ * \param flag Respected flag.
+ * \param on 1 to set, 0 to unset flag.
+ */
+void knot_zone_set_flag(knot_zone_t *zone, knot_zone_flag_t flag, unsigned on);
+
#endif
/*! @} */
diff --git a/src/libknot/zone/zonedb.c b/src/libknot/zone/zonedb.c
index a9b6545..43b4489 100644..100755
--- a/src/libknot/zone/zonedb.c
+++ b/src/libknot/zone/zonedb.c
@@ -51,11 +51,11 @@ static int knot_zonedb_compare_zone_names(void *p1, void *p2)
int ret = knot_dname_compare(zone1->name, zone2->name);
-dbg_zonedb_exec(
+dbg_zonedb_exec_detail(
char *name1 = knot_dname_to_str(zone1->name);
char *name2 = knot_dname_to_str(zone2->name);
- dbg_zonedb("Compared names %s and %s, result: %d.\n",
- name1, name2, ret);
+ dbg_zonedb_detail("Compared names %s and %s, result: %d.\n",
+ name1, name2, ret);
free(name1);
free(name2);
);
@@ -64,23 +64,6 @@ dbg_zonedb_exec(
}
/*----------------------------------------------------------------------------*/
-
-//static int knot_zonedb_replace_zone_in_list(void **list_item, void **new_zone)
-//{
-// assert(list_item != NULL);
-// assert(*list_item != NULL);
-// assert(new_zone != NULL);
-// assert(*new_zone != NULL);
-
-// dbg_zonedb("Replacing list item %p with new zone %p\n",
-// *list_item, *new_zone);
-
-// *list_item = *new_zone;
-
-// return 0;
-//}
-
-/*----------------------------------------------------------------------------*/
/* API functions */
/*----------------------------------------------------------------------------*/
@@ -152,63 +135,13 @@ knot_zone_t *knot_zonedb_remove_zone(knot_zonedb_t *db,
// remove the zone from the skip list, but do not destroy it
gen_tree_remove(db->zone_tree, &dummy_zone);
-// if (destroy_zone) {
-// // properly destroy the zone and all its contents
-// knot_zone_deep_free(&z, 0);
-// }
-
db->zone_count--;
- //return KNOT_EOK;
return z;
}
/*----------------------------------------------------------------------------*/
-//knot_zone_t *knot_zonedb_replace_zone(knot_zonedb_t *db,
-// knot_zone_t *zone)
-//{
-// knot_zone_t *z = knot_zonedb_find_zone(db,
-// knot_node_owner(knot_zone_apex(zone)));
-// if (z == NULL) {
-// return NULL;
-// }
-
-// /*! \todo The replace should be atomic!!! */
-
-// dbg_zonedb("Found zone: %p\n", z);
-
-// int ret = skip_remove(db->zones,
-// (void *)knot_node_owner(knot_zone_apex(zone)),
-// NULL, NULL);
-// if (ret != 0) {
-// return NULL;
-// }
-
-// dbg_zonedb("Removed zone, return value: %d\n", ret);
-// dbg_zonedb("Old zone: %p\n", z);
-
-// ret = skip_insert(db->zones,
-// (void *)knot_node_owner(knot_zone_apex(zone)),
-// (void *)zone, NULL);
-
-// dbg_zonedb("Inserted zone, return value: %d\n", ret);
-
-// if (ret != 0) {
-// // return the removed zone back
-// skip_insert(db->zones,
-// (void *)knot_node_owner(knot_zone_apex(z)),
-// (void *)z, NULL);
-// /*! \todo There may be problems and the zone may remain
-// removed. */
-// return NULL;
-// }
-
-// return z;
-//}
-
-/*----------------------------------------------------------------------------*/
-
knot_zone_t *knot_zonedb_find_zone(const knot_zonedb_t *db,
const knot_dname_t *zone_name)
{
@@ -229,11 +162,7 @@ const knot_zone_t *knot_zonedb_find_zone_for_name(knot_zonedb_t *db,
knot_zone_t dummy_zone;
dummy_zone.name = knot_dname_deep_copy(dname);
void *found = NULL;
-
-// int exact_match = gen_tree_find_less_or_equal(db->zone_tree,
-// &dummy_zone,
-// &found);
-// UNUSED(exact_match);
+
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);
@@ -351,54 +280,16 @@ static void delete_zone_from_db(void *node, void *data)
knot_zone_t *zone = (knot_zone_t *)node;
assert(zone);
synchronize_rcu();
- knot_zone_deep_free(&zone, 0);
+ knot_zone_set_flag(zone, KNOT_ZONE_DISCARDED, 1);
+ knot_zone_release(zone);
+ zone = NULL;
}
void knot_zonedb_deep_free(knot_zonedb_t **db)
{
dbg_zonedb("Deleting zone db (%p).\n", *db);
-// dbg_zonedb("Is it empty (%p)? %s\n",
-// (*db)->zones, skip_is_empty((*db)->zones) ? "yes" : "no");
-
-//dbg_zonedb_exec(
-// int i = 1;
-// char *name = NULL;
-// while (zn != NULL) {
-// dbg_zonedb("%d. zone: %p, key: %p\n", i, zn->value,
-// zn->key);
-// assert(zn->key == ((knot_zone_t *)zn->value)->apex->owner);
-// name = knot_dname_to_str((knot_dname_t *)zn->key);
-// dbg_zonedb(" zone name: %s\n", name);
-// free(name);
-
-// zn = skip_next(zn);
-// }
-
-// zn = skip_first((*db)->zones);
-//);
-
-// while (zn != NULL) {
-// zone = (knot_zone_t *)zn->value;
-// assert(zone != NULL);
-
-// // remove the zone from the database
-// skip_remove((*db)->zones, zn->key, NULL, NULL);
-// // wait for all readers to finish
-// synchronize_rcu;
-// // destroy the zone
-// knot_zone_deep_free(&zone, 0);
-
-// zn = skip_first((*db)->zones);
-// }
-
-// assert(skip_is_empty((*db)->zones));
-
-// skip_destroy_list(&(*db)->zones, NULL, NULL);
gen_tree_destroy(&((*db)->zone_tree), delete_zone_from_db, NULL);
assert((*db)->zone_tree == NULL);
free(*db);
*db = NULL;
}
-
-/*----------------------------------------------------------------------------*/
-
diff --git a/src/libknot/zone/zonedb.h b/src/libknot/zone/zonedb.h
index d5a4992..81326bf 100644..100755
--- a/src/libknot/zone/zonedb.h
+++ b/src/libknot/zone/zonedb.h
@@ -85,9 +85,6 @@ int knot_zonedb_add_zone(knot_zonedb_t *db, knot_zone_t *zone);
knot_zone_t * knot_zonedb_remove_zone(knot_zonedb_t *db,
const knot_dname_t *zone_name);
-//knot_zone_t *knot_zonedb_replace_zone(knot_zonedb_t *db,
-// knot_zone_t *zone);
-
/*!
* \brief Finds zone exactly matching the given zone name.
*
diff --git a/src/tests/README b/src/tests/README
index 2f299ad..2f299ad 100644..100755
--- a/src/tests/README
+++ b/src/tests/README
diff --git a/src/tests/common/acl_tests.c b/src/tests/common/acl_tests.c
index c1884cd..c1884cd 100644..100755
--- a/src/tests/common/acl_tests.c
+++ b/src/tests/common/acl_tests.c
diff --git a/src/tests/common/acl_tests.h b/src/tests/common/acl_tests.h
index a928e2d..a928e2d 100644..100755
--- a/src/tests/common/acl_tests.h
+++ b/src/tests/common/acl_tests.h
diff --git a/src/tests/common/da_tests.c b/src/tests/common/da_tests.c
deleted file mode 100644
index 627e8aa..0000000
--- a/src/tests/common/da_tests.c
+++ /dev/null
@@ -1,330 +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/common/da_tests.h"
-#include "common/dynamic-array.h"
-#include <unistd.h>
-#include <urcu.h>
-
-static int da_tests_count(int argc, char *argv[]);
-static int da_tests_run(int argc, char *argv[]);
-
-/*
- * Unit API.
- */
-unit_api da_tests_api = {
- "Dynamic array",
- &da_tests_count,
- &da_tests_run
-};
-
-/*
- * Unit implementation.
- */
-
-static const int DA_TEST_COUNT = 5;
-static const int RCU_THREADS = 3;
-static const int DA_FRAGMENT = 10;
-static const int DA_DEF_SIZE = 1000;
-static const int DA_OPERATIONS = 1000;
-enum Operations {
- DA_RESERVE = 0,
- DA_OCCUPY = 1,
- DA_RELEASE = 2,
- DA_OPCOUNT = 3
-};
-
-static int da_tests_count(int argc, char *argv[])
-{
- return DA_TEST_COUNT;
-}
-
-static void do_something(int loops)
-{
- int i;
- int res = 1;
-
- static const int LOOPS = 10000;
-
- for (int j = 1; j <= LOOPS; ++j) {
- for (i = 1; i <= loops; ++i) {
- res *= i;
- }
- }
-}
-
-static void *test_rcu_routine(void *obj)
-{
- rcu_register_thread();
- rcu_read_lock();
-
- do_something(1000);
-
- rcu_read_unlock();
- rcu_unregister_thread();
-
- return NULL;
-}
-
-static int test_rcu_threads()
-{
- // Create threads
- pthread_t *threads = malloc(RCU_THREADS * sizeof(pthread_t));
- for (int i = 0; i < RCU_THREADS; ++i) {
- if (pthread_create(&threads[i], NULL, test_rcu_routine, NULL)) {
- diag("rcu: failed to create thread %d", i);
- free(threads);
- return 0;
- }
- }
-
- // Join threads
- void *pret = NULL;
- for (int i = 0; i < RCU_THREADS; ++i) {
- if (pthread_join(threads[i], &pret)) {
- diag("rcu: failed to join thread %d", i);
- free(threads);
- return 0;
- }
- }
-
- synchronize_rcu();
- free(threads);
-
- return 1;
-}
-
-static int test_da_init(da_array_t *arr)
-{
- return da_initialize(arr, DA_DEF_SIZE, sizeof(uint)) == 0;
-}
-
-static int test_da_random_op(da_array_t *arr)
-{
- unsigned seed = (unsigned)time(0);
- uint allocated = DA_DEF_SIZE;
- uint size = 0;
-
- for (int i = 0; i < DA_OPERATIONS; ++i) {
- int r = rand_r(&seed) % DA_OPCOUNT;
- int count = rand_r(&seed) % DA_FRAGMENT + 1;
-
- switch (r) {
-
- // Perform reserve operation
- case DA_RESERVE:
- if (da_reserve(arr, count) >= 0 &&
- size <= allocated) {
- if ((allocated - size) < count) {
- allocated *= 2;
- }
- } else {
- diag("dynamic-array: da_reserve(%p, %d) failed"
- " (size %d, alloc'd %d)",
- arr, count, size, allocated);
- return 0;
- }
- break;
-
- // Perform occupy operation
- case DA_OCCUPY:
- if (da_occupy(arr, count) == 0) {
- uint *items = (uint *) da_get_items(arr);
- for (int j = 0; j < da_get_count(arr); ++j) {
- items[j] = rand_r(&seed);
- }
- if (size <= allocated &&
- (allocated - size) >= count) {
- size += count;
- } else {
- return 0;
- }
- } else {
- diag("dynamic-array: da_occupy(%p, %d) failed"
- " (size %d, alloc'd %d)",
- arr, count, size, allocated);
- return 0;
- }
- break;
-
- // Perform release operation
- case DA_RELEASE:
- if (arr->count > 0) {
- count = (rand_r(&seed) % DA_FRAGMENT) % arr->count;
- da_release(arr, count);
-
- if (size <= allocated && size >= count) {
- size -= count;
- } else {
- return 0;
- }
- }
- break;
-
- default:
- break;
- }
-
- // Check allocated / size
- if (allocated != arr->allocated || size != arr->count) {
- diag("dynamic-array: allocated memory %d (expected %d)"
- " size %d (expected %d) mismatch",
- arr->allocated, allocated, arr->count, size);
- return 0;
- }
- }
-
- return 1;
-}
-
-void *test_da_read(void *obj)
-{
- rcu_register_thread();
- rcu_read_lock();
-
- unsigned seed = (unsigned)time(0);
- da_array_t *arr = (da_array_t *) obj;
- int index = rand_r(&seed) % da_get_count(arr);
-
- note(" dynamic-array: read thread");
- note(" read thread: saving pointer to %d. item", index);
- uint *item = &((uint *) da_get_items(arr))[index];
- note(" read thread: before: pointer: %p item: %u", item, *item);
-
- do_something(100000);
-
- note(" read thread after: pointer: %p item: %u", item, *item);
- rcu_read_unlock();
- note(" read thread unlocked: pointer: %p item: %u", item, *item);
-
- do_something(10000);
-
- note(" read thread: now the item should be deallocated");
- //note(" read thread: pointer: %p item: %u", item, *item);
-
- rcu_unregister_thread();
-
- return NULL;
-}
-
-static int test_da_resize_holding(da_array_t *arr)
-{
- int ret = 1;
- rcu_register_thread();
- pthread_t reader;
-
- // Create thread for reading
- note("dynamic-array: creating read threads");
- if (pthread_create(&reader, NULL, test_da_read, (void *)arr)) {
- diag("dynamic-array: failed to create reading thread",
- __func__);
- rcu_unregister_thread();
- return 0;
- }
-
- // Wait some time, so the other thread gets the item for reading
- do_something(5000);
-
- // Force resize
- note(" dynamic-array: array resized");
- if (da_reserve(arr, arr->allocated - arr->count + 1) == -1) {
- diag("dynamic-array: da_reserve(%p, %d) failed", arr,
- arr->allocated - arr->count + 1);
- ret = 0;
- }
-
- //Wait for the thread to finish
- void *pret = NULL;
- if (pthread_join(reader, &pret)) {
- diag("dynamic-array: failed to join reading thread",
- __func__);
- ret = 0;
- }
-
- rcu_unregister_thread();
- return ret;
-}
-
-static int test_da_resize(da_array_t *arr)
-{
- unsigned seed = (unsigned)time(0);
- int orig_count = da_get_count(arr);
- note("dynamic-array: allocated: %d, items: %d", arr->allocated,
- orig_count);
- // store the items currently in the array
- int *items = (int *)malloc(orig_count * sizeof(int));
- for (int i = 0; i < orig_count; ++i) {
- items[i] = ((int *)da_get_items(arr))[i];
- }
-
- // force resize
- int res = 0;
- while ((res = da_reserve(arr, 10)) == 0) {
- int i = da_get_count(arr);
- da_occupy(arr, 10);
- for (; i < da_get_count(arr); ++i) {
- ((int *)da_get_items(arr))[i] = rand_r(&seed);
- }
- }
-
- if (res < 0) {
- diag("dynamic-array: failed to reserve space");
- return 0;
- }
-
- int errors = 0;
- for (int i = 0; i < orig_count; ++i) {
- if (items[i] != ((int *)da_get_items(arr))[i]) {
- diag("dynamic-array: Wrong item on position %d."
- "Should be: %d, "
- "present value: %d", i, items[i],
- ((int *)da_get_items(arr))[i]);
- ++errors;
- }
- }
-
- free(items);
-
- return errors == 0;
-}
-
-static int da_tests_run(int argc, char *argv[])
-{
- // Init
- rcu_init();
- da_array_t array;
-
- // Test 1: test rcu
- ok(test_rcu_threads(), "dynamic-array: rcu tests");
-
- // Test 2: init
- ok(test_da_init(&array), "dynamic-array: init");
-
- // Test 3: reserve/occupy random operations
- ok(test_da_random_op(&array),
- "dynamic-array: randomized reserve/occupy/release");
-
- // Test 4: resizing array while holding an item
- ok(test_da_resize_holding(&array),
- "dynamic-array: resize array while holding an item");
-
- // Test 5: resize
- ok(test_da_resize(&array), "dynamic-array: resize array");
-
- // Cleanup
- da_destroy(&array);
- return 0;
-}
diff --git a/src/tests/common/events_tests.c b/src/tests/common/events_tests.c
index 0acd706..0acd706 100644..100755
--- a/src/tests/common/events_tests.c
+++ b/src/tests/common/events_tests.c
diff --git a/src/tests/common/events_tests.h b/src/tests/common/events_tests.h
index b54b6da..b54b6da 100644..100755
--- a/src/tests/common/events_tests.h
+++ b/src/tests/common/events_tests.h
diff --git a/src/tests/common/fdset_tests.c b/src/tests/common/fdset_tests.c
index 08e0577..08e0577 100644..100755
--- a/src/tests/common/fdset_tests.c
+++ b/src/tests/common/fdset_tests.c
diff --git a/src/tests/common/fdset_tests.h b/src/tests/common/fdset_tests.h
index d29e1a9..d29e1a9 100644..100755
--- a/src/tests/common/fdset_tests.h
+++ b/src/tests/common/fdset_tests.h
diff --git a/src/tests/common/skiplist_tests.c b/src/tests/common/skiplist_tests.c
index 4fe99ec..4fe99ec 100644..100755
--- a/src/tests/common/skiplist_tests.c
+++ b/src/tests/common/skiplist_tests.c
diff --git a/src/tests/common/skiplist_tests.h b/src/tests/common/skiplist_tests.h
index ff91706..ff91706 100644..100755
--- a/src/tests/common/skiplist_tests.h
+++ b/src/tests/common/skiplist_tests.h
diff --git a/src/tests/common/slab_tests.c b/src/tests/common/slab_tests.c
index f362ca0..5724a23 100644..100755
--- a/src/tests/common/slab_tests.c
+++ b/src/tests/common/slab_tests.c
@@ -23,6 +23,11 @@
#include "common/slab/slab.h"
#include "knot/common.h"
+/*! \brief Type-safe maximum macro. */
+#define SLAB_MAX(a, b) \
+ ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; })
+
+
/* Explicitly ask for symbols,
* as the constructor and destructor
* aren't created for test modules.
@@ -119,7 +124,7 @@ static int slab_tests_run(int argc, char *argv[])
for(int i = 0; i < alloc_count; ++i) {
double roll = rand() / (double) RAND_MAX;
size_t bsize = roll * 2048;
- bsize = MAX(bsize, 8);
+ bsize = SLAB_MAX(bsize, 8);
if ((ptrs_i == 0) || (roll < 0.6)) {
void* m = slab_alloc_alloc(&alloc, bsize);
if (m == 0) {
diff --git a/src/tests/common/slab_tests.h b/src/tests/common/slab_tests.h
index 4d45fb8..4d45fb8 100644..100755
--- a/src/tests/common/slab_tests.h
+++ b/src/tests/common/slab_tests.h
diff --git a/src/tests/files/sample_conf b/src/tests/files/sample_conf
index b15fce5..b15fce5 100644..100755
--- a/src/tests/files/sample_conf
+++ b/src/tests/files/sample_conf
diff --git a/src/tests/knot/conf_tests.c b/src/tests/knot/conf_tests.c
index 61520ea..61520ea 100644..100755
--- a/src/tests/knot/conf_tests.c
+++ b/src/tests/knot/conf_tests.c
diff --git a/src/tests/knot/conf_tests.h b/src/tests/knot/conf_tests.h
index dfd2fd7..dfd2fd7 100644..100755
--- a/src/tests/knot/conf_tests.h
+++ b/src/tests/knot/conf_tests.h
diff --git a/src/tests/knot/dthreads_tests.c b/src/tests/knot/dthreads_tests.c
index 982329b..982329b 100644..100755
--- a/src/tests/knot/dthreads_tests.c
+++ b/src/tests/knot/dthreads_tests.c
diff --git a/src/tests/knot/dthreads_tests.h b/src/tests/knot/dthreads_tests.h
index e41bdc5..e41bdc5 100644..100755
--- a/src/tests/knot/dthreads_tests.h
+++ b/src/tests/knot/dthreads_tests.h
diff --git a/src/tests/knot/journal_tests.c b/src/tests/knot/journal_tests.c
index 7c8125e..5c89de9 100644..100755
--- a/src/tests/knot/journal_tests.c
+++ b/src/tests/knot/journal_tests.c
@@ -34,7 +34,7 @@ unit_api journal_tests_api = {
/*
* Unit implementation.
*/
-static const int JOURNAL_TEST_COUNT = 20;
+static const int JOURNAL_TEST_COUNT = 21;
/*! \brief Generate random string with given length. */
static int randstr(char* dst, size_t len)
@@ -76,6 +76,7 @@ static int journal_tests_run(int argc, char *argv[])
int tmp_fd = mkstemp(jfn_buf);
ok(tmp_fd >= 0, "journal: create temporary file");
skip(tmp_fd < 0, JOURNAL_TEST_COUNT - 1);
+ close(tmp_fd);
/* Test 2: Create journal. */
const char *jfilename = jfn_buf;
@@ -139,7 +140,9 @@ static int journal_tests_run(int argc, char *argv[])
journal_close(journal);
/* Recreate journal = NORMAL mode. */
- remove(jfilename);
+ if (remove(jfilename) < 0) {
+ diag("journal: couldn't remove filename");
+ }
fsize = 8092;
jsize = 512;
ret = journal_create(jfilename, jsize);
@@ -199,7 +202,7 @@ static int journal_tests_run(int argc, char *argv[])
ok(j && ret == 0, "journal: mapped entry data integrity check");
endskip;
- /* Test 17: Make a transaction. */
+ /* Test 16: Make a transaction. */
uint64_t tskey = 0x75750000;
ret = journal_trans_begin(j);
ok(j && ret == 0, "journal: TRANS begin");
@@ -208,16 +211,16 @@ static int journal_tests_run(int argc, char *argv[])
journal_write(j, tskey + i, tmpbuf, sizeof(tmpbuf));
}
- /* Test 18: Check if uncommited node exists. */
+ /* 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 19: Commit transaction. */
+ /* 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 20: Rollback transaction. */
+ /* Test 19: Rollback transaction. */
tskey = 0x6B6B0000;
journal_trans_begin(j);
for (int i = 0; i < 16; ++i) {
@@ -228,7 +231,7 @@ static int journal_tests_run(int argc, char *argv[])
read_ret = journal_read(j, tskey + rand() % 16, NULL, chk_buf);
ok(j && ret == 0 && read_ret != 0, "journal: transaction rollback");
- /* Test 16: Write random data. */
+ /* Test 20: Write random data. */
ret = 0;
for (int i = 0; i < 512; ++i) {
int key = i;
@@ -258,16 +261,17 @@ static int journal_tests_run(int argc, char *argv[])
break;
}
}
-
- /* Test 16: Check data integrity. */
ok(j && ret == 0, "journal: sustained mmap r/w");
+ /* Test 21: Open + create journal. */
+ journal_close(j);
+ remove(jfilename);
+ j = journal_open(jfilename, fsize, 0, 0);
+ ok(j != NULL, "journal: open+create from scratch");
+
/* Close journal. */
journal_close(j);
- /* Close temporary file fd. */
- close(tmp_fd);
-
/* Delete journal. */
remove(jfilename);
diff --git a/src/tests/knot/journal_tests.h b/src/tests/knot/journal_tests.h
index beec8ca..beec8ca 100644..100755
--- a/src/tests/knot/journal_tests.h
+++ b/src/tests/knot/journal_tests.h
diff --git a/src/tests/knot/server_tests.c b/src/tests/knot/server_tests.c
index 5ae04d8..5ae04d8 100644..100755
--- a/src/tests/knot/server_tests.c
+++ b/src/tests/knot/server_tests.c
diff --git a/src/tests/knot/server_tests.h b/src/tests/knot/server_tests.h
index 43ad0c1..43ad0c1 100644..100755
--- a/src/tests/knot/server_tests.h
+++ b/src/tests/knot/server_tests.h
diff --git a/src/tests/libknot/files/parsed_data b/src/tests/libknot/files/parsed_data
index 4027c92..4027c92 100644..100755
--- a/src/tests/libknot/files/parsed_data
+++ b/src/tests/libknot/files/parsed_data
Binary files differ
diff --git a/src/tests/libknot/files/parsed_data_queries b/src/tests/libknot/files/parsed_data_queries
index 5857c87..5857c87 100644..100755
--- a/src/tests/libknot/files/parsed_data_queries
+++ b/src/tests/libknot/files/parsed_data_queries
Binary files differ
diff --git a/src/tests/libknot/files/raw_data b/src/tests/libknot/files/raw_data
index f94236b..f94236b 100644..100755
--- a/src/tests/libknot/files/raw_data
+++ b/src/tests/libknot/files/raw_data
Binary files differ
diff --git a/src/tests/libknot/files/raw_data_queries b/src/tests/libknot/files/raw_data_queries
index 9062d5a..9062d5a 100644..100755
--- a/src/tests/libknot/files/raw_data_queries
+++ b/src/tests/libknot/files/raw_data_queries
Binary files differ
diff --git a/src/tests/libknot/libknot/cuckoo_tests.c b/src/tests/libknot/libknot/cuckoo_tests.c
index c1306a3..8d22e36 100644..100755
--- a/src/tests/libknot/libknot/cuckoo_tests.c
+++ b/src/tests/libknot/libknot/cuckoo_tests.c
@@ -15,6 +15,7 @@
*/
#include <time.h>
#include <assert.h>
+#include <string.h>
#include "tests/libknot/libknot/cuckoo_tests.h"
diff --git a/src/tests/libknot/libknot/cuckoo_tests.h b/src/tests/libknot/libknot/cuckoo_tests.h
index b6b0db8..b6b0db8 100644..100755
--- a/src/tests/libknot/libknot/cuckoo_tests.h
+++ b/src/tests/libknot/libknot/cuckoo_tests.h
diff --git a/src/tests/libknot/libknot/dname_table_tests.c b/src/tests/libknot/libknot/dname_table_tests.c
index 0d00a44..0d00a44 100644..100755
--- a/src/tests/libknot/libknot/dname_table_tests.c
+++ b/src/tests/libknot/libknot/dname_table_tests.c
diff --git a/src/tests/libknot/libknot/dname_table_tests.h b/src/tests/libknot/libknot/dname_table_tests.h
index f3088e9..f3088e9 100644..100755
--- a/src/tests/libknot/libknot/dname_table_tests.h
+++ b/src/tests/libknot/libknot/dname_table_tests.h
diff --git a/src/tests/libknot/libknot/dname_tests.c b/src/tests/libknot/libknot/dname_tests.c
index 35ac230..35ac230 100644..100755
--- a/src/tests/libknot/libknot/dname_tests.c
+++ b/src/tests/libknot/libknot/dname_tests.c
diff --git a/src/tests/libknot/libknot/dname_tests.h b/src/tests/libknot/libknot/dname_tests.h
index a7d75aa..a7d75aa 100644..100755
--- a/src/tests/libknot/libknot/dname_tests.h
+++ b/src/tests/libknot/libknot/dname_tests.h
diff --git a/src/tests/libknot/libknot/edns_tests.c b/src/tests/libknot/libknot/edns_tests.c
index ac5d130..4d1a37a 100644..100755
--- a/src/tests/libknot/libknot/edns_tests.c
+++ b/src/tests/libknot/libknot/edns_tests.c
@@ -495,12 +495,13 @@ static int test_edns_has_option()
*/
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;
}
+
+ assert(edns->option_count == 0);
for (int j = 0; j < test_edns_data[i].option_count; j++) {
if (knot_edns_add_option(edns,
diff --git a/src/tests/libknot/libknot/edns_tests.h b/src/tests/libknot/libknot/edns_tests.h
index 4553234..4553234 100644..100755
--- a/src/tests/libknot/libknot/edns_tests.h
+++ b/src/tests/libknot/libknot/edns_tests.h
diff --git a/src/tests/libknot/libknot/node_tests.c b/src/tests/libknot/libknot/node_tests.c
index 10b01fa..b252982 100644..100755
--- a/src/tests/libknot/libknot/node_tests.c
+++ b/src/tests/libknot/libknot/node_tests.c
@@ -76,7 +76,7 @@ static int test_node_create()
errors++;
diag("Failed to create node structure");
}
- knot_node_free(&tmp, 0);
+ knot_node_free(&tmp);
}
return (errors == 0);
}
@@ -134,7 +134,7 @@ static int test_node_add_rrset()
diag("Values in found rrset are wrong");
}
- knot_node_free(&tmp, 0);
+ knot_node_free(&tmp);
}
return (errors == 0);
@@ -166,7 +166,7 @@ static int test_node_get_rrset()
diag("Failed to get proper rrset from node");
}
}
- knot_node_free(&nodes[i], 0);
+ knot_node_free(&nodes[i]);
}
return (errors == 0);
@@ -194,7 +194,7 @@ static int test_node_get_parent()
errors++;
diag("Failed to get proper parent from node");
}
- knot_node_free(&nodes[i], 0);
+ knot_node_free(&nodes[i]);
}
return (errors == 0);
}
@@ -230,7 +230,7 @@ static int test_node_sorting()
// last = *((uint16_t *)node->key);
// }
- knot_node_free(&tmp, 0);
+ knot_node_free(&tmp);
return (errors == 0);
}
@@ -244,7 +244,7 @@ static int test_node_delete()
tmp_node = knot_node_new(&test_nodes[i].owner,
test_nodes[i].parent, 0);
- knot_node_free(&tmp_node, 0);
+ knot_node_free(&tmp_node);
errors += (tmp_node != NULL);
}
@@ -269,9 +269,9 @@ static int test_node_set_parent()
diag("Parent node is wrongly set.");
errors++;
}
- knot_node_free(&tmp_node, 0);
+ knot_node_free(&tmp_node);
}
- knot_node_free(&tmp_parent, 0);
+ knot_node_free(&tmp_parent);
return (errors == 0);
}
@@ -289,7 +289,7 @@ static int test_node_free_rrsets()
// errors += (tmp_node->rrsets != NULL);
- knot_node_free(&tmp_node, 0);
+ knot_node_free(&tmp_node);
}
return (errors == 0);
}
diff --git a/src/tests/libknot/libknot/node_tests.h b/src/tests/libknot/libknot/node_tests.h
index a90179f..a90179f 100644..100755
--- a/src/tests/libknot/libknot/node_tests.h
+++ b/src/tests/libknot/libknot/node_tests.h
diff --git a/src/tests/libknot/libknot/nsec3_tests.c b/src/tests/libknot/libknot/nsec3_tests.c
index 7b95549..7b95549 100644..100755
--- a/src/tests/libknot/libknot/nsec3_tests.c
+++ b/src/tests/libknot/libknot/nsec3_tests.c
diff --git a/src/tests/libknot/libknot/nsec3_tests.h b/src/tests/libknot/libknot/nsec3_tests.h
index 10e7ed9..10e7ed9 100644..100755
--- a/src/tests/libknot/libknot/nsec3_tests.h
+++ b/src/tests/libknot/libknot/nsec3_tests.h
diff --git a/src/tests/libknot/libknot/packet_tests.c b/src/tests/libknot/libknot/packet_tests.c
index 916328d..916328d 100644..100755
--- a/src/tests/libknot/libknot/packet_tests.c
+++ b/src/tests/libknot/libknot/packet_tests.c
diff --git a/src/tests/libknot/libknot/packet_tests.h b/src/tests/libknot/libknot/packet_tests.h
index 5a8ce03..5a8ce03 100644..100755
--- a/src/tests/libknot/libknot/packet_tests.h
+++ b/src/tests/libknot/libknot/packet_tests.h
diff --git a/src/tests/libknot/libknot/query_tests.c b/src/tests/libknot/libknot/query_tests.c
index 1e4e081..1e4e081 100644..100755
--- a/src/tests/libknot/libknot/query_tests.c
+++ b/src/tests/libknot/libknot/query_tests.c
diff --git a/src/tests/libknot/libknot/query_tests.h b/src/tests/libknot/libknot/query_tests.h
index 037ecab..037ecab 100644..100755
--- a/src/tests/libknot/libknot/query_tests.h
+++ b/src/tests/libknot/libknot/query_tests.h
diff --git a/src/tests/libknot/libknot/rdata_tests.c b/src/tests/libknot/libknot/rdata_tests.c
index 0c53613..0c53613 100644..100755
--- a/src/tests/libknot/libknot/rdata_tests.c
+++ b/src/tests/libknot/libknot/rdata_tests.c
diff --git a/src/tests/libknot/libknot/rdata_tests.h b/src/tests/libknot/libknot/rdata_tests.h
index 1f43c91..1f43c91 100644..100755
--- a/src/tests/libknot/libknot/rdata_tests.h
+++ b/src/tests/libknot/libknot/rdata_tests.h
diff --git a/src/tests/libknot/libknot/response_tests.c b/src/tests/libknot/libknot/response_tests.c
index f40bb76..f40bb76 100644..100755
--- a/src/tests/libknot/libknot/response_tests.c
+++ b/src/tests/libknot/libknot/response_tests.c
diff --git a/src/tests/libknot/libknot/response_tests.h b/src/tests/libknot/libknot/response_tests.h
index c9a117b..c9a117b 100644..100755
--- a/src/tests/libknot/libknot/response_tests.h
+++ b/src/tests/libknot/libknot/response_tests.h
diff --git a/src/tests/libknot/libknot/rrset_tests.c b/src/tests/libknot/libknot/rrset_tests.c
index 41284df..41284df 100644..100755
--- a/src/tests/libknot/libknot/rrset_tests.c
+++ b/src/tests/libknot/libknot/rrset_tests.c
diff --git a/src/tests/libknot/libknot/rrset_tests.h b/src/tests/libknot/libknot/rrset_tests.h
index b0787d6..b0787d6 100644..100755
--- a/src/tests/libknot/libknot/rrset_tests.h
+++ b/src/tests/libknot/libknot/rrset_tests.h
diff --git a/src/tests/libknot/libknot/tsig_tests.c b/src/tests/libknot/libknot/tsig_tests.c
index e0a3d34..e0a3d34 100644..100755
--- a/src/tests/libknot/libknot/tsig_tests.c
+++ b/src/tests/libknot/libknot/tsig_tests.c
diff --git a/src/tests/libknot/libknot/tsig_tests.h b/src/tests/libknot/libknot/tsig_tests.h
index 8ea15f6..8ea15f6 100644..100755
--- a/src/tests/libknot/libknot/tsig_tests.h
+++ b/src/tests/libknot/libknot/tsig_tests.h
diff --git a/src/tests/libknot/libknot/zone_tests.c b/src/tests/libknot/libknot/zone_tests.c
index 72aae39..54cd38d 100644..100755
--- a/src/tests/libknot/libknot/zone_tests.c
+++ b/src/tests/libknot/libknot/zone_tests.c
@@ -95,13 +95,13 @@ static int test_zone_create(knot_zone_contents_t **zone)
if ((*zone) == NULL) {
diag("zone: Failed to create zone.");
- knot_node_free(&node, 0);
+ knot_node_free(&node);
return 0;
}
if ((*zone)->apex != node) {
diag("zone: Zone apex not set right.");
- knot_node_free(&node, 0);
+ knot_node_free(&node);
return 0;
}
@@ -133,7 +133,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
: 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, 0);
+ knot_node_free(&node);
++errors;
}
/* TODO check values in the node as well */
@@ -157,7 +157,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
KNOT_EBADZONE);
++errors;
}
- knot_node_free(&node, 0);
+ knot_node_free(&node);
}
//note("NULL zone");
@@ -179,7 +179,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
++errors;
}
- knot_node_free(&node, 0);
+ knot_node_free(&node);
//note("NULL node");
note("Inserting NULL node...\n");
@@ -211,7 +211,7 @@ static int test_zone_add_node(knot_zone_contents_t *zone, int nsec3)
++errors;
}
- knot_node_free(&node, 0);
+ knot_node_free(&node);
}
// check if all nodes are inserted
diff --git a/src/tests/libknot/libknot/zone_tests.h b/src/tests/libknot/libknot/zone_tests.h
index 5539709..5539709 100644..100755
--- a/src/tests/libknot/libknot/zone_tests.h
+++ b/src/tests/libknot/libknot/zone_tests.h
diff --git a/src/tests/libknot/libknot/zone_tree_tests.c b/src/tests/libknot/libknot/zone_tree_tests.c
index 207afea..207afea 100644..100755
--- a/src/tests/libknot/libknot/zone_tree_tests.c
+++ b/src/tests/libknot/libknot/zone_tree_tests.c
diff --git a/src/tests/libknot/libknot/zone_tree_tests.h b/src/tests/libknot/libknot/zone_tree_tests.h
index 4cea88c..4cea88c 100644..100755
--- a/src/tests/libknot/libknot/zone_tree_tests.h
+++ b/src/tests/libknot/libknot/zone_tree_tests.h
diff --git a/src/tests/libknot/libknot/zonedb_tests.c b/src/tests/libknot/libknot/zonedb_tests.c
index 7b45587..7b45587 100644..100755
--- a/src/tests/libknot/libknot/zonedb_tests.c
+++ b/src/tests/libknot/libknot/zonedb_tests.c
diff --git a/src/tests/libknot/libknot/zonedb_tests.h b/src/tests/libknot/libknot/zonedb_tests.h
index 0c4f8ef..0c4f8ef 100644..100755
--- a/src/tests/libknot/libknot/zonedb_tests.h
+++ b/src/tests/libknot/libknot/zonedb_tests.h
diff --git a/src/tests/libknot/realdata/files/parsed_data b/src/tests/libknot/realdata/files/parsed_data
index fe22b90..fe22b90 100644..100755
--- a/src/tests/libknot/realdata/files/parsed_data
+++ b/src/tests/libknot/realdata/files/parsed_data
Binary files differ
diff --git a/src/tests/libknot/realdata/files/parsed_data_queries b/src/tests/libknot/realdata/files/parsed_data_queries
index 5857c87..5857c87 100644..100755
--- a/src/tests/libknot/realdata/files/parsed_data_queries
+++ b/src/tests/libknot/realdata/files/parsed_data_queries
Binary files differ
diff --git a/src/tests/libknot/realdata/files/raw_data b/src/tests/libknot/realdata/files/raw_data
index 502005e..502005e 100644..100755
--- a/src/tests/libknot/realdata/files/raw_data
+++ b/src/tests/libknot/realdata/files/raw_data
Binary files differ
diff --git a/src/tests/libknot/realdata/files/raw_data_queries b/src/tests/libknot/realdata/files/raw_data_queries
index 9062d5a..9062d5a 100644..100755
--- a/src/tests/libknot/realdata/files/raw_data_queries
+++ b/src/tests/libknot/realdata/files/raw_data_queries
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
index d0216c7..d0216c7 100644..100755
--- a/src/tests/libknot/realdata/libknot/dname_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/dname_tests_realdata.c
diff --git a/src/tests/libknot/realdata/libknot/dname_tests_realdata.h b/src/tests/libknot/realdata/libknot/dname_tests_realdata.h
index a7d75aa..a7d75aa 100644..100755
--- a/src/tests/libknot/realdata/libknot/dname_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/dname_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/edns_tests_realdata.c b/src/tests/libknot/realdata/libknot/edns_tests_realdata.c
index 257d480..257d480 100644..100755
--- a/src/tests/libknot/realdata/libknot/edns_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/edns_tests_realdata.c
diff --git a/src/tests/libknot/realdata/libknot/edns_tests_realdata.h b/src/tests/libknot/realdata/libknot/edns_tests_realdata.h
index cfa64b0..cfa64b0 100644..100755
--- a/src/tests/libknot/realdata/libknot/edns_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/edns_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/node_tests_realdata.c b/src/tests/libknot/realdata/libknot/node_tests_realdata.c
index b9415ef..91209c9 100644..100755
--- a/src/tests/libknot/realdata/libknot/node_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/node_tests_realdata.c
@@ -94,7 +94,7 @@ static int test_node_create(const list *node_list)
errors++;
diag("Failed to create node structure");
}
- knot_node_free(&tmp, 0);
+ knot_node_free(&tmp);
}
return (errors == 0);
@@ -168,7 +168,7 @@ static int test_node_add_rrset(list *rrset_list)
diag("Values in found rrset are wrong");
}
- knot_node_free(&tmp, 0);
+ knot_node_free(&tmp);
}
return (errors == 0);
diff --git a/src/tests/libknot/realdata/libknot/node_tests_realdata.h b/src/tests/libknot/realdata/libknot/node_tests_realdata.h
index a90179f..a90179f 100644..100755
--- a/src/tests/libknot/realdata/libknot/node_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/node_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/packet_tests_realdata.c b/src/tests/libknot/realdata/libknot/packet_tests_realdata.c
index 08c0882..08c0882 100644..100755
--- a/src/tests/libknot/realdata/libknot/packet_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/packet_tests_realdata.c
diff --git a/src/tests/libknot/realdata/libknot/packet_tests_realdata.h b/src/tests/libknot/realdata/libknot/packet_tests_realdata.h
index c0e0479..c0e0479 100644..100755
--- a/src/tests/libknot/realdata/libknot/packet_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/packet_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.c b/src/tests/libknot/realdata/libknot/rdata_tests_realdata.c
index f4ba64c..f4ba64c 100644..100755
--- a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/rdata_tests_realdata.c
diff --git a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.h b/src/tests/libknot/realdata/libknot/rdata_tests_realdata.h
index 570b2b1..570b2b1 100644..100755
--- a/src/tests/libknot/realdata/libknot/rdata_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/rdata_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/response_tests_realdata.c b/src/tests/libknot/realdata/libknot/response_tests_realdata.c
index 7dac341..7dac341 100644..100755
--- a/src/tests/libknot/realdata/libknot/response_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/response_tests_realdata.c
diff --git a/src/tests/libknot/realdata/libknot/response_tests_realdata.h b/src/tests/libknot/realdata/libknot/response_tests_realdata.h
index 731604b..731604b 100644..100755
--- a/src/tests/libknot/realdata/libknot/response_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/response_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.c b/src/tests/libknot/realdata/libknot/rrset_tests_realdata.c
index cb59f4c..cb59f4c 100644..100755
--- a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/rrset_tests_realdata.c
diff --git a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.h b/src/tests/libknot/realdata/libknot/rrset_tests_realdata.h
index cc3b705..cc3b705 100644..100755
--- a/src/tests/libknot/realdata/libknot/rrset_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/rrset_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/zone_tests_realdata.c b/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
index 2738dab..4687978 100644..100755
--- a/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/zone_tests_realdata.c
@@ -77,7 +77,7 @@ static int test_zone_create(list node_list)
errors++;
}
knot_node_free_rrsets(node, 1);
- knot_node_free(&node, 0);
+ knot_node_free(&node);
}
return (errors == 0);
diff --git a/src/tests/libknot/realdata/libknot/zone_tests_realdata.h b/src/tests/libknot/realdata/libknot/zone_tests_realdata.h
index 5539709..5539709 100644..100755
--- a/src/tests/libknot/realdata/libknot/zone_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/zone_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c b/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c
index 96d1517..96d1517 100644..100755
--- a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c
+++ b/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.c
diff --git a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h b/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h
index 0c4f8ef..0c4f8ef 100644..100755
--- a/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h
+++ b/src/tests/libknot/realdata/libknot/zonedb_tests_realdata.h
diff --git a/src/tests/libknot/realdata/libknot_tests_loader_realdata.c b/src/tests/libknot/realdata/libknot_tests_loader_realdata.c
index e972855..e972855 100644..100755
--- a/src/tests/libknot/realdata/libknot_tests_loader_realdata.c
+++ b/src/tests/libknot/realdata/libknot_tests_loader_realdata.c
diff --git a/src/tests/libknot/realdata/libknot_tests_loader_realdata.h b/src/tests/libknot/realdata/libknot_tests_loader_realdata.h
index 8f57944..8f57944 100644..100755
--- a/src/tests/libknot/realdata/libknot_tests_loader_realdata.h
+++ b/src/tests/libknot/realdata/libknot_tests_loader_realdata.h
diff --git a/src/tests/libknot/realdata/unittests_libknot_realdata.c b/src/tests/libknot/realdata/unittests_libknot_realdata.c
index e557c43..e557c43 100644..100755
--- a/src/tests/libknot/realdata/unittests_libknot_realdata.c
+++ b/src/tests/libknot/realdata/unittests_libknot_realdata.c
diff --git a/src/tests/libknot/unittests_libknot.c b/src/tests/libknot/unittests_libknot.c
index d522e1d..d522e1d 100644..100755
--- a/src/tests/libknot/unittests_libknot.c
+++ b/src/tests/libknot/unittests_libknot.c
diff --git a/src/tests/unittests_main.c b/src/tests/unittests_main.c
index 1ec336a..21eae14 100644..100755
--- a/src/tests/unittests_main.c
+++ b/src/tests/unittests_main.c
@@ -22,7 +22,6 @@
#include "tests/common/slab_tests.h"
#include "tests/common/skiplist_tests.h"
#include "tests/common/events_tests.h"
-#include "tests/common/da_tests.h"
#include "tests/common/acl_tests.h"
#include "tests/common/fdset_tests.h"
#include "tests/knot/dthreads_tests.h"
@@ -47,7 +46,6 @@ int main(int argc, char *argv[])
&skiplist_tests_api, //! Skip list unit
&dthreads_tests_api, //! DThreads testing unit
&events_tests_api, //! Events testing unit
- &da_tests_api, //! Dynamic array unit
&acl_tests_api, //! ACLs
&fdset_tests_api, //! FDSET polling wrapper
diff --git a/src/tests/xfr_tests.c b/src/tests/xfr_tests.c
index 5017109..b78678b 100644..100755
--- a/src/tests/xfr_tests.c
+++ b/src/tests/xfr_tests.c
@@ -172,11 +172,11 @@ int main(int argc, char **argv)
server_t *server = server_create();
// Initialize configuration
- conf_read_lock();
+ rcu_read_lock();
conf_add_hook(conf(), CONF_LOG, log_conf_hook, 0);
conf_add_hook(conf(), CONF_LOG, zones_ns_conf_hook, server->nameserver);
conf_add_hook(conf(), CONF_LOG, server_conf_hook, server);
- conf_read_unlock();
+ rcu_read_unlock();
// Find implicit configuration file
if (!config_fn) {
@@ -215,7 +215,7 @@ int main(int argc, char **argv)
log_server_error("Couldn't open configuration file "
"'%s'.\n", config_fn);
} else {
- log_server_error("Failed to parse configuration '%s'.\n",
+ log_server_error("Failed to load configuration '%s'.\n",
config_fn);
}
server_destroy(&server);
diff --git a/src/tests/xfr_tests.h b/src/tests/xfr_tests.h
index 29de11d..29de11d 100644..100755
--- a/src/tests/xfr_tests.h
+++ b/src/tests/xfr_tests.h
diff --git a/src/zcompile/LICENSE b/src/zcompile/LICENSE
index 55faacf..55faacf 100644..100755
--- a/src/zcompile/LICENSE
+++ b/src/zcompile/LICENSE
diff --git a/src/zcompile/parser-descriptor.c b/src/zcompile/parser-descriptor.c
index b876877..bc3ee16 100644..100755
--- a/src/zcompile/parser-descriptor.c
+++ b/src/zcompile/parser-descriptor.c
@@ -539,3 +539,4 @@ uint16_t parser_rrclass_from_string(const char *name)
return (uint16_t) rrclass;
}
+/*! @} */
diff --git a/src/zcompile/parser-descriptor.h b/src/zcompile/parser-descriptor.h
index 48c6f02..48c6f02 100644..100755
--- a/src/zcompile/parser-descriptor.h
+++ b/src/zcompile/parser-descriptor.h
diff --git a/src/zcompile/parser-util.c b/src/zcompile/parser-util.c
index cfbc624..955a7b0 100644..100755
--- a/src/zcompile/parser-util.c
+++ b/src/zcompile/parser-util.c
@@ -1128,25 +1128,32 @@ static ssize_t rdata_wireformat_to_rdata_atoms(const uint16_t *wireformat,
// break;
case KNOT_RDATA_WF_IPSECGATEWAY:
dbg_rdata("Parsed item is an IPSECGATEWAY address.\n");
- switch (rdata_atom_data(temp_rdatas[1])[0]) {
+ 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 */
- default:
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;
- }
-
- break;
+ default:
+ dbg_rdata("Unknown IPSECKEY gateway!\n");
+ free(temp_rdatas);
+ return -1;
+ } // switch
}
if (is_domain) {
@@ -2473,3 +2480,4 @@ void set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE],
bits[window][bit / 8] |= (1 << (7 - bit % 8));
}
+/*! @} */
diff --git a/src/zcompile/parser-util.h b/src/zcompile/parser-util.h
index 57258dc..57258dc 100644..100755
--- a/src/zcompile/parser-util.h
+++ b/src/zcompile/parser-util.h
diff --git a/src/zcompile/tests/unittests_zp_main.c b/src/zcompile/tests/unittests_zp_main.c
index 5d8c5e9..5d8c5e9 100644..100755
--- a/src/zcompile/tests/unittests_zp_main.c
+++ b/src/zcompile/tests/unittests_zp_main.c
diff --git a/src/zcompile/tests/zcompile_tests.c b/src/zcompile/tests/zcompile_tests.c
index 5d3dce6..5d3dce6 100644..100755
--- a/src/zcompile/tests/zcompile_tests.c
+++ b/src/zcompile/tests/zcompile_tests.c
diff --git a/src/zcompile/zcompile-error.c b/src/zcompile/zcompile-error.c
index 9357cde..9357cde 100644..100755
--- a/src/zcompile/zcompile-error.c
+++ b/src/zcompile/zcompile-error.c
diff --git a/src/zcompile/zcompile-error.h b/src/zcompile/zcompile-error.h
index c6d999c..c6d999c 100644..100755
--- a/src/zcompile/zcompile-error.h
+++ b/src/zcompile/zcompile-error.h
diff --git a/src/zcompile/zcompile.c b/src/zcompile/zcompile.c
index c4415d4..e2f05e3 100644..100755
--- a/src/zcompile/zcompile.c
+++ b/src/zcompile/zcompile.c
@@ -42,6 +42,7 @@
#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"
@@ -111,69 +112,6 @@ static void rrset_list_delete(rrset_list_t **head)
dbg_zp("zp: list_delete: List deleleted.\n");
}
-static int find_rrset_for_rrsig_in_zone(knot_zone_contents_t *zone,
- knot_rrset_t *rrsig)
-{
- assert(rrsig != NULL);
- assert(rrsig->rdata->items[0].raw_data);
-
- knot_node_t *tmp_node = NULL;
-
- if (knot_rdata_rrsig_type_covered(knot_rrset_rdata(rrsig))
- != KNOT_RRTYPE_NSEC3) {
- tmp_node = knot_zone_contents_get_node(zone, rrsig->owner);
- } else {
- tmp_node = knot_zone_contents_get_nsec3_node(zone,
- rrsig->owner);
- }
-
- dbg_zp_verb("zp: find_rr_for_sig: Found this node for RRSIG: %p.\n",
- tmp_node);
-
- if (tmp_node == NULL) {
- dbg_zp("zp: find_rr_for_sig: There is no node for this RR.\n");
- return KNOTDZCOMPILE_EINVAL;
- }
-
- knot_rrset_t *tmp_rrset =
- knot_node_get_rrset(tmp_node,
- knot_rdata_rrsig_type_covered(
- rrsig->rdata));
-
- dbg_zp_verb("zp: find_rr_for_sig: Found this RRSet for RRSIG: %p.\n",
- tmp_rrset);
-
- if (tmp_rrset == NULL) {
- dbg_zp("zp: find_rr_for_sig: There is no RRSet "
- "for this RRSIG.\n");
- return KNOTDZCOMPILE_EINVAL;
- }
-
-
- if (tmp_rrset->rrsigs != NULL) {
- int ret = knot_zone_contents_add_rrsigs(zone, rrsig,
- &tmp_rrset, &tmp_node,
- KNOT_RRSET_DUPL_MERGE, 1);
- if (ret != KNOT_EOK) {
- dbg_zp("zp: find_rr_for_sig: Cannot add RRSIG.\n");
- return ret;
- }
- knot_rrset_free(&rrsig);
- } else {
- int ret = knot_zone_contents_add_rrsigs(zone, rrsig,
- &tmp_rrset, &tmp_node,
- KNOT_RRSET_DUPL_SKIP, 1);
- if (ret != KNOT_EOK) {
- dbg_zp("zp: find_rr_for_sig: Cannot add RRSIG.\n");
- return ret;
- }
- }
-
- dbg_zp("zp: find_rr_for_sig: Found node: %p found rrset: %p.\n",
- tmo_node, tmp_rrset);
- return KNOTDZCOMPILE_EOK;
-}
-
static int find_rrset_for_rrsig_in_node(knot_zone_contents_t *zone,
knot_node_t *node,
knot_rrset_t *rrsig)
@@ -187,28 +125,51 @@ static int find_rrset_for_rrsig_in_node(knot_zone_contents_t *zone,
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)));
- return KNOTDZCOMPILE_EINVAL;
- }
+ 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;
+ }
- if (tmp_rrset->rrsigs != NULL) {
- if (knot_zone_contents_add_rrsigs(zone, rrsig,
- &tmp_rrset, &node,
- KNOT_RRSET_DUPL_MERGE, 1) < 0) {
- dbg_zp("zp: find_rr_for_sig: Cannot add RRSIG.\n");
- return KNOTDZCOMPILE_EINVAL;
+ 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);
- } else {
- if (knot_zone_contents_add_rrsigs(zone, rrsig,
- &tmp_rrset, &node,
- KNOT_RRSET_DUPL_SKIP, 1) < 0) {
- dbg_zp("zp: find_rr_for_sig: Cannot add RRSIG.\n");
- return KNOTDZCOMPILE_EINVAL;
- }
}
assert(tmp_rrset->rrsigs != NULL);
@@ -244,10 +205,9 @@ static void process_rrsigs_in_node(knot_zone_contents_t *zone,
rrset_list_t *tmp = parser->node_rrsigs;
while (tmp != NULL) {
if (find_rrset_for_rrsig_in_node(zone, node,
- tmp->data) != 0) {
- rrset_list_add(&parser->rrsig_orphans,
- tmp->data);
- parser->rrsig_orphan_count++;
+ tmp->data) != KNOT_EOK) {
+ zc_error_prev_line("Could not add RRSIG to zone!\n");
+ return;
}
tmp = tmp->next;
}
@@ -279,6 +239,7 @@ dbg_zp_exec_detail(
assert(current_rrset->rdata->count == descriptor->length);
}
+
assert(current_rrset->rdata->count > 0);
assert(knot_dname_is_fqdn(current_rrset->owner));
@@ -336,6 +297,7 @@ dbg_zp_exec_detail(
}
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,
@@ -458,11 +420,10 @@ dbg_zp_exec_detail(
"add RDATA to RRSet.\n");
return KNOTDZCOMPILE_EBRDATA;
}
-
- /* I chose skip, but there should not really be
- * any rrset to skip */
+
+ /* Selected merge option does not really matter here. */
if (knot_zone_contents_add_rrset(contents, rrset, &node,
- KNOT_RRSET_DUPL_SKIP, 1) < 0) {
+ KNOT_RRSET_DUPL_MERGE, 1) < 0) {
knot_rrset_free(&rrset);
dbg_zp("zp: process_rr: Cannot "
"add RDATA to RRSet.\n");
@@ -472,8 +433,9 @@ dbg_zp_exec_detail(
if (current_rrset->type !=
KNOT_RRTYPE_RRSIG && rrset->ttl !=
current_rrset->ttl) {
- zc_error_prev_line(
- "TTL does not match the TTL of the RRSet");
+ 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,
@@ -497,31 +459,6 @@ dbg_zp_exec_detail(
return KNOTDZCOMPILE_EOK;
}
-static uint find_rrsets_orphans(knot_zone_contents_t *zone, rrset_list_t
- *head)
-{
- uint found_rrsets = 0;
- while (head != NULL) {
- if (find_rrset_for_rrsig_in_zone(zone, head->data) == 0) {
- found_rrsets += 1;
- dbg_zp("zp: find_orphans: "
- "RRSet succesfully found: owner %s type %s\n",
- knot_dname_to_str(head->data->owner),
- knot_rrtype_to_string(head->data->type));
- }
- else { /* we can throw it away now */
- dbg_zp("zp: find_orphans: "
- "RRSet not found for RRSIG: %s (%s)\n",
- knot_dname_to_str(head->data->owner),
- knot_rrtype_to_string(
- knot_rdata_rrsig_type_covered(head->data->rdata)));
- knot_rrset_free(&head->data);
- }
- head = head->next;
- }
- return found_rrsets;
-}
-
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)
{
@@ -549,19 +486,23 @@ static int zone_open(const char *filename, uint32_t ttl, uint16_t rclass,
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. */
- if (outfile != NULL) {
- FILE *f = fopen(outfile, "wb");
- if (f == NULL) {
- fprintf(stderr, "Cannot write zone db to file '%s' (%s).\n",
- outfile, strerror(errno));
- return KNOTDZCOMPILE_EINVAL;
- }
- fclose(f);
+ 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);
@@ -570,7 +511,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
}
if (!knot_dname_is_fqdn(dname)) {
- fprintf(stderr, "Error: given zone origin is not FQDN.\n");
+ log_zone_error("Error: given zone origin is not FQDN.\n");
knot_dname_release(dname);
return KNOTDZCOMPILE_EINVAL;
}
@@ -587,7 +528,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
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, 0);
+ knot_node_free(&origin_node);
return KNOTDZCOMPILE_ENOMEM;
}
@@ -595,7 +536,7 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
zp_lex_init(&scanner);
if (scanner == NULL) {
knot_dname_release(origin_from_config);
- knot_node_free(&origin_node, 0);
+ knot_node_free(&origin_node);
return KNOTDZCOMPILE_ENOMEM;
}
@@ -608,25 +549,55 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
// 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) {
- /*!< \todo #1676 Implement proper locking. */
+ log_zone_error("Parse failed.\n");
FILE *in_file = (FILE *)zp_get_in(scanner);
fclose(in_file);
- zp_lex_destroy(scanner);
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);
-
- /*!< \todo #1676 Implement proper locking. */
dbg_zp("zp: zone_read: Parse complete for %s.\n",
zonefile);
@@ -650,31 +621,20 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
return KNOTDZCOMPILE_EZONEINVAL;
}
- uint found_orphans;
- found_orphans = find_rrsets_orphans(contents,
- parser->rrsig_orphans);
-
- dbg_zp("zp: zone_read: %u RRSIG orphans found.\n", found_orphans);
-
- rrset_list_delete(&parser->rrsig_orphans);
-
- if (found_orphans != parser->rrsig_orphan_count) {
- /*! \todo This might be desired behaviour. */
- fprintf(stderr,
- "There are unassigned RRSIGs in the zone!\n");
+ 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++;
}
-
- /*! \todo Check return value. */
- knot_zone_contents_adjust(contents);
-
+
dbg_zp("zp: zone_read: Zone adjusted.\n");
if (parser->errors != 0) {
- log_zone_error("Parser finished with %d error(s)%s\n",
- parser->errors, outfile == NULL ?
- "." : ", not dumping the zone!");
- } else if (outfile != NULL) {
+ 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",
@@ -688,7 +648,10 @@ int zone_read(const char *name, const char *zonefile, const char *outfile,
if (ret != KNOT_EOK) {
log_zone_error("Could not dump zone, reason: "
"%s.\n", knot_strerror(ret));
- remove(outfile);
+ if (remove(outfile) != 0) {
+ log_zone_error("Could not remove "
+ "db file!\n");
+ }
totalerrors++;
} else {
/* Write CRC file. */
diff --git a/src/zcompile/zcompile.h b/src/zcompile/zcompile.h
index 37b3791..d19ef4c 100644..100755
--- a/src/zcompile/zcompile.h
+++ b/src/zcompile/zcompile.h
@@ -131,18 +131,11 @@ struct zparser {
knot_rrset_t *current_rrset; /*!< Current RRSet. */
knot_rdata_item_t *temporary_items; /*!< Temporary rdata items. */
- /*!
- * \brief list of RRSIGs that were not inside their nodes in zone file
- */
- rrset_list_t *rrsig_orphans;
- unsigned long rrsig_orphan_count; /*!< RRSIG orphan count */
-
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. */
- int origin_directive; /*!< Set to 1 if $ORIGIN directive is present. */
};
typedef struct zparser zparser_type;
diff --git a/src/zcompile/zcompile_main.c b/src/zcompile/zcompile_main.c
index c84515e..983376a 100644..100755
--- a/src/zcompile/zcompile_main.c
+++ b/src/zcompile/zcompile_main.c
@@ -26,7 +26,7 @@ static void help(int argc, char **argv)
{
printf("Usage: %s [parameters] origin zonefile\n",
argv[0]);
- printf("Parameters:\n"
+ printf("\n:Parameters:\n"
" -o <outfile> Override output file.\n"
" -v Verbose mode - additional runtime information.\n"
" -s Enable semantic checks.\n"
@@ -114,7 +114,6 @@ int main(int argc, char **argv)
} else {
log_zone_info("Zone file for '%s' is OK.\n", origin);
}
- //log_close();
return 0;
}
diff --git a/src/zcompile/zlexer.l b/src/zcompile/zlexer.l
index 58e6439..58e6439 100644..100755
--- a/src/zcompile/zlexer.l
+++ b/src/zcompile/zlexer.l
diff --git a/src/zcompile/zparser.y b/src/zcompile/zparser.y
index 89af437..c35060e 100644..100755
--- a/src/zcompile/zparser.y
+++ b/src/zcompile/zparser.y
@@ -314,7 +314,6 @@ origin_directive: DOLLAR_ORIGIN sp abs_dname trail
// knot_node_free(&parser->origin, 1);
}
parser->origin = origin_node;
- parser->origin_directive = 1;
}
| DOLLAR_ORIGIN sp rel_dname trail
{
@@ -406,12 +405,8 @@ abs_dname: '.'
}
| '@'
{
- if (parser->origin_directive) {
- $$ = parser->origin->owner;
- } else {
- zc_error("@ used, but no $ORIGIN specified.\n");
- $$ = parser->origin->owner;
- }
+ assert(parser->origin != NULL);
+ $$ = parser->origin->owner;
}
| rel_dname '.'
{
@@ -1267,13 +1262,13 @@ rdata_apl: rdata_apl_seq trail
rdata_apl_seq: dotted_str
{
- zadd_rdata_wireformat(zparser_conv_apl_rdata($1.str));
+ zadd_rdata_txt_wireformat(zparser_conv_apl_rdata($1.str), 1);
free($1.str);
}
| rdata_apl_seq sp dotted_str
{
- zadd_rdata_wireformat(zparser_conv_apl_rdata($3.str));
+ zadd_rdata_txt_wireformat(zparser_conv_apl_rdata($3.str), 0);
free($3.str);
}
@@ -1637,13 +1632,9 @@ zparser_init(const char *filename, uint32_t ttl, uint16_t rclass,
parser->current_zone = knot_zone_new(origin, 0, 1);
parser->node_rrsigs = NULL;
- parser->rrsig_orphans = NULL;
- parser->rrsig_orphan_count = 0;
parser->current_rrset->rclass = parser->default_class;
parser->current_rrset->rdata = NULL;
-
- parser->origin_directive = 0;
}